LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Ipw2100-admin] [BUILD FAILURE 04/12] Next April 14 : PPC64 randconfig [drivers/staging/built-in.o]
From: Greg KH @ 2009-04-15  1:06 UTC (permalink / raw)
  To: reinette chatre
  Cc: sachinp, Stephen Rothwell, Andrea Merello, linux-kernel,
	Rafael J. Wysocki, Linuxppc-dev, linux-next,
	subrata@linux.vnet.ibm.com, Alexander Beregalov,
	James P. Ketrenos
In-Reply-To: <1239735595.15115.60.camel@rc-desk>

On Tue, Apr 14, 2009 at 11:59:55AM -0700, reinette chatre wrote:
> Hi Subrata,
> 
> On Tue, 2009-04-14 at 11:28 -0700, Subrata Modak wrote:
> > Observed the following build error:
> > ---
> > LD      drivers/built-in.o
> > drivers/staging/built-in.o: In function `ieee80211_xmit':
> > drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c:528: multiple
> > definition of `ieee80211_xmit'
> > drivers/net/built-in.o:drivers/net/wireless/ipw2x00/libipw_tx.c:256:
> > first defined here
> > make[1]: *** [drivers/built-in.o] Error 1
> > make: *** [drivers] Error 2
> 
> Looks like the rtl8187se driver started with a copy of ipw2x00's
> library. Errors like this can thus be expected and should be addressed
> by rtl8187se as they are the ones who made the copy.

Yes, at this point in time, don't build the staging drivers into the
kernel, it's not advised at all.

thanks,

greg k-h

^ permalink raw reply

* [PATCH v2] powerpc: pseries/dtl.c should include asm/firmware.h
From: Jeremy Kerr @ 2009-04-15  0:35 UTC (permalink / raw)
  To: linuxppc-dev, linux-next, Paul Mackerras
  Cc: Stephen Rothwell, Michael Neuling, Subrata Modak
In-Reply-To: <<49D3419E.7000005@in.ibm.com>

From: Sachin Sant <sachinp@in.ibm.com>

A randconfig build on powerpc failed with:

dtl.c: In function 'dtl_init':
dtl.c:238: error: implicit declaration of function 'firmware_has_feature'
dtl.c:238: error: 'FW_FEATURE_SPLPAR' undeclared (first use in this function)

- We need firmware.h for these definitions.

Signed-off-by: Sachin Sant <sachinp@in.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---
v2: This time without the non-ascii quotes

---
 arch/powerpc/platforms/pseries/dtl.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index fafcaa0..ab69925 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -25,6 +25,7 @@
 #include <asm/smp.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/firmware.h>
 
 #include "plpar_wrappers.h"
 

^ permalink raw reply related

* [PATCH] powerpc: pseries/dtl.c should include asm/firmware.h
From: Jeremy Kerr @ 2009-04-14 23:45 UTC (permalink / raw)
  To: linuxppc-dev, linux-next, Paul Mackerras
  Cc: Stephen Rothwell, Michael Neuling, Subrata Modak
In-Reply-To: <<49D3419E.7000005@in.ibm.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="us-ascii", Size: 857 bytes --]

From: Sachin Sant <sachinp@in.ibm.com>

A randconfig build on powerpc failed with:

dtl.c: In function ‘dtl_init’:
dtl.c:238: error: implicit declaration of function ‘firmware_has_feature’
dtl.c:238: error: ‘FW_FEATURE_SPLPAR’ undeclared (first use in this function)

- We need firmware.h for these definitions.

Signed-off-by: Sachin Sant <sachinp@in.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---
 arch/powerpc/platforms/pseries/dtl.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index fafcaa0..ab69925 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -25,6 +25,7 @@
 #include <asm/smp.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/firmware.h>
 
 #include "plpar_wrappers.h"
 

^ permalink raw reply related

* [PATCH 2.6.30] fsl_devices.h: Bring the legacy fsl_spi_platform_data hooks back
From: Anton Vorontsov @ 2009-04-14 23:39 UTC (permalink / raw)
  To: Grant Likely
  Cc: sachinp, Stephen Rothwell, David Brownell, Greg KH, linux-kernel,
	Rafael J. Wysocki, Linuxppc-dev, linux-next, Paul Mackerras,
	subrata, Alexander Beregalov
In-Reply-To: <fa686aa40904141603u6b533fcfs401e09b718d35ed3@mail.gmail.com>

In commit 364fdbc00fbdd409ade63500710123fe323aa164 ("spi_mpc83xx:
rework chip selects handling"), I merged activate_cs and deactivate_cs
hooks into cs_control, but I overlooked that mpc52xx_psc_spi driver
is using these hooks too. And that resulted in the following build
failure:

CC      drivers/spi/mpc52xx_psc_spi.o
drivers/spi/mpc52xx_psc_spi.c: In function 'mpc52xx_psc_spi_do_probe':
drivers/spi/mpc52xx_psc_spi.c:398: error: 'struct fsl_spi_platform_data'
has no member named 'activate_cs'
drivers/spi/mpc52xx_psc_spi.c:399: error: 'struct fsl_spi_platform_data'
has no member named 'deactivate_cs'
make[2]: *** [drivers/spi/mpc52xx_psc_spi.o] Error 1

This patch simply adds the legacy hooks back for 2.6.30, and for
2.6.31 we'll convert the driver to ->cs_control.

Reported-by: Subrata Modak <subrata@linux.vnet.ibm.com>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---

On Tue, Apr 14, 2009 at 05:03:52PM -0600, Grant Likely wrote:
[...]
> > Hm. struct fsl_spi_platform_data is still there. It's just there
> > is no two functions (activate_cs and deactivate_cs) any longer,
> > there's just one: cs_ontrol that takes "spi_device" and "on"
> > arguments).
> >
> > And the build fix (down below) is trivial.
> 
> Regardless of how trivial the build fix is for in-tree, I'm not
> thrilled with breaking out of tree users.  I don't bend over backwards
> for out-of-tree, but the decision should be intentional and not forced
> into, especially during the stabilization period.  Please add the
> hooks back for 2.6.30.  You can send another patch targeted at 2.6.31
> -next to remove them again so that it can be discussed properly on the
> list.

Okay. Here it is.

 include/linux/fsl_devices.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index f2a78b5..0cde180 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -83,6 +83,10 @@ struct fsl_spi_platform_data {
 	u16	max_chipselect;
 	void	(*cs_control)(struct spi_device *spi, bool on);
 	u32	sysclk;
+
+	/* Legacy hooks, used by mpc52xx_psc_spi driver. */
+	void	(*activate_cs)(u8 cs, u8 polarity);
+	void	(*deactivate_cs)(u8 cs, u8 polarity);
 };
 
 struct mpc8xx_pcmcia_ops {
-- 
1.6.2.2

^ permalink raw reply related

* Re: [BUILD FAILURE 01/12] Next April 14 : PPC64 randconfig [arch/powerpc/platforms/pseries/dtl.c]
From: Jeremy Kerr @ 2009-04-14 23:36 UTC (permalink / raw)
  To: subrata
  Cc: sachinp, Stephen Rothwell, linux-kernel, Rafael J. Wysocki,
	Linuxppc-dev, linux-next, Alexander Beregalov
In-Reply-To: <1239733686.5344.73.camel@subratamodak.linux.ibm.com>

Hi Subrata,

> This was reported earlier and fix given by Sachin:
> http://patchwork.ozlabs.org/patch/25481/,

Michael Neuling asked for some changes to that patch, but I haven't seen 
a new patch on the list. Will send soon..

Regards,


Jeremy

^ permalink raw reply

* Re: [BUILD FAILURE 11/12] Next April 14 : PPC64 randconfig [drivers/spi/mpc52xx_psc_spi.c]
From: Grant Likely @ 2009-04-14 23:03 UTC (permalink / raw)
  To: avorontsov
  Cc: sachinp, Stephen Rothwell, David Brownell, Greg KH, linux-kernel,
	Rafael J. Wysocki, Linuxppc-dev, linux-next, Paul Mackerras,
	subrata, Alexander Beregalov
In-Reply-To: <20090414222753.GA26006@oksana.dev.rtsoft.ru>

Damn.  I didn't "reply to all" earlier in the thread.  Adding back the
mailing list.

On Tue, Apr 14, 2009 at 4:27 PM, Anton Vorontsov
<avorontsov@ru.mvista.com> wrote:
> On Tue, Apr 14, 2009 at 04:19:56PM -0600, Grant Likely wrote:
>> On Tue, Apr 14, 2009 at 4:02 PM, Anton Vorontsov
>> <avorontsov@ru.mvista.com> wrote:
>> > On Tue, Apr 14, 2009 at 03:54:16PM -0600, Grant Likely wrote:
>> >> On Tue, Apr 14, 2009 at 3:51 PM, Anton Vorontsov
>> >> <avorontsov@ru.mvista.com> wrote:
>> >> > On Tue, Apr 14, 2009 at 03:31:39PM -0600, Grant Likely wrote:
>> >> >> On Tue, Apr 14, 2009 at 3:27 PM, Anton Vorontsov
>> >> >> <avorontsov@ru.mvista.com> wrote:
>> >> >> > On Tue, Apr 14, 2009 at 12:42:47PM -0600, Grant Likely wrote:
>> >> >> >> Thanks Subrata. =A0I'll look into this.
>> >> >> >
>> >> >> > Whoops. That's my fault, I didn't expect that anyone other
>> >> >> > than spi_mpc83xx is using fsl_spi_platform_data. :-/
>> >> >>
>> >> >> /me hands Anton a paper bag.
>> >> >
>> >> > Yeah... :-(
>> >> >
>> >> > This should fix the issue:
>> >>
>> >> Are there any users of this in tree?
>> >
>> > Nope. Sure, we should switch the driver to the gpios =3D <>,
>> > but I believe it's too late for 2.6.30, and FWIW, I can't test
>> > the result on the hardware (don't have any MPC52xx machines).
>> >
>> > So there are two options:
>> >
>> > 1. Remove the cs stuff completely (then the driver would only
>> > =A0 handle SPI devices w/o chipselects, and thus we should state it
>> > =A0 in the Kconfig).
>> > 2. Just fix the build (could also help non-mainline users, if any).
>>
>> Either way will break out of tree users. =A0I don't want to be forced
>> into such a decision during the stablization period. =A0The removal of
>> struct fsl_spi_platform_data needs to be reverted.
>
> Hm. struct fsl_spi_platform_data is still there. It's just there
> is no two functions (activate_cs and deactivate_cs) any longer,
> there's just one: cs_ontrol that takes "spi_device" and "on"
> arguments).
>
> And the build fix (down below) is trivial.

Regardless of how trivial the build fix is for in-tree, I'm not
thrilled with breaking out of tree users.  I don't bend over backwards
for out-of-tree, but the decision should be intentional and not forced
into, especially during the stabilization period.  Please add the
hooks back for 2.6.30.  You can send another patch targeted at 2.6.31
-next to remove them again so that it can be discussed properly on the
list.

g.

>
>> g.
>>
>> >
>> >>
>> >> >
>> >> > ---
>> >> >
>> >> > diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_ps=
c_spi.c
>> >> > index 68c77a9..e1901fd 100644
>> >> > --- a/drivers/spi/mpc52xx_psc_spi.c
>> >> > +++ b/drivers/spi/mpc52xx_psc_spi.c
>> >> > @@ -13,6 +13,7 @@
>> >> >
>> >> > =A0#include <linux/module.h>
>> >> > =A0#include <linux/init.h>
>> >> > +#include <linux/types.h>
>> >> > =A0#include <linux/errno.h>
>> >> > =A0#include <linux/interrupt.h>
>> >> > =A0#include <linux/of_platform.h>
>> >> > @@ -30,8 +31,7 @@
>> >> >
>> >> > =A0struct mpc52xx_psc_spi {
>> >> > =A0 =A0 =A0 =A0/* fsl_spi_platform data */
>> >> > - =A0 =A0 =A0 void (*activate_cs)(u8, u8);
>> >> > - =A0 =A0 =A0 void (*deactivate_cs)(u8, u8);
>> >> > + =A0 =A0 =A0 void (*cs_control)(struct spi_device *spi, bool on);
>> >> > =A0 =A0 =A0 =A0u32 sysclk;
>> >> >
>> >> > =A0 =A0 =A0 =A0/* driver internal data */
>> >> > @@ -111,18 +111,16 @@ static void mpc52xx_psc_spi_activate_cs(struc=
t spi_device *spi)
>> >> > =A0 =A0 =A0 =A0out_be16((u16 __iomem *)&psc->ccr, ccr);
>> >> > =A0 =A0 =A0 =A0mps->bits_per_word =3D cs->bits_per_word;
>> >> >
>> >> > - =A0 =A0 =A0 if (mps->activate_cs)
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->activate_cs(spi->chip_select,
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (spi-=
>mode & SPI_CS_HIGH) ? 1 : 0);
>> >> > + =A0 =A0 =A0 if (mps->cs_control)
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control(spi, (spi->mode & SPI=
_CS_HIGH) ? 1 : 0);
>> >> > =A0}
>> >> >
>> >> > =A0static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi=
)
>> >> > =A0{
>> >> > =A0 =A0 =A0 =A0struct mpc52xx_psc_spi *mps =3D spi_master_get_devda=
ta(spi->master);
>> >> >
>> >> > - =A0 =A0 =A0 if (mps->deactivate_cs)
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->deactivate_cs(spi->chip_select,
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (spi-=
>mode & SPI_CS_HIGH) ? 1 : 0);
>> >> > + =A0 =A0 =A0 if (mps->cs_control)
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control(spi, (spi->mode & SPI=
_CS_HIGH) ? 0 : 1);
>> >> > =A0}
>> >> >
>> >> > =A0#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
>> >> > @@ -388,15 +386,13 @@ static int __init mpc52xx_psc_spi_do_probe(st=
ruct device *dev, u32 regaddr,
>> >> > =A0 =A0 =A0 =A0mps->irq =3D irq;
>> >> > =A0 =A0 =A0 =A0if (pdata =3D=3D NULL) {
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_warn(dev, "probe called without =
platform data, no "
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "(de)=
activate_cs function will be called\n");
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->activate_cs =3D NULL;
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->deactivate_cs =3D NULL;
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "cs_c=
ontrol function will be called\n");
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control =3D NULL;
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mps->sysclk =3D 0;
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->bus_num =3D bus_num;
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->num_chipselect =3D 255;
>> >> > =A0 =A0 =A0 =A0} else {
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->activate_cs =3D pdata->activate_=
cs;
>> >> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->deactivate_cs =3D pdata->deactiv=
ate_cs;
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mps->cs_control =3D pdata->cs_control=
;
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mps->sysclk =3D pdata->sysclk;
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->bus_num =3D pdata->bus_num;
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0master->num_chipselect =3D pdata->ma=
x_chipselect;
>> >> >
>> >>
>> >>
>> >>
>> >> --
>> >> Grant Likely, B.Sc., P.Eng.
>> >> Secret Lab Technologies Ltd.
>> >
>> > --
>> > Anton Vorontsov
>> > email: cbouatmailru@gmail.com
>> > irc://irc.freenode.net/bd2
>> >
>>
>>
>>
>> --
>> Grant Likely, B.Sc., P.Eng.
>> Secret Lab Technologies Ltd.
>
> --
> Anton Vorontsov
> email: cbouatmailru@gmail.com
> irc://irc.freenode.net/bd2
>



--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH] AOA: Convert onyx and tas codecs to new-style i2c drivers
From: Andreas Schwab @ 2009-04-14 22:48 UTC (permalink / raw)
  To: Jean Delvare
  Cc: Takashi Iwai, linuxppc-dev, Johannes Berg, Benjamin, alsa-devel
In-Reply-To: <20090414214949.736597d9@hyperion.delvare>

Jean Delvare <khali@linux-fr.org> writes:

> Hi Johannes,
>
> On Tue, 14 Apr 2009 19:41:55 +0200, Johannes Berg wrote:
>> Alright, with the patch Andreas pointed out it loads, but segfaults, as
>> below. Works fine without your patch.
>
> Thanks for the quick test and sorry that it didn't work. I'll take a
> look at the trace below and try to figure out what went wrong.
>
> Did you remove the 2 MODULE_DEVICE_TABLE from my patch? If you didn't,
> please pick the latest version of my patch which doesn't have them:
> ftp://ftp.kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/sound-aoa-codecs-convert-to-new-style.patch
> I don't think they are the reason of the crash, but who knows...

I tried with a tas-based iBook, and it works fine here.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* Re: [RFC v2] virtio: add virtio-over-PCI driver
From: David Hawkins @ 2009-04-14 22:27 UTC (permalink / raw)
  To: Grant Likely
  Cc: Arnd Bergmann, Jan-Bernd Themann, netdev, Rusty Russell,
	linux-kernel, linuxppc-dev, Ira Snyder
In-Reply-To: <fa686aa40904141516s1ca2965fted07bf2a6f5ce390@mail.gmail.com>

Hi Grant,

> Hmmm, I hadn't thought about this.  I was intending to use the
> Virtex's memory region for all virtio, but if I can allocate memory
> regions on both sides of the PCI bus, then that may be best.

Sounds like you can experiment and see what works best :)

>> If you use
>> a PCI Target only core, then the MPC5200 DMA controller
>> will have to do all the work, and read transfers might
>> be slightly less efficient.
> 
> I'll definitely intend to enable master mode on the Xilinx PCI controller.

Since you understand the lingo, you clearly understand
there are core differences :)

>> Our target boards (PowerPC) live in compactPCI backplanes
>> and talk to x86 boards that do not have DMA controllers.
>> So the PCI target board DMA controllers are used to
>> transfer data efficiently to the x86 host (writes)
>> and less efficiently from the host to the boards
>> (reads). Our bandwidth requirements are 'to the host',
>> so we can live with the asymmetry in performance.
> 
> Fortunately I don't have very high bandwidth requirements for the
> first spin, so I have some room to experiment.  :-)

Yes, in theory you have enough bandwidth ... then a
few features are added, the PCI core is not quite as
fast as advertised, etc etc :)

Cheers,
Dave

^ permalink raw reply

* Re: [BUILD FAILURE 06/12] Next April 14 : PPC64 randconfig [drivers/net/ehea/ehea_main.c]
From: David Miller @ 2009-04-14 22:18 UTC (permalink / raw)
  To: a.beregalov
  Cc: tklein, sfr, themann, netdev, linux-kernel, rjw, Linuxppc-dev,
	sachinp, raisch, julia, linux-next, greg, linux-net, mel, subrata,
	jgarzik
In-Reply-To: <20090414183938.GA17134@orion>

From: Alexander Beregalov <a.beregalov@gmail.com>
Date: Tue, 14 Apr 2009 22:39:38 +0400

> ehea: Fix incomplete conversion to net_device_ops
> 
> Reported-by: Subrata Modak <subrata@linux.vnet.ibm.com>
> Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com>

Applied, thanks Alexander.

^ permalink raw reply

* Re: [RFC v2] virtio: add virtio-over-PCI driver
From: Grant Likely @ 2009-04-14 22:16 UTC (permalink / raw)
  To: David Hawkins
  Cc: Arnd Bergmann, Jan-Bernd Themann, netdev, Rusty Russell,
	linux-kernel, linuxppc-dev, Ira Snyder
In-Reply-To: <49E505B3.5070005@ovro.caltech.edu>

On Tue, Apr 14, 2009 at 3:52 PM, David Hawkins <dwh@ovro.caltech.edu> wrote=
:
> Hi Grant,
>
>> Thanks David. =A0I haven't looked closely at the xilinx pci data sheet
>> yet, but I don't expect too many issues in this area. =A0As you say, it
>> won't take much to code it up. =A0I'll be poking my VHDL engineer to
>> make it do what I want it to. =A0:-)
>
> The key aspects of the core will be that it is Master/Target
> so that it can take over the PCI bus, and that it has a
> DMA engine that can take care of most of the work. In
> your case, since you have a DMA controller on the host
> (MPC5200) and the target (Xilinx), your driver might end
> up having nicer symmetry than our application. The
> most efficient implementation will be the one that
> uses PCI writes, i.e., MPC5200 DMAs to the Xilinx core,
> and the Xilinx core DMAs to the MPC5200.

Hmmm, I hadn't thought about this.  I was intending to use the
Virtex's memory region for all virtio, but if I can allocate memory
regions on both sides of the PCI bus, then that may be best.

> If you use
> a PCI Target only core, then the MPC5200 DMA controller
> will have to do all the work, and read transfers might
> be slightly less efficient.

I'll definitely intend to enable master mode on the Xilinx PCI controller.

> Our target boards (PowerPC) live in compactPCI backplanes
> and talk to x86 boards that do not have DMA controllers.
> So the PCI target board DMA controllers are used to
> transfer data efficiently to the x86 host (writes)
> and less efficiently from the host to the boards
> (reads). Our bandwidth requirements are 'to the host',
> so we can live with the asymmetry in performance.

Fortunately I don't have very high bandwidth requirements for the
first spin, so I have some room to experiment.  :-)

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH] AOA: Convert onyx and tas codecs to new-style i2c    drivers
From: Johannes Berg @ 2009-04-14 21:59 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Takashi Iwai, linuxppc-dev, alsa-devel
In-Reply-To: <20090414214949.736597d9@hyperion.delvare>

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

Hi Jean,

> Thanks for the quick test and sorry that it didn't work. I'll take a
> look at the trace below and try to figure out what went wrong.

No worries, seems some error path is going wrong but I can't see what it
is right now.

> Did you remove the 2 MODULE_DEVICE_TABLE from my patch? If you didn't,
> please pick the latest version of my patch which doesn't have them:
> ftp://ftp.kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/sound-aoa-codecs-convert-to-new-style.patch
> I don't think they are the reason of the crash, but who knows...

No, I didn't, but I was loading the modules manually so that didn't kick
in.

> Are you using a machine with onyx or tas? I guess onyx but I want to be
> sure.

onyx only.

> > [   10.267137] snd-aoa-codec-onyx: found pcm3052
> > [   10.267238] PM: Adding info for i2c:2-0046
> > [   10.267926] snd-aoa-fabric-layout: platform-onyx-codec-ref doesn't match!
> 
> Does this error also happen without my patch? It would help to see the
> logs without my patch to see where it starts diverging.

Yes -- this happens normally.

> > [   10.267930] snd-aoa: fabric didn't like codec onyx
> > [   10.268041] aoa_codec_onyx: probe of 2-0046 failed with error -22
> 
> Apparently aoa_codec_register failed in onyx_i2c_probe(), I have to
> understand why.

Because the device-tree is broken -- there are two nodes for the same
device, and only one of them can be used. Then the fabric rejects the
first instantiation from the broken node. Here's how it looks normally:

...
[   10.398296] snd-aoa-codec-onyx: found pcm3052
[   10.398472] PM: Adding info for i2c:2-0046
[   10.412189] snd-aoa-fabric-layout: platform-onyx-codec-ref doesn't match!
[   10.462593] snd-aoa: fabric didn't like codec onyx
[   10.468030] PM: Removing info for i2c:2-0046
[   10.473892] snd-aoa-codec-onyx: found pcm3052
[   10.479317] PM: Adding info for i2c:3-0046
[   10.485631] snd-aoa-fabric-layout: can use this codec
...

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [RFC v2] virtio: add virtio-over-PCI driver
From: Ira Snyder @ 2009-04-14 21:53 UTC (permalink / raw)
  To: Grant Likely
  Cc: Arnd Bergmann, Jan-Bernd Themann, netdev, Rusty Russell,
	linux-kernel, linuxppc-dev
In-Reply-To: <fa686aa40904141328oa57fb1bsffd0549a52eca90@mail.gmail.com>

On Tue, Apr 14, 2009 at 02:28:26PM -0600, Grant Likely wrote:
> On Mon, Feb 23, 2009 at 6:00 PM, Ira Snyder <iws@ovro.caltech.edu> wrote:
> > This adds support to Linux for using virtio between two computers linked by
> > a PCI interface. This allows the use of virtio_net to create a familiar,
> > fast interface for communication. It should be possible to use other virtio
> > devices in the future, but this has not been tested.
> 
> Hey Ira,
> 
> I like this a lot.  I need to do much the same thing on one of my
> platforms, so I'm going to use your patch as my starting point.  Have
> you made many changes since you posted this version of your patch?
> I'd like to collaborate on the development and help to get it
> mainlined.
> 

This would be great. I'd really appreciate the help. I haven't had time
to make any changes since I last posted the patch. I started work on
converting all of the usage of struct vop_loc_* to just use the on-wire
structures, but I didn't get very far before other work got in the way.

> In my case I've got an MPC5200 as the 'host' and a Xilinx Virtex
> (ppc440) as the 'client'.  I intend set aside a region of the Xilinx
> Virtex's memory space for the shared queues.  I'm starting work on it
> now, and I'll provide you with feedback and/or patches as I make
> progress.
> 

I'm looking forward to seeing your implementation. If you have any
questions, I'd be happy to attempt to answer them :)

Ira

^ permalink raw reply

* Re: [RFC v2] virtio: add virtio-over-PCI driver
From: David Hawkins @ 2009-04-14 21:52 UTC (permalink / raw)
  To: Grant Likely
  Cc: Arnd Bergmann, Jan-Bernd Themann, netdev, Rusty Russell,
	linux-kernel, linuxppc-dev, Ira Snyder
In-Reply-To: <fa686aa40904141445x6a125e12r391e0853d89baf72@mail.gmail.com>

Hi Grant,

> Thanks David.  I haven't looked closely at the xilinx pci data sheet
> yet, but I don't expect too many issues in this area.  As you say, it
> won't take much to code it up.  I'll be poking my VHDL engineer to
> make it do what I want it to.  :-)

The key aspects of the core will be that it is Master/Target
so that it can take over the PCI bus, and that it has a
DMA engine that can take care of most of the work. In
your case, since you have a DMA controller on the host
(MPC5200) and the target (Xilinx), your driver might end
up having nicer symmetry than our application. The
most efficient implementation will be the one that
uses PCI writes, i.e., MPC5200 DMAs to the Xilinx core,
and the Xilinx core DMAs to the MPC5200. If you use
a PCI Target only core, then the MPC5200 DMA controller
will have to do all the work, and read transfers might
be slightly less efficient.

Our target boards (PowerPC) live in compactPCI backplanes
and talk to x86 boards that do not have DMA controllers.
So the PCI target board DMA controllers are used to
transfer data efficiently to the x86 host (writes)
and less efficiently from the host to the boards
(reads). Our bandwidth requirements are 'to the host',
so we can live with the asymmetry in performance.

> I'll keep you up to date on my progress.

Sounds good.

Cheers,
Dave

^ permalink raw reply

* Re: [RFC v2] virtio: add virtio-over-PCI driver
From: David Hawkins @ 2009-04-14 21:23 UTC (permalink / raw)
  To: Grant Likely
  Cc: Arnd Bergmann, Jan-Bernd Themann, netdev, Rusty Russell,
	linux-kernel, linuxppc-dev, Ira Snyder
In-Reply-To: <fa686aa40904141328oa57fb1bsffd0549a52eca90@mail.gmail.com>

Hi Grant,

> I like this a lot.  I need to do much the same thing on one of my
> platforms, so I'm going to use your patch as my starting point.  Have
> you made many changes since you posted this version of your patch?
> I'd like to collaborate on the development and help to get it
> mainlined.
> 
> In my case I've got an MPC5200 as the 'host' and a Xilinx Virtex
> (ppc440) as the 'client'.  I intend set aside a region of the Xilinx
> Virtex's memory space for the shared queues.  I'm starting work on it
> now, and I'll provide you with feedback and/or patches as I make
> progress.

I'll let Ira update you on the patch status.

If you want someone to chat about the hardware-level interaction,
feel free to chat off-list - assuming of course that no one wants
to hear us talk hardware :)

I selected the MPC8349EA in-part due to its PCI mailboxes, so
that we could implement this type of driver (an interlocked
handshake for flow control of data transfers). The previous
chip I'd used was a PLX PCI9054 Master/Target, and it has
similar registers.

I'm not sure if the Xilinx PCI core, or whatever PCI core you
are using, already has something like the mailboxes implemented,
but if not, it won't take much to code up some logic.
I prefer VHDL myself, but can speak Verilog if forced to :)

Cheers,
Dave

^ permalink raw reply

* Re: [RFC v2] virtio: add virtio-over-PCI driver
From: Grant Likely @ 2009-04-14 21:45 UTC (permalink / raw)
  To: David Hawkins
  Cc: Arnd Bergmann, Jan-Bernd Themann, netdev, Rusty Russell,
	linux-kernel, linuxppc-dev, Ira Snyder
In-Reply-To: <49E4FED0.1020003@ovro.caltech.edu>

On Tue, Apr 14, 2009 at 3:23 PM, David Hawkins <dwh@ovro.caltech.edu> wrote:
> I'll let Ira update you on the patch status.
>
> If you want someone to chat about the hardware-level interaction,
> feel free to chat off-list - assuming of course that no one wants
> to hear us talk hardware :)
>
> I selected the MPC8349EA in-part due to its PCI mailboxes, so
> that we could implement this type of driver (an interlocked
> handshake for flow control of data transfers). The previous
> chip I'd used was a PLX PCI9054 Master/Target, and it has
> similar registers.
>
> I'm not sure if the Xilinx PCI core, or whatever PCI core you
> are using, already has something like the mailboxes implemented,
> but if not, it won't take much to code up some logic.
> I prefer VHDL myself, but can speak Verilog if forced to :)

Thanks David.  I haven't looked closely at the xilinx pci data sheet
yet, but I don't expect too many issues in this area.  As you say, it
won't take much to code it up.  I'll be poking my VHDL engineer to
make it do what I want it to.  :-)

I'll keep you up to date on my progress.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [BUILD FAILURE 11/12] Next April 14 : PPC64 randconfig [drivers/spi/mpc52xx_psc_spi.c]
From: Anton Vorontsov @ 2009-04-14 21:27 UTC (permalink / raw)
  To: Grant Likely
  Cc: sachinp, Stephen Rothwell, David Brownell, Greg KH, linux-kernel,
	Rafael J. Wysocki, Linuxppc-dev, linux-next, Paul Mackerras,
	subrata, Alexander Beregalov
In-Reply-To: <fa686aa40904141142s3717812ep293973fefce8853d@mail.gmail.com>

On Tue, Apr 14, 2009 at 12:42:47PM -0600, Grant Likely wrote:
> Thanks Subrata.  I'll look into this.

Whoops. That's my fault, I didn't expect that anyone other
than spi_mpc83xx is using fsl_spi_platform_data. :-/

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* Question about DBCR0 initialization for 440
From: John Linn @ 2009-04-14 20:33 UTC (permalink / raw)
  To: jwboyer, grant.likely, linuxppc-dev

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

The kernel does not initialize the PPC440 DBCR0 register. This prevents
(among other things) the use of software breakpoints with GDB.  I
realize that boot loaders probably do initialize this but we run a lot
without a boot loader and so do our customers.

 

The file, head_fsl_booke.S, does initialize the register for the
freescale specific code (as shown at the end of the message).

 

We are needing this also for Xilinx.  What's the best method to
incorporate this, is it possible to add to head_44x.S?

 

Thanks,

John

 

#if !defined(CONFIG_BDI_SWITCH)

            /*

             * The Abatron BDI JTAG debugger does not tolerate others

             * mucking with the debug registers.

             */

            lis     r2,DBCR0_IDM@h

            mtspr   SPRN_DBCR0,r2

            isync

            /* clear any residual debug events */

            li      r2,-1

            mtspr   SPRN_DBSR,r2

#endif

 



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.


[-- Attachment #2: Type: text/html, Size: 5751 bytes --]

^ permalink raw reply

* Re: [RFC v2] virtio: add virtio-over-PCI driver
From: Grant Likely @ 2009-04-14 20:28 UTC (permalink / raw)
  To: Ira Snyder
  Cc: Arnd Bergmann, Jan-Bernd Themann, netdev, Rusty Russell,
	linux-kernel, linuxppc-dev
In-Reply-To: <20090224000002.GA578@ovro.caltech.edu>

On Mon, Feb 23, 2009 at 6:00 PM, Ira Snyder <iws@ovro.caltech.edu> wrote:
> This adds support to Linux for using virtio between two computers linked =
by
> a PCI interface. This allows the use of virtio_net to create a familiar,
> fast interface for communication. It should be possible to use other virt=
io
> devices in the future, but this has not been tested.

Hey Ira,

I like this a lot.  I need to do much the same thing on one of my
platforms, so I'm going to use your patch as my starting point.  Have
you made many changes since you posted this version of your patch?
I'd like to collaborate on the development and help to get it
mainlined.

In my case I've got an MPC5200 as the 'host' and a Xilinx Virtex
(ppc440) as the 'client'.  I intend set aside a region of the Xilinx
Virtex's memory space for the shared queues.  I'm starting work on it
now, and I'll provide you with feedback and/or patches as I make
progress.

g.

>
> I have implemented guest support for the Freescale MPC8349EMDS board, whi=
ch
> is capable of running in PCI agent mode (It acts like a PCI card, but is =
a
> complete computer system, running Linux). The driver is trivial to port t=
o
> any MPC83xx system.
>
> It was developed to work in a CompactPCI crate of computers, one of which
> is a standard x86 system (acting as the host) and many PowerPC systems
> (acting as guests).
>
> I have only tested this driver with a single board in my system. The host
> is a 1066MHz Pentium3-M, and the guest is a 533MHz PowerPC. I am able
> achieve transfer rates of about 150 mbit host->guest and 350 mbit
> guest->host. A few tests showed that using an mtu of 4000 provided much
> better results than an mtu of 1500. Using an mtu of 64000 significantly
> dropped performance. The performance is equivalent to my PCINet driver fo=
r
> host->guest, and about 20% faster for guest->host transfers.
>
> I have included a short document explaining what I think is the most
> complicated part of the driver: using the DMA engine to transfer data. I
> hope everything else is readily obvious from the code. Questions are
> welcome.
>
> I will not be able to work on this full time for at least a few weeks, so=
 I
> would appreciate actual review of this driver. =A0Nitpicks are fine, I ju=
st
> won't be able to respond to them quickly.
>
> RFCv1 -> RFCv2:
> =A0* fix major brokenness of host detach_buf()
> =A0* support VIRTIO_NET_F_CSUM
> =A0* support VIRTIO_NET_F_GSO
> =A0* support VIRTIO_NET_F_MRG_RXBUF
> =A0* rewrote DMA transfers to support merged rxbufs
> =A0* added a hack to fix the endianness of virtio_net's metadata
> =A0* lots more performance for guest->host transfers (~40MB/sec)
> =A0* updated documentation
> =A0* allocate 128 feature bits instead of 32
>
> Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
> ---
>
> Yes, the commit message has too much information. This is an RFC after
> all. I fully expect to have to make changes. In fact, I posting this
> more to "get it out there" than anything else, since I have other tasks
> that need doing.
>
> I'd appreciate a serious review of the design by the people who have
> been pressuring me to use virtio. I'm very happy to answer any questions
> you have.
>
> Thanks to everyone who gave feedback for RFCv1!
> Ira
>
> =A0Documentation/virtio-over-PCI.txt =A0 =A0 | =A0 60 +
> =A0arch/powerpc/boot/dts/mpc834x_mds.dts | =A0 =A07 +
> =A0drivers/virtio/Kconfig =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0 22 +
> =A0drivers/virtio/Makefile =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 =A02 +
> =A0drivers/virtio/vop.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0119 ++
> =A0drivers/virtio/vop_fsl.c =A0 =A0 =A0 =A0 =A0 =A0 =A0| 2020 +++++++++++=
++++++++++++++++++++++
> =A0drivers/virtio/vop_host.c =A0 =A0 =A0 =A0 =A0 =A0 | 1071 +++++++++++++=
++++
> =A0drivers/virtio/vop_hw.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 80 ++
> =A08 files changed, 3381 insertions(+), 0 deletions(-)
> =A0create mode 100644 Documentation/virtio-over-PCI.txt
> =A0create mode 100644 drivers/virtio/vop.h
> =A0create mode 100644 drivers/virtio/vop_fsl.c
> =A0create mode 100644 drivers/virtio/vop_host.c
> =A0create mode 100644 drivers/virtio/vop_hw.h
>
> diff --git a/Documentation/virtio-over-PCI.txt b/Documentation/virtio-ove=
r-PCI.txt
> new file mode 100644
> index 0000000..e4520d4
> --- /dev/null
> +++ b/Documentation/virtio-over-PCI.txt
> @@ -0,0 +1,60 @@
> +The implementation of virtio-over-PCI was driven with the following goal=
s:
> +* Avoid MMIO reads, try to use only MMIO writes
> +* Use the onboard DMA engine, for speed
> +
> +The implementation also borrows many of the details from the only other
> +implementation, virtio_ring.
> +
> +It succeeds in avoiding all MMIO reads on the critical paths. I did not
> +see any reason to avoid the use of MMIO reads during device probing, sin=
ce
> +it is not a critical path.
> +
> +=3D=3D=3D Avoiding MMIO reads =3D=3D=3D
> +To avoid MMIO reads, both the host and guest systems have a copy of the
> +descriptors. Both sides need to read the descriptors after they have bee=
n
> +written, but only the host system writes to them. This allows us to keep=
 a
> +local copy for later use.
> +
> +=3D=3D=3D Using the DMA engine =3D=3D=3D
> +This is the only truly complicated part of the system. Since this
> +implementation was designed for use with virtio_net, it may be biased
> +towards virtio_net's usage of the virtio interface.
> +
> +In merged rxbufs mode, the virtio_net driver provides a receive ring, wh=
ich
> +it fills with empty PAGE_SIZE buffers. The DMA code sets up transfers
> +directly from the guest transmit queue to the empty packets in the host
> +receive queue. Data transfer in the other direction works in a similar
> +fashion.
> +
> +The guest (PowerPC) system keeps its own local set of descriptors, which=
 are
> +filled by the virtio add_buf() call. Whenever this happens, the avail ri=
ng is
> +changed, and therefore we try to transfer data.
> +
> +The algorithm is essentially as follows:
> +1) Check for an available local or remote entry
> +2) Check that the other side has enough room for the packet
> +3) Transfer the chain, joining small packets and splitting large packets
> +4) Move the entries to the used rings, but do not update the used index
> +5) Schedule a DMA callback to happen when the transfer completes
> +6) Start the DMA transfer
> +7) When the DMA finishes, the callback updates the used indices and
> + =A0 triggers any necessary callbacks
> +
> +The algorithm can only handle chains that are to be coalesced together. =
It
> +puts all data sequentially into the PAGE_SIZE buffers exposed by the
> +receiving side, including both the virtio_net header and packet data.
> +
> +=3D=3D=3D Startup Sequence =3D=3D=3D
> +There are currently problems in the startup sequence between the host an=
d
> +guest drivers. The current scheme assumes that the guest is up and waiti=
ng
> +before the host is ready. I am having a very hard time coming up with a =
scheme
> +that is perfectly safe, where either side could win the race and be read=
y
> +first.
> +
> +Even harder is a situation where you would like to use the "network devi=
ce"
> +from your bootloader to tftp a kernel, then boot Linux. In this case,
> +Linux has no knowledge of where the device descriptors were before it bo=
oted.
> +You'd need to stop and re-start the host driver to make sure it re-initi=
alizes
> +the new descriptor memory after Linux has booted.
> +
> +This is a definite "needs work" item.
> diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dt=
s/mpc834x_mds.dts
> index d9adba0..5c7617d 100644
> --- a/arch/powerpc/boot/dts/mpc834x_mds.dts
> +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
> @@ -104,6 +104,13 @@
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mode =3D "cpu";
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0};
>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 message-unit@8030 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,mpc8349=
-mu";
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <0x8030 0xd0>;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupts =3D <69 0x8>;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupt-parent =3D <&ipic=
>;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 };
> +
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dma@82a8 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0#address-cells =3D <1>;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0#size-cells =3D <1>;
> diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
> index 3dd6294..efcf56b 100644
> --- a/drivers/virtio/Kconfig
> +++ b/drivers/virtio/Kconfig
> @@ -33,3 +33,25 @@ config VIRTIO_BALLOON
>
> =A0 =A0 =A0 =A0 If unsure, say M.
>
> +config VIRTIO_OVER_PCI_HOST
> + =A0 =A0 =A0 tristate "Virtio-over-PCI Host support (EXPERIMENTAL)"
> + =A0 =A0 =A0 depends on PCI && EXPERIMENTAL
> + =A0 =A0 =A0 select VIRTIO
> + =A0 =A0 =A0 ---help---
> + =A0 =A0 =A0 =A0 This driver provides the host support necessary for usi=
ng virtio
> + =A0 =A0 =A0 =A0 over the PCI bus with a Freescale MPC8349EMDS evaluatio=
n board.
> +
> + =A0 =A0 =A0 =A0 If unsure, say N.
> +
> +config VIRTIO_OVER_PCI_FSL
> + =A0 =A0 =A0 tristate "Virtio-over-PCI Guest support (EXPERIMENTAL)"
> + =A0 =A0 =A0 depends on MPC834x_MDS && EXPERIMENTAL
> + =A0 =A0 =A0 select VIRTIO
> + =A0 =A0 =A0 select DMA_ENGINE
> + =A0 =A0 =A0 select FSL_DMA
> + =A0 =A0 =A0 ---help---
> + =A0 =A0 =A0 =A0 This driver provides the guest support necessary for us=
ing virtio
> + =A0 =A0 =A0 =A0 over the PCI bus.
> +
> + =A0 =A0 =A0 =A0 If unsure, say N.
> +
> diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
> index 6738c44..f31afaa 100644
> --- a/drivers/virtio/Makefile
> +++ b/drivers/virtio/Makefile
> @@ -2,3 +2,5 @@ obj-$(CONFIG_VIRTIO) +=3D virtio.o
> =A0obj-$(CONFIG_VIRTIO_RING) +=3D virtio_ring.o
> =A0obj-$(CONFIG_VIRTIO_PCI) +=3D virtio_pci.o
> =A0obj-$(CONFIG_VIRTIO_BALLOON) +=3D virtio_balloon.o
> +obj-$(CONFIG_VIRTIO_OVER_PCI_HOST) +=3D vop_host.o
> +obj-$(CONFIG_VIRTIO_OVER_PCI_FSL) +=3D vop_fsl.o
> diff --git a/drivers/virtio/vop.h b/drivers/virtio/vop.h
> new file mode 100644
> index 0000000..5f77228
> --- /dev/null
> +++ b/drivers/virtio/vop.h
> @@ -0,0 +1,119 @@
> +/*
> + * Virtio-over-PCI definitions
> + *
> + * Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu>
> + *
> + * This file is licensed under the terms of the GNU General Public Licen=
se
> + * version 2. This program is licensed "as is" without any warranty of a=
ny
> + * kind, whether express or implied.
> + */
> +
> +#ifndef VOP_H
> +#define VOP_H
> +
> +#include <linux/types.h>
> +
> +/* The number of entries per ring (MUST be a power of two) */
> +#define VOP_RING_SIZE =A0 =A0 =A0 =A0 =A064
> +
> +/* Marks a buffer as continuing via the next field */
> +#define VOP_DESC_F_NEXT =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A01
> +/* Marks a buffer as write-only (otherwise read-only) */
> +#define VOP_DESC_F_WRITE =A0 =A0 =A0 2
> +
> +/* Interrupts should not be generated when adding to avail or used */
> +#define VOP_F_NO_INTERRUPT =A0 =A0 1
> +
> +/* Virtio-over-PCI descriptors: 12 bytes. These can chain together via "=
next" */
> +struct vop_desc {
> + =A0 =A0 =A0 /* Address (host physical) */
> + =A0 =A0 =A0 __le32 addr;
> + =A0 =A0 =A0 /* Length (bytes) */
> + =A0 =A0 =A0 __le32 len;
> + =A0 =A0 =A0 /* Flags */
> + =A0 =A0 =A0 __le16 flags;
> + =A0 =A0 =A0 /* Chaining for descriptors */
> + =A0 =A0 =A0 __le16 next;
> +} __attribute__((packed));
> +
> +/* Virtio-over-PCI used descriptor chains: 8 bytes */
> +struct vop_used_elem {
> + =A0 =A0 =A0 /* Start index of used descriptor chain */
> + =A0 =A0 =A0 __le32 id;
> + =A0 =A0 =A0 /* Total length of the descriptor chain which was used (wri=
tten to) */
> + =A0 =A0 =A0 __le32 len;
> +} __attribute__((packed));
> +
> +/* The ring in host memory, only written by the guest */
> +/* NOTE: with VOP_RING_SIZE =3D=3D 64, this is 520 bytes */
> +struct vop_host_ring {
> + =A0 =A0 =A0 /* The flags, so the guest can indicate that it doesn't wan=
t
> + =A0 =A0 =A0 =A0* interrupts when things are added to the avail ring */
> + =A0 =A0 =A0 __le16 flags;
> +
> + =A0 =A0 =A0 /* The index, which points at the next slot where a chain i=
ndex
> + =A0 =A0 =A0 =A0* will be added to the used ring */
> + =A0 =A0 =A0 __le16 used_idx;
> +
> + =A0 =A0 =A0 /* The used ring */
> + =A0 =A0 =A0 struct vop_used_elem used[VOP_RING_SIZE];
> +} __attribute__((packed));
> +
> +/* The ring in guest memory, only written by the host */
> +/* NOTE: with VOP_RING_SIZE =3D=3D 64, this is 904 bytes! */
> +struct vop_guest_ring {
> + =A0 =A0 =A0 /* The descriptors */
> + =A0 =A0 =A0 struct vop_desc desc[VOP_RING_SIZE];
> +
> + =A0 =A0 =A0 /* The flags, so the host can indicate that it doesn't want
> + =A0 =A0 =A0 =A0* interrupts when things are added to the used ring */
> + =A0 =A0 =A0 __le16 flags;
> +
> + =A0 =A0 =A0 /* The index, which points at the next slot where a chain i=
ndex
> + =A0 =A0 =A0 =A0* will be added to the avail ring */
> + =A0 =A0 =A0 __le16 avail_idx;
> +
> + =A0 =A0 =A0 /* The avail ring */
> + =A0 =A0 =A0 __le16 avail[VOP_RING_SIZE];
> +} __attribute__((packed));
> +
> +/*
> + * This is the status structure holding the virtio_device status
> + * as well as the feature bits for this device and the configuration
> + * space.
> + *
> + * NOTE: it is for the LOCAL device. This is the slow path, so
> + * NOTE: the mmio reads won't cause any speed problems
> + */
> +struct vop_status {
> + =A0 =A0 =A0 /* Status bits for the device */
> + =A0 =A0 =A0 __le32 status;
> +
> + =A0 =A0 =A0 /* Feature bits for the device (128 bits) */
> + =A0 =A0 =A0 __le32 features[4];
> +
> + =A0 =A0 =A0 /* Configuration space (different for each device type) */
> + =A0 =A0 =A0 u8 config[1004];
> +
> +} __attribute__((packed));
> +
> +/*
> + * Layout in memory
> + *
> + * |--------------------------|
> + * | 0: local device status =A0 |
> + * |--------------------------|
> + * | 1024: host/guest ring 1 =A0|
> + * |--------------------------|
> + * | 2048: host/guest ring 2 =A0|
> + * |--------------------------|
> + * | 3072: host/guest ring 3 =A0|
> + * |--------------------------|
> + *
> + * Now, you have one of these for each virtio device, and
> + * then you're pretty much set. You can expose 16K of memory
> + * out on the bus (on each side) and have 4 virtio devices,
> + * each with a different type, and 3 virtqueues
> + */
> +
> +#endif /* VOP_H */
> diff --git a/drivers/virtio/vop_fsl.c b/drivers/virtio/vop_fsl.c
> new file mode 100644
> index 0000000..7cb3cdd
> --- /dev/null
> +++ b/drivers/virtio/vop_fsl.c
> @@ -0,0 +1,2020 @@
> +/*
> + * Virtio-over-PCI MPC8349EMDS Guest Driver
> + *
> + * Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu>
> + *
> + * This file is licensed under the terms of the GNU General Public Licen=
se
> + * version 2. This program is licensed "as is" without any warranty of a=
ny
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/of_platform.h>
> +#include <linux/io.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_config.h>
> +#include <linux/virtio_net.h>
> +#include <linux/interrupt.h>
> +#include <linux/virtio_net.h>
> +#include <linux/dmaengine.h>
> +#include <linux/workqueue.h>
> +#include <linux/etherdevice.h>
> +
> +/* MPC8349EMDS specific get_immrbase() */
> +#include <sysdev/fsl_soc.h>
> +
> +#include "vop_hw.h"
> +#include "vop.h"
> +
> +/*
> + * These are internal use only versions of the structures that
> + * are exported over PCI by this driver
> + *
> + * They are used internally to keep track of the PowerPC queues so that
> + * we don't have to keep flipping endianness all the time
> + */
> +struct vop_loc_desc {
> + =A0 =A0 =A0 u32 addr;
> + =A0 =A0 =A0 u32 len;
> + =A0 =A0 =A0 u16 flags;
> + =A0 =A0 =A0 u16 next;
> +};
> +
> +struct vop_loc_avail {
> + =A0 =A0 =A0 u16 index;
> + =A0 =A0 =A0 u16 ring[VOP_RING_SIZE];
> +};
> +
> +struct vop_loc_used_elem {
> + =A0 =A0 =A0 u32 id;
> + =A0 =A0 =A0 u32 len;
> +};
> +
> +struct vop_loc_used {
> + =A0 =A0 =A0 u16 index;
> + =A0 =A0 =A0 struct vop_loc_used_elem ring[VOP_RING_SIZE];
> +};
> +
> +/*
> + * DMA Resolver state information
> + */
> +struct vop_dma_info {
> + =A0 =A0 =A0 struct dma_chan *chan;
> +
> + =A0 =A0 =A0 /* The currently processing avail entry */
> + =A0 =A0 =A0 u16 loc_avail;
> + =A0 =A0 =A0 u16 rem_avail;
> +
> + =A0 =A0 =A0 /* The currently processing used entries */
> + =A0 =A0 =A0 u16 loc_used;
> + =A0 =A0 =A0 u16 rem_used;
> +};
> +
> +struct vop_vq {
> +
> + =A0 =A0 =A0 /* The actual virtqueue itself */
> + =A0 =A0 =A0 struct virtqueue vq;
> + =A0 =A0 =A0 struct device *dev;
> +
> + =A0 =A0 =A0 /* The host ring address */
> + =A0 =A0 =A0 struct vop_host_ring __iomem *host;
> +
> + =A0 =A0 =A0 /* The guest ring address */
> + =A0 =A0 =A0 struct vop_guest_ring *guest;
> +
> + =A0 =A0 =A0 /* Our own memory descriptors */
> + =A0 =A0 =A0 struct vop_loc_desc desc[VOP_RING_SIZE];
> + =A0 =A0 =A0 struct vop_loc_avail avail;
> + =A0 =A0 =A0 struct vop_loc_used used;
> + =A0 =A0 =A0 unsigned int flags;
> +
> + =A0 =A0 =A0 /* Data tokens from add_buf() */
> + =A0 =A0 =A0 void *data[VOP_RING_SIZE];
> +
> + =A0 =A0 =A0 unsigned int num_free; =A0/* number of free descriptors in =
desc */
> + =A0 =A0 =A0 unsigned int free_head; /* start of the free descriptors in=
 desc */
> + =A0 =A0 =A0 unsigned int num_added; /* number of entries added to desc =
*/
> +
> + =A0 =A0 =A0 u16 loc_last_used; =A0 =A0 =A0/* the last local used entry =
processed */
> + =A0 =A0 =A0 u16 rem_last_used; =A0 =A0 =A0/* the current value of remot=
e used_idx */
> +
> + =A0 =A0 =A0 /* DMA resolver state */
> + =A0 =A0 =A0 struct vop_dma_info dma;
> + =A0 =A0 =A0 struct work_struct work;
> + =A0 =A0 =A0 int (*resolve)(struct vop_vq *vq);
> +
> + =A0 =A0 =A0 void __iomem *immr;
> + =A0 =A0 =A0 int kick_val;
> +};
> +
> +/* Convert from a struct virtqueue to a struct vop_vq */
> +#define to_vop_vq(X) container_of(X, struct vop_vq, vq)
> +
> +/*
> + * This represents a virtio_device for our driver. It follows the memory
> + * layout shown above. It has pointers to all of the host and guest memo=
ry
> + * areas that we need to access
> + */
> +struct vop_vdev {
> +
> + =A0 =A0 =A0 /* The specific virtio device (console, net, blk) */
> + =A0 =A0 =A0 struct virtio_device vdev;
> +
> + =A0 =A0 =A0 #define VOP_DEVICE_REGISTERED 1
> + =A0 =A0 =A0 int status;
> +
> + =A0 =A0 =A0 /* Start address of local and remote memory */
> + =A0 =A0 =A0 void *loc;
> + =A0 =A0 =A0 void __iomem *rem;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* These are the status, feature, and configuration infor=
mation
> + =A0 =A0 =A0 =A0* for this virtio device. They are exposed in our memory=
 block
> + =A0 =A0 =A0 =A0* starting at offset 0.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 struct vop_status __iomem *host_status;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* These are the status, feature, and configuration infor=
mation
> + =A0 =A0 =A0 =A0* for the guest virtio device. They are exposed in the g=
uest
> + =A0 =A0 =A0 =A0* memory block starting at offset 0.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 struct vop_status *guest_status;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* These are the virtqueues for the virtio driver running=
 this
> + =A0 =A0 =A0 =A0* device to use. The host portions are exposed in our me=
mory block
> + =A0 =A0 =A0 =A0* starting at offset 1024. The exposed areas are aligned=
 to 1024 byte
> + =A0 =A0 =A0 =A0* boundaries, so they appear at offets 1024, 2048, and 3=
072
> + =A0 =A0 =A0 =A0* respectively.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 struct vop_vq virtqueues[3];
> +};
> +
> +#define to_vop_vdev(X) container_of(X, struct vop_vdev, vdev)
> +
> +struct vop_dev {
> +
> + =A0 =A0 =A0 struct of_device *op;
> + =A0 =A0 =A0 struct device *dev;
> +
> + =A0 =A0 =A0 /* Reset and start */
> + =A0 =A0 =A0 struct mutex mutex;
> + =A0 =A0 =A0 struct work_struct reset_work;
> + =A0 =A0 =A0 struct work_struct start_work;
> +
> + =A0 =A0 =A0 int irq;
> +
> + =A0 =A0 =A0 /* Our board control registers */
> + =A0 =A0 =A0 void __iomem *immr;
> +
> + =A0 =A0 =A0 /* The guest memory, exposed at PCI BAR1 */
> + =A0 =A0 =A0 #define VOP_GUEST_MEM_SIZE 16384
> + =A0 =A0 =A0 void *guest_mem;
> + =A0 =A0 =A0 dma_addr_t guest_mem_addr;
> +
> + =A0 =A0 =A0 /* Host memory, given to us by host in OMR0 */
> + =A0 =A0 =A0 #define VOP_HOST_MEM_SIZE 16384
> + =A0 =A0 =A0 void __iomem *host_mem;
> +
> + =A0 =A0 =A0 /* The virtio devices */
> + =A0 =A0 =A0 struct vop_vdev devices[4];
> + =A0 =A0 =A0 struct dma_chan *chan;
> +};
> +
> +/*
> + * DMA callback information
> + */
> +struct vop_dma_cbinfo {
> + =A0 =A0 =A0 struct vop_vq *vq;
> +
> + =A0 =A0 =A0 /* The amount to increment the used rings */
> + =A0 =A0 =A0 unsigned int loc;
> + =A0 =A0 =A0 unsigned int rem;
> +};
> +
> +static const char driver_name[] =3D "vdev";
> +static struct kmem_cache *dma_cache;
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Whole-descriptor access helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * Return a copy of a local descriptor in native format for easy use
> + * of all fields
> + *
> + * @vq the virtqueue
> + * @idx the descriptor index
> + * @desc pointer to the structure to copy into
> + */
> +static void vop_loc_desc(struct vop_vq *vq, unsigned int idx,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct vop_loc_desc *des=
c)
> +{
> + =A0 =A0 =A0 BUG_ON(idx >=3D VOP_RING_SIZE);
> + =A0 =A0 =A0 BUG_ON(!desc);
> +
> + =A0 =A0 =A0 desc->addr =A0=3D vq->desc[idx].addr;
> + =A0 =A0 =A0 desc->len =A0 =3D vq->desc[idx].len;
> + =A0 =A0 =A0 desc->flags =3D vq->desc[idx].flags;
> + =A0 =A0 =A0 desc->next =A0=3D vq->desc[idx].next;
> +}
> +
> +/*
> + * Return a copy of a remote descriptor in native format for easy use
> + * of all fields
> + *
> + * @vq the virtqueue
> + * @idx the descriptor index
> + * @desc pointer to the structure to copy into
> + */
> +static void vop_rem_desc(struct vop_vq *vq, unsigned int idx,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct vop_loc_desc *des=
c)
> +{
> + =A0 =A0 =A0 BUG_ON(idx >=3D VOP_RING_SIZE);
> + =A0 =A0 =A0 BUG_ON(!desc);
> +
> + =A0 =A0 =A0 desc->addr =A0=3D le32_to_cpu(vq->guest->desc[idx].addr);
> + =A0 =A0 =A0 desc->len =A0 =3D le32_to_cpu(vq->guest->desc[idx].len);
> + =A0 =A0 =A0 desc->flags =3D le16_to_cpu(vq->guest->desc[idx].flags);
> + =A0 =A0 =A0 desc->next =A0=3D le16_to_cpu(vq->guest->desc[idx].next);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Local descriptor ring access helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static void vop_set_desc_addr(struct vop_vq *vq, unsigned int idx, u32 a=
ddr)
> +{
> + =A0 =A0 =A0 vq->desc[idx].addr =3D addr;
> +}
> +
> +static void vop_set_desc_len(struct vop_vq *vq, unsigned int idx, u32 le=
n)
> +{
> + =A0 =A0 =A0 vq->desc[idx].len =3D len;
> +}
> +
> +static void vop_set_desc_flags(struct vop_vq *vq, unsigned int idx, u16 =
flags)
> +{
> + =A0 =A0 =A0 vq->desc[idx].flags =3D flags;
> +}
> +
> +static void vop_set_desc_next(struct vop_vq *vq, unsigned int idx, u16 n=
ext)
> +{
> + =A0 =A0 =A0 vq->desc[idx].next =3D next;
> +}
> +
> +static u16 vop_get_desc_flags(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 return vq->desc[idx].flags;
> +}
> +
> +static u16 vop_get_desc_next(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 return vq->desc[idx].next;
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Status Helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static u32 vop_get_host_status(struct vop_vdev *vdev)
> +{
> + =A0 =A0 =A0 return ioread32(&vdev->host_status->status);
> +}
> +
> +static u32 vop_get_host_features(struct vop_vdev *vdev)
> +{
> + =A0 =A0 =A0 return ioread32(&vdev->host_status->features[0]);
> +}
> +
> +static u16 vop_get_host_flags(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 return le16_to_cpu(vq->guest->flags);
> +}
> +
> +/*
> + * Set the guest's flags variable (lives in host memory)
> + */
> +static void vop_set_guest_flags(struct vop_vq *vq, u16 flags)
> +{
> + =A0 =A0 =A0 iowrite16(flags, &vq->host->flags);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Remote Ring Debugging Helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +#ifdef DEBUG_DUMP_RINGS
> +static void dump_rem_desc(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 struct vop_loc_desc desc;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "REM DESC 0xADDRESSX LENGTH 0xFLAG NEXT\n"=
);
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_rem_desc(vq, i, &desc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "DESC %.2d: 0x%.8x %.6d 0x=
%.4x %.2d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 i, desc.add=
r, desc.len, desc.flags, desc.next);
> + =A0 =A0 =A0 }
> +}
> +
> +static void dump_rem_avail(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "REM AVAIL IDX %.2d\n", le16_to_cpu(vq->gu=
est->avail_idx));
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "REM AVAIL %.2d: %.2d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 i, le16_to_=
cpu(vq->guest->avail[i]));
> + =A0 =A0 =A0 }
> +}
> +
> +static void dump_rem_used(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "REM USED IDX %.2d\n", ioread16(&vq->host-=
>used_idx));
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "REM USED %.2d: %.2d %.6d\=
n", i,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ioread32(&v=
q->host->used[i].id),
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ioread32(&v=
q->host->used[i].len));
> + =A0 =A0 =A0 }
> +}
> +
> +static void dump_rem_rings(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 dump_rem_desc(vq);
> + =A0 =A0 =A0 dump_rem_avail(vq);
> + =A0 =A0 =A0 dump_rem_used(vq);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Local Ring Debugging Helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static void dump_loc_desc(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 struct vop_loc_desc desc;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "LOC DESC 0xADDRESSX LENGTH 0xFLAG NEXT\n"=
);
> + =A0 =A0 =A0 for (i =3D 0 ; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_loc_desc(vq, i, &desc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "DESC %.2d: 0x%.8x %.6d 0x=
%.4x %.2d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 i, desc.add=
r, desc.len, desc.flags, desc.next);
> + =A0 =A0 =A0 }
> +}
> +
> +static void dump_loc_avail(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "LOC AVAIL IDX %.2d\n", vq->avail.index);
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "LOC AVAIL %.2d: %.2d\n", =
i, vq->avail.ring[i]);
> +}
> +
> +static void dump_loc_used(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "LOC USED IDX %.2hu\n", vq->used.index);
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "LOC USED %.2d: %.2d %.6d\=
n", i,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->used.ri=
ng[i].id, vq->used.ring[i].len);
> + =A0 =A0 =A0 }
> +}
> +
> +static void dump_loc_rings(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 dump_loc_desc(vq);
> + =A0 =A0 =A0 dump_loc_avail(vq);
> + =A0 =A0 =A0 dump_loc_used(vq);
> +}
> +
> +static void debug_dump_rings(struct vop_vq *vq, const char *msg)
> +{
> + =A0 =A0 =A0 dev_dbg(vq->dev, "\n");
> + =A0 =A0 =A0 dev_dbg(vq->dev, "%s\n", msg);
> + =A0 =A0 =A0 dump_loc_rings(vq);
> + =A0 =A0 =A0 dump_rem_rings(vq);
> + =A0 =A0 =A0 dev_dbg(vq->dev, "\n");
> +}
> +#else
> +static void debug_dump_rings(struct vop_vq *vq, const char *msg)
> +{
> + =A0 =A0 =A0 /* Nothing */
> +}
> +#endif
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Scatterlist DMA helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * This function abuses some of the scatterlist code and implements
> + * dma_map_sg() in such a way that we don't need to keep the scatterlist
> + * around in order to unmap it.
> + *
> + * It is also designed to never merge scatterlist entries, which is
> + * never what we want for virtio.
> + *
> + * When it is time to unmap the buffer, you can use dma_unmap_single() t=
o
> + * unmap each entry in the chain. Get the address, length, and direction
> + * from the descriptors! (keep a local copy for speed)
> + */
> +static int vop_dma_map_sg(struct device *dev, struct scatterlist sg[],
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigned int out, unsig=
ned int in)
> +{
> + =A0 =A0 =A0 dma_addr_t addr;
> + =A0 =A0 =A0 enum dma_data_direction dir;
> + =A0 =A0 =A0 struct scatterlist *start;
> + =A0 =A0 =A0 unsigned int i, failure;
> +
> + =A0 =A0 =A0 start =3D sg;
> +
> + =A0 =A0 =A0 for (i =3D 0; i < out + in; i++) {
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Check for scatterlist chaining abuse */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 BUG_ON(sg =3D=3D NULL);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dir =3D (i < out) ? DMA_TO_DEVICE : DMA_FRO=
M_DEVICE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 addr =3D dma_map_single(dev, sg_virt(sg), s=
g->length, dir);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (dma_mapping_error(dev, addr))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto unwind;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg_dma_address(sg) =3D addr;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return 0;
> +
> +unwind:
> + =A0 =A0 =A0 failure =3D i;
> + =A0 =A0 =A0 sg =3D start;
> +
> + =A0 =A0 =A0 for (i =3D 0; i < failure; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dir =3D (i < out) ? DMA_TO_DEVICE : DMA_FRO=
M_DEVICE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 addr =3D sg_dma_address(sg);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(dev, addr, sg->length, dir=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return -ENOMEM;
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* DMA Helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * Transfer data between two physical addresses with DMA
> + *
> + * NOTE: does not automatically unmap the src and dst addresses
> + *
> + * @chan the channel to use
> + * @dst the physical destination address
> + * @src the physical source address
> + * @len the length to transfer (in bytes)
> + * @return a valid cookie, or -ERRNO
> + */
> +static dma_cookie_t dma_async_memcpy_raw_to_raw(struct dma_chan *chan,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0dma_addr_t dst,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0dma_addr_t src,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0size_t len)
> +{
> + =A0 =A0 =A0 struct dma_device *dev =3D chan->device;
> + =A0 =A0 =A0 struct dma_async_tx_descriptor *tx;
> + =A0 =A0 =A0 enum dma_ctrl_flags flags;
> + =A0 =A0 =A0 dma_cookie_t cookie;
> + =A0 =A0 =A0 int cpu;
> +
> + =A0 =A0 =A0 flags =3D DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UN=
MAP;
> + =A0 =A0 =A0 tx =3D dev->device_prep_dma_memcpy(chan, dst, src, len, fla=
gs);
> + =A0 =A0 =A0 if (!tx)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> +
> + =A0 =A0 =A0 tx->callback =3D NULL;
> + =A0 =A0 =A0 cookie =3D tx->tx_submit(tx);
> +
> + =A0 =A0 =A0 cpu =3D get_cpu();
> + =A0 =A0 =A0 per_cpu_ptr(chan->local, cpu)->bytes_transferred +=3D len;
> + =A0 =A0 =A0 per_cpu_ptr(chan->local, cpu)->memcpy_count++;
> + =A0 =A0 =A0 put_cpu();
> +
> + =A0 =A0 =A0 return cookie;
> +}
> +
> +/*
> + * Trigger an interrupt after all DMA issued up to this point
> + * have been processed
> + *
> + * @chan the channel to use
> + * @callback the function to call (must not sleep)
> + * @data the data to send to the callback
> + *
> + * @return a valid cookie, or -ERRNO
> + */
> +static dma_cookie_t dma_async_interrupt(struct dma_chan *chan,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 dma_async_tx_callback callback,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 void *data)
> +{
> + =A0 =A0 =A0 struct dma_device *dev =3D chan->device;
> + =A0 =A0 =A0 struct dma_async_tx_descriptor *tx;
> +
> + =A0 =A0 =A0 /* Set up the DMA */
> + =A0 =A0 =A0 tx =3D dev->device_prep_dma_interrupt(chan, DMA_PREP_INTERR=
UPT);
> + =A0 =A0 =A0 if (!tx)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> +
> + =A0 =A0 =A0 tx->callback =3D callback;
> + =A0 =A0 =A0 tx->callback_param =3D data;
> +
> + =A0 =A0 =A0 return tx->tx_submit(tx);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* DMA Resolver =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static void vop_remote_used_changed(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 if (!(vop_get_host_flags(vq) & VOP_F_NO_INTERRUPT)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "notifying the host (new b=
uffers in used)\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 iowrite32(vq->kick_val, vq->immr + ODR_OFFS=
ET);
> + =A0 =A0 =A0 }
> +}
> +
> +static void vop_local_used_changed(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 if (!(vq->flags & VOP_F_NO_INTERRUPT)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "notifying self (new buffe=
rs in used)\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->vq.callback(&vq->vq);
> + =A0 =A0 =A0 }
> +}
> +
> +/*
> + * DMA callback function for merged rxbufs
> + *
> + * This is called every time a DMA transfer completes, and will update t=
he
> + * indices in the local and remote used rings, then notify both sides th=
at
> + * their used ring has changed
> + *
> + * You must be sure that the data was actually written to the used rings=
 before
> + * this function is called
> + */
> +static void dma_callback(void *data)
> +{
> + =A0 =A0 =A0 struct vop_dma_cbinfo *cb =3D data;
> + =A0 =A0 =A0 struct vop_vq *vq =3D cb->vq;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "%s: vq %p loc %d rem %d\n", __func__, vq,=
 cb->loc, cb->rem);
> +
> + =A0 =A0 =A0 /* Write the local used index */
> + =A0 =A0 =A0 vq->used.index +=3D cb->loc;
> +
> + =A0 =A0 =A0 /* Write the remote used index */
> + =A0 =A0 =A0 vq->rem_last_used +=3D cb->rem;
> + =A0 =A0 =A0 iowrite16(vq->rem_last_used, &vq->host->used_idx);
> +
> + =A0 =A0 =A0 /* Make sure the indices are written before triggering call=
backs */
> + =A0 =A0 =A0 wmb();
> +
> + =A0 =A0 =A0 /* Trigger the local used callback */
> + =A0 =A0 =A0 dev_dbg(vq->dev, "local used changed, running callback\n");
> + =A0 =A0 =A0 vop_local_used_changed(vq);
> +
> + =A0 =A0 =A0 /* Trigger the remote used callback */
> + =A0 =A0 =A0 dev_dbg(vq->dev, "remote used changed, running callback\n")=
;
> + =A0 =A0 =A0 vop_remote_used_changed(vq);
> +
> + =A0 =A0 =A0 /* Free the callback data */
> + =A0 =A0 =A0 kmem_cache_free(dma_cache, cb);
> +}
> +
> +/*
> + * Take an entry from the local avail ring and add it to the local
> + * used ring with the given length
> + *
> + * NOTE: does not update the used index
> + *
> + * @vq the virtqueue
> + * @avail_idx the index in the avail ring to take the entry from
> + * @used_idx the index in the used ring to put the entry
> + * @used_len the length used
> + */
> +static void vop_loc_avail_to_used(struct vop_vq *vq, unsigned int avail_=
idx,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigne=
d int used_idx, u32 used_len)
> +{
> + =A0 =A0 =A0 u16 id;
> +
> + =A0 =A0 =A0 /* Make sure the indices are inside the rings */
> + =A0 =A0 =A0 avail_idx &=3D (VOP_RING_SIZE - 1);
> + =A0 =A0 =A0 used_idx =A0&=3D (VOP_RING_SIZE - 1);
> +
> + =A0 =A0 =A0 /* Get the index stored in the avail ring */
> + =A0 =A0 =A0 id =3D vq->avail.ring[avail_idx];
> +
> + =A0 =A0 =A0 /* Copy the index and length to the used ring */
> + =A0 =A0 =A0 vq->used.ring[used_idx].id =3D id;
> + =A0 =A0 =A0 vq->used.ring[used_idx].len =3D used_len;
> +}
> +
> +/*
> + * Take an entry from the remote avail ring and add it to the remote
> + * used ring with the given length
> + *
> + * NOTE: does not update the used index
> + *
> + * @vq the virtqueue
> + * @avail_idx the index in the avail ring to take the entry from
> + * @used_idx the index in the used ring to put the entry
> + * @used_len the length used
> + */
> +static void vop_rem_avail_to_used(struct vop_vq *vq, unsigned int avail_=
idx,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigne=
d int used_idx, u32 used_len)
> +{
> + =A0 =A0 =A0 u16 id;
> +
> + =A0 =A0 =A0 /* Make sure the indices are inside the rings */
> + =A0 =A0 =A0 avail_idx &=3D (VOP_RING_SIZE - 1);
> + =A0 =A0 =A0 used_idx =A0&=3D (VOP_RING_SIZE - 1);
> +
> + =A0 =A0 =A0 /* Get the index stored in the avail ring */
> + =A0 =A0 =A0 id =3D le16_to_cpu(vq->guest->avail[avail_idx]);
> +
> + =A0 =A0 =A0 /* Copy the index and length to the used ring */
> + =A0 =A0 =A0 iowrite32(id, &vq->host->used[used_idx].id);
> + =A0 =A0 =A0 iowrite32(used_len, &vq->host->used[used_idx].len);
> +}
> +
> +/*
> + * Return the number of entries available in the local avail ring
> + */
> +static unsigned int loc_num_avail(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 return vq->avail.index - vq->dma.loc_avail;
> +}
> +
> +/*
> + * Return the number of entries available in the remote avail ring
> + */
> +static unsigned int rem_num_avail(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 return le16_to_cpu(vq->guest->avail_idx) - vq->dma.rem_avai=
l;
> +}
> +
> +/*
> + * Return a descriptor id from the local avail ring
> + *
> + * @vq the virtqueue
> + * @idx the index to return the id from
> + */
> +static u16 vop_loc_avail_id(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 idx &=3D (VOP_RING_SIZE - 1);
> + =A0 =A0 =A0 return vq->avail.ring[idx];
> +}
> +
> +/*
> + * Return a descriptor id from the remote avail ring
> + *
> + * @vq the virtqueue
> + * @idx the index to return the id from
> + */
> +static u16 vop_rem_avail_id(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 idx &=3D (VOP_RING_SIZE - 1);
> + =A0 =A0 =A0 return le16_to_cpu(vq->guest->avail[idx]);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Extra helpers for mergeable DMA =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * TODO: the number of bytes being transmitted could be added to the ava=
il
> + * TODO: ring, rather than just an index. I'm not sure it would make muc=
h
> + * TODO: difference, though.
> + */
> +
> +/*
> + * Calculate the number of bytes used in a local descriptor chain
> + *
> + * @vq the virtqueue
> + * @idx the start descriptor index
> + * @return the number of bytes
> + */
> +static unsigned int loc_num_bytes(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 struct vop_loc_desc desc;
> + =A0 =A0 =A0 unsigned int bytes =3D 0;
> +
> + =A0 =A0 =A0 while (true) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_loc_desc(vq, idx, &desc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 bytes +=3D desc.len;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(desc.flags & VOP_DESC_F_NEXT))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 idx =3D desc.next;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return bytes;
> +}
> +
> +/*
> + * Calculate the number of bytes used in a remote descriptor chain
> + *
> + * @vq the virtqueue
> + * @idx the start descriptor index
> + * @return the number of bytes
> + */
> +static unsigned int rem_num_bytes(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 struct vop_loc_desc desc;
> + =A0 =A0 =A0 unsigned int bytes =3D 0;
> +
> + =A0 =A0 =A0 while (true) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_rem_desc(vq, idx, &desc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 bytes +=3D desc.len;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(desc.flags & VOP_DESC_F_NEXT))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 idx =3D desc.next;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return bytes;
> +}
> +
> +/*
> + * Transmit the next local available entry to the remote side, splitting
> + * up the local descriptor as needed
> + *
> + * This routine makes the following assumptions:
> + * 1) The header already has the correct number of buffers set
> + * 2) The available buffers are all PAGE_SIZE
> + */
> +static int vop_dma_xmit(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 struct vop_dma_info *dma =3D &vq->dma;
> + =A0 =A0 =A0 struct dma_chan *chan =3D dma->chan;
> + =A0 =A0 =A0 dma_cookie_t cookie;
> +
> + =A0 =A0 =A0 unsigned int loc_idx, rem_idx;
> + =A0 =A0 =A0 struct vop_loc_desc loc, rem;
> +
> + =A0 =A0 =A0 struct vop_dma_cbinfo *cb;
> + =A0 =A0 =A0 dma_addr_t src, dst;
> + =A0 =A0 =A0 size_t len;
> +
> + =A0 =A0 =A0 unsigned int loc_total =3D 0;
> + =A0 =A0 =A0 unsigned int rem_total =3D 0;
> + =A0 =A0 =A0 unsigned int bufs_used =3D 0;
> +
> + =A0 =A0 =A0 /* Check that there is a local descriptor available */
> + =A0 =A0 =A0 if (!loc_num_avail(vq)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "No local descriptors avai=
lable\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOSPC;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Get the starting entry from each available ring */
> + =A0 =A0 =A0 loc_idx =3D vop_loc_avail_id(vq, dma->loc_avail);
> + =A0 =A0 =A0 rem_idx =3D vop_rem_avail_id(vq, dma->rem_avail);
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "rem_avail %d loc_num_bytes %d\n", rem_num=
_avail(vq), loc_num_bytes(vq, loc_idx));
> +
> + =A0 =A0 =A0 /* Check that there are enough remote buffers available */
> + =A0 =A0 =A0 if (rem_num_avail(vq) * PAGE_SIZE < loc_num_bytes(vq, loc_i=
dx)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "Insufficient remote descr=
iptors available\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOSPC;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Allocate DMA callback data */
> + =A0 =A0 =A0 cb =3D kmem_cache_alloc(dma_cache, GFP_KERNEL);
> + =A0 =A0 =A0 if (!cb) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "Unable to allocate DMA ca=
llback data\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Load the starting descriptors */
> + =A0 =A0 =A0 vop_loc_desc(vq, loc_idx, &loc);
> + =A0 =A0 =A0 vop_rem_desc(vq, rem_idx, &rem);
> +
> + =A0 =A0 =A0 while (true) {
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dst =3D rem.addr + 0x80000000;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 src =3D loc.addr;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 len =3D min(loc.len, rem.len);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "DMA xmit dst %.8x src %.8=
x len %d\n", dst, src, len);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cookie =3D dma_async_memcpy_raw_to_raw(chan=
, dst, src, len);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (dma_submit_error(cookie)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "DMA submi=
t error\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free_cb;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc.len -=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem.len -=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc.addr +=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem.addr +=3D len;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc_total +=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem_total +=3D len;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "loc.len %d rem.len %d\n",=
 loc.len, rem.len);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "loc.addr %.8x rem.addr %.=
8x\n", loc.addr, rem.addr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "loc_total %d rem_total %d=
\n", loc_total, rem_total);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (loc.len =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "local: de=
scriptor depleted, loading next\n");
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(loc.flags & VOP_DESC_=
F_NEXT)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq-=
>dev, "local: no next descriptor, chain finished\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "local: fe=
tching next descriptor\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc_idx =3D loc.next;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_loc_desc(vq, loc_idx, &=
loc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (rem.len =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "remote: d=
escriptor depleted, adding to used\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_rem_avail_to_used(vq, d=
ma->rem_avail + bufs_used, dma->rem_used + bufs_used, rem_total);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bufs_used++;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "remote: f=
etching next descriptor\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem_idx =3D vop_rem_avail_i=
d(vq, dma->rem_avail + bufs_used);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_rem_desc(vq, rem_idx, &=
rem);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem_total =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Add the last remote descriptor to the used ring */
> + =A0 =A0 =A0 BUG_ON(rem_total =3D=3D 0);
> + =A0 =A0 =A0 dev_dbg(vq->dev, "adding last remote descriptor to used rin=
g\n");
> + =A0 =A0 =A0 vop_rem_avail_to_used(vq, dma->rem_avail + bufs_used, dma->=
rem_used + bufs_used, rem_total);
> + =A0 =A0 =A0 bufs_used++;
> +
> + =A0 =A0 =A0 /* Add the local descriptor to the sude ring */
> + =A0 =A0 =A0 dev_dbg(vq->dev, "adding only local descriptor to used ring=
\n");
> + =A0 =A0 =A0 vop_loc_avail_to_used(vq, dma->loc_avail, dma->loc_used, lo=
c_total);
> +
> + =A0 =A0 =A0 /* Make very sure that everything written to the rings actu=
ally happened
> + =A0 =A0 =A0 =A0* bofer the DMA callback can be triggered */
> + =A0 =A0 =A0 wmb();
> +
> + =A0 =A0 =A0 /* Set up the DMA callback information */
> + =A0 =A0 =A0 cb->vq =3D vq;
> + =A0 =A0 =A0 cb->loc =3D 1;
> + =A0 =A0 =A0 cb->rem =3D bufs_used;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "setup DMA callback vq %p loc %d rem %d\n"=
, vq, 1, bufs_used);
> +
> + =A0 =A0 =A0 /* Trigger an interrupt when the DMA completes to update th=
e used
> + =A0 =A0 =A0 =A0* indices and trigger the necessary callbacks */
> + =A0 =A0 =A0 cookie =3D dma_async_interrupt(chan, dma_callback, cb);
> + =A0 =A0 =A0 if (dma_submit_error(cookie)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "DMA interrupt submit erro=
r\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free_cb;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Everything was successful, so update the DMA resolver's =
state */
> + =A0 =A0 =A0 dma->loc_avail++;
> + =A0 =A0 =A0 dma->rem_avail +=3D bufs_used;
> + =A0 =A0 =A0 dma->loc_used++;
> + =A0 =A0 =A0 dma->rem_used +=3D bufs_used;
> +
> + =A0 =A0 =A0 /* Start the DMA */
> + =A0 =A0 =A0 dev_dbg(vq->dev, "DMA xmit setup successful, starting\n");
> + =A0 =A0 =A0 dma_async_memcpy_issue_pending(chan);
> +
> + =A0 =A0 =A0 return 0;
> +
> +out_free_cb:
> + =A0 =A0 =A0 kmem_cache_free(dma_cache, cb);
> + =A0 =A0 =A0 return -ENOMEM;
> +}
> +
> +/*
> + * Receive the next remote available entry to the local side, splitting
> + * up the remote descriptor as needed
> + *
> + * This routine makes the following assumptions:
> + * 1) The header already has the correct number of buffers set
> + * 2) The available buffers are all PAGE_SIZE
> + */
> +static int vop_dma_recv(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 struct vop_dma_info *dma =3D &vq->dma;
> + =A0 =A0 =A0 struct dma_chan *chan =3D dma->chan;
> + =A0 =A0 =A0 dma_cookie_t cookie;
> +
> + =A0 =A0 =A0 unsigned int loc_idx, rem_idx;
> + =A0 =A0 =A0 struct vop_loc_desc loc, rem;
> +
> + =A0 =A0 =A0 struct vop_dma_cbinfo *cb;
> + =A0 =A0 =A0 dma_addr_t src, dst;
> + =A0 =A0 =A0 size_t len;
> +
> + =A0 =A0 =A0 unsigned int loc_total =3D 0;
> + =A0 =A0 =A0 unsigned int rem_total =3D 0;
> + =A0 =A0 =A0 unsigned int bufs_used =3D 0;
> +
> + =A0 =A0 =A0 /* Check that there is a remote descriptor available */
> + =A0 =A0 =A0 if (!rem_num_avail(vq)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "No remote descriptors ava=
ilable\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOSPC;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Get the starting entry from each available ring */
> + =A0 =A0 =A0 loc_idx =3D vop_loc_avail_id(vq, dma->loc_avail);
> + =A0 =A0 =A0 rem_idx =3D vop_rem_avail_id(vq, dma->rem_avail);
> +
> + =A0 =A0 =A0 /* Check that there are enough local buffers available */
> + =A0 =A0 =A0 if (loc_num_avail(vq) * PAGE_SIZE < rem_num_bytes(vq, rem_i=
dx)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "Insufficient local descri=
ptors available\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOSPC;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Allocate DMA callback data */
> + =A0 =A0 =A0 cb =3D kmem_cache_alloc(dma_cache, GFP_KERNEL);
> + =A0 =A0 =A0 if (!cb) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "Unable to allocate DMA ca=
llback data\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Load the starting descriptors */
> + =A0 =A0 =A0 vop_loc_desc(vq, loc_idx, &loc);
> + =A0 =A0 =A0 vop_rem_desc(vq, rem_idx, &rem);
> +
> + =A0 =A0 =A0 while (true) {
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dst =3D loc.addr;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 src =3D rem.addr + 0x80000000;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 len =3D min(loc.len, rem.len);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "DMA recv dst %.8x src %.8=
x len %d\n", dst, src, len);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cookie =3D dma_async_memcpy_raw_to_raw(chan=
, dst, src, len);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (dma_submit_error(cookie)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "DMA submi=
t error\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free_cb;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc.len -=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem.len -=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc.addr +=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem.addr +=3D len;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc_total +=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem_total +=3D len;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (rem.len =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(rem.flags & VOP_DESC_=
F_NEXT))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rem_idx =3D rem.next;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_rem_desc(vq, rem_idx, &=
rem);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (loc.len =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_loc_avail_to_used(vq, d=
ma->loc_avail + bufs_used, dma->loc_used + bufs_used, loc_total);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bufs_used++;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc_idx =3D vop_loc_avail_i=
d(vq, dma->loc_avail + bufs_used);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_loc_desc(vq, loc_idx, &=
loc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 loc_total =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Add the last local descriptor to the used ring */
> + =A0 =A0 =A0 BUG_ON(loc_total =3D=3D 0);
> + =A0 =A0 =A0 vop_loc_avail_to_used(vq, dma->loc_avail + bufs_used, dma->=
loc_used + bufs_used, loc_total);
> + =A0 =A0 =A0 bufs_used++;
> +
> + =A0 =A0 =A0 /* Add the remote descriptor to the used ring */
> + =A0 =A0 =A0 vop_rem_avail_to_used(vq, dma->rem_avail, dma->rem_used, re=
m_total);
> +
> + =A0 =A0 =A0 /* Make very sure that everything written to the rings actu=
ally happened
> + =A0 =A0 =A0 =A0* before the DMA callback can be triggered */
> + =A0 =A0 =A0 wmb();
> +
> + =A0 =A0 =A0 /* Set up the DMA callback information */
> + =A0 =A0 =A0 cb->vq =3D vq;
> + =A0 =A0 =A0 cb->loc =3D bufs_used;
> + =A0 =A0 =A0 cb->rem =3D 1;
> +
> + =A0 =A0 =A0 /* Trigger an interrupt when the DMA completes to update th=
e used
> + =A0 =A0 =A0 =A0* indices and trigger the necessary callbacks */
> + =A0 =A0 =A0 cookie =3D dma_async_interrupt(chan, dma_callback, cb);
> + =A0 =A0 =A0 if (dma_submit_error(cookie)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "DMA interrupt submit erro=
r\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free_cb;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Everything was successful, so update the DMA resolver's =
state */
> + =A0 =A0 =A0 dma->loc_avail +=3D bufs_used;
> + =A0 =A0 =A0 dma->rem_avail++;
> + =A0 =A0 =A0 dma->loc_used +=3D bufs_used;
> + =A0 =A0 =A0 dma->rem_used++;
> +
> + =A0 =A0 =A0 /* Start the DMA */
> + =A0 =A0 =A0 dev_dbg(vq->dev, "DMA recv setup successful, starting\n");
> + =A0 =A0 =A0 dma_async_memcpy_issue_pending(chan);
> +
> + =A0 =A0 =A0 return 0;
> +
> +out_free_cb:
> + =A0 =A0 =A0 kmem_cache_free(dma_cache, cb);
> + =A0 =A0 =A0 return -ENOMEM;
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Virtqueue Ops Infrastructure =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * Modify the struct virtio_net_hdr_mrg_rxbuf's num_buffers field to acc=
ount
> + * for the split that will happen in the DMA xmit routine
> + *
> + * This assumes that both sides have the same PAGE_SIZE
> + */
> +static void vop_fixup_vnet_mrg_hdr(struct scatterlist sg[], unsigned int=
 out)
> +{
> + =A0 =A0 =A0 struct virtio_net_hdr *hdr;
> + =A0 =A0 =A0 struct virtio_net_hdr_mrg_rxbuf *mhdr;
> + =A0 =A0 =A0 unsigned int bytes =3D 0;
> +
> + =A0 =A0 =A0 /* There must be a header + data, at the least */
> + =A0 =A0 =A0 BUG_ON(out < 2);
> +
> + =A0 =A0 =A0 /* The first entry must be the structure */
> + =A0 =A0 =A0 BUG_ON(sg->length !=3D sizeof(struct virtio_net_hdr_mrg_rxb=
uf));
> +
> + =A0 =A0 =A0 hdr =3D sg_virt(sg);
> + =A0 =A0 =A0 mhdr =3D sg_virt(sg);
> +
> + =A0 =A0 =A0 /* We merge buffers together, so just count up the number o=
f bytes
> + =A0 =A0 =A0 =A0* needed, then figure out how many pages that will be */
> + =A0 =A0 =A0 for (/* none */; out; out--, sg =3D sg_next(sg))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 bytes +=3D sg->length;
> +
> + =A0 =A0 =A0 /* Of course, nobody ever imagined that we might actually u=
se
> + =A0 =A0 =A0 =A0* this on machines with different endianness...
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* We force little-endian for now, since that's what our =
host is */
> + =A0 =A0 =A0 mhdr->num_buffers =3D cpu_to_le16(DIV_ROUND_UP(bytes, PAGE_=
SIZE));
> +
> + =A0 =A0 =A0 /* Might as well fix up the other fields while we're at it =
*/
> + =A0 =A0 =A0 hdr->hdr_len =3D cpu_to_le16(hdr->hdr_len);
> + =A0 =A0 =A0 hdr->gso_size =3D cpu_to_le16(hdr->gso_size);
> + =A0 =A0 =A0 hdr->csum_start =3D cpu_to_le16(hdr->csum_start);
> + =A0 =A0 =A0 hdr->csum_offset =3D cpu_to_le16(hdr->csum_offset);
> +}
> +
> +/*
> + * Add a buffer to our local descriptors and the local avail ring
> + *
> + * NOTE: there hasn't been any transfer yet, just adding to local
> + * NOTE: rings. The kick() will process any DMA that needs to happen
> + *
> + * @return 0 on success, -ERRNO otherwise
> + */
> +static int vop_add_buf(struct virtqueue *_vq, struct scatterlist sg[],
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned int out, unsigned i=
nt in, void *data)
> +{
> + =A0 =A0 =A0 /* For now, we'll just add the buffers to our local descrip=
tors and
> + =A0 =A0 =A0 =A0* avail ring */
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> + =A0 =A0 =A0 unsigned int i, avail, head, uninitialized_var(prev);
> +
> + =A0 =A0 =A0 BUG_ON(data =3D=3D NULL);
> + =A0 =A0 =A0 BUG_ON(out + in =3D=3D 0);
> +
> + =A0 =A0 =A0 /* Make sure we have space for this to succeed */
> + =A0 =A0 =A0 if (vq->num_free < out + in) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "No free space left: len=
=3D%d free=3D%d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out + in, v=
q->num_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOSPC;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* If this is an xmit buffer from virtio_net, fixup the hea=
der */
> + =A0 =A0 =A0 if (out > 1) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "Fixing up virtio_net head=
er\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_fixup_vnet_mrg_hdr(sg, out);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 head =3D vq->free_head;
> +
> + =A0 =A0 =A0 /* DMA map the scatterlist */
> + =A0 =A0 =A0 if (vop_dma_map_sg(vq->dev, sg, out, in)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "Failed to DMA map scatter=
list\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* We're about to use some buffers from the free list */
> + =A0 =A0 =A0 vq->num_free -=3D out + in;
> +
> + =A0 =A0 =A0 for (i =3D vq->free_head; out; i =3D vop_get_desc_next(vq, =
i), out--) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_flags(vq, i, VOP_DESC_F_NEXT);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_addr(vq, i, sg_dma_address(sg)=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_len(vq, i, sg->length);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 prev =3D i;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 for (/* none */; in; i =3D vop_get_desc_next(vq, i), in--) =
{
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_flags(vq, i, VOP_DESC_F_NEXT |=
 VOP_DESC_F_WRITE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_addr(vq, i, sg_dma_address(sg)=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_len(vq, i, sg->length);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 prev =3D i;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Last one doesn't continue */
> + =A0 =A0 =A0 vop_set_desc_flags(vq, prev, vop_get_desc_flags(vq, prev) &=
 ~VOP_DESC_F_NEXT);
> +
> + =A0 =A0 =A0 /* Update the free pointer */
> + =A0 =A0 =A0 vq->free_head =3D i;
> +
> + =A0 =A0 =A0 /* Set token */
> + =A0 =A0 =A0 vq->data[head] =3D data;
> +
> + =A0 =A0 =A0 /* Add an entry for the head of the chain into the avail ar=
ray, but
> + =A0 =A0 =A0 =A0* don't update avail->idx until kick() */
> + =A0 =A0 =A0 avail =3D (vq->avail.index + vq->num_added++) & (VOP_RING_S=
IZE - 1);
> + =A0 =A0 =A0 vq->avail.ring[avail] =3D head;
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "Added buffer head %i to %p\n", head, vq);
> + =A0 =A0 =A0 debug_dump_rings(vq, "Added buffer(s), dumping rings");
> +
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static inline bool loc_more_used(const struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 return vq->loc_last_used !=3D vq->used.index;
> +}
> +
> +static void detach_buf(struct vop_vq *vq, unsigned int head)
> +{
> + =A0 =A0 =A0 dma_addr_t addr;
> + =A0 =A0 =A0 unsigned int idx, len;
> + =A0 =A0 =A0 enum dma_data_direction dir;
> + =A0 =A0 =A0 struct vop_loc_desc desc;
> +
> + =A0 =A0 =A0 /* Clear data pointer */
> + =A0 =A0 =A0 vq->data[head] =3D NULL;
> +
> + =A0 =A0 =A0 /* Put the chain back on the free list, unmapping as we go =
*/
> + =A0 =A0 =A0 idx =3D head;
> + =A0 =A0 =A0 while (true) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_loc_desc(vq, idx, &desc);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 addr =3D desc.addr;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 len =A0=3D desc.len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dir =A0=3D (desc.flags & VOP_DESC_F_WRITE) =
? DMA_FROM_DEVICE : DMA_TO_DEVICE;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Unmap the entry */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(vq->dev, addr, len, dir);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->num_free++;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* If there is no next descriptor, we're do=
ne */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(desc.flags & VOP_DESC_F_NEXT))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 idx =3D desc.next;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 vop_set_desc_next(vq, idx, vq->free_head);
> + =A0 =A0 =A0 vq->free_head =3D head;
> +}
> +
> +/*
> + * Get a buffer from the used ring
> + *
> + * @return the data token given to add_buf(), or NULL if there
> + * =A0 =A0 =A0 =A0 are no remaining buffers
> + */
> +static void *vop_get_buf(struct virtqueue *_vq, unsigned int *len)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> + =A0 =A0 =A0 unsigned int head, used;
> + =A0 =A0 =A0 void *ret;
> +
> + =A0 =A0 =A0 if (!loc_more_used(vq)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "No more buffers in queue\=
n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return NULL;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 used =3D vq->loc_last_used & (VOP_RING_SIZE - 1);
> + =A0 =A0 =A0 head =3D vq->used.ring[used].id;
> + =A0 =A0 =A0 *len =3D vq->used.ring[used].len;
> +
> + =A0 =A0 =A0 BUG_ON(head >=3D VOP_RING_SIZE);
> + =A0 =A0 =A0 BUG_ON(!vq->data[head]);
> +
> + =A0 =A0 =A0 /* detach_buf() clears data, save it now */
> + =A0 =A0 =A0 ret =3D vq->data[head];
> + =A0 =A0 =A0 detach_buf(vq, head);
> +
> + =A0 =A0 =A0 /* Update the last local used_idx */
> + =A0 =A0 =A0 vq->loc_last_used++;
> +
> + =A0 =A0 =A0 return ret;
> +}
> +
> +/*
> + * The avail ring changed, so we need to start as much DMA as we can
> + */
> +static void vop_kick(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "kick: making %d new buffers available\n",=
 vq->num_added);
> + =A0 =A0 =A0 vq->avail.index +=3D vq->num_added;
> + =A0 =A0 =A0 vq->num_added =3D 0;
> +
> + =A0 =A0 =A0 /* Run the DMA resolver */
> + =A0 =A0 =A0 dev_dbg(vq->dev, "kick: using resolver %pS\n", vq->resolve)=
;
> + =A0 =A0 =A0 schedule_work(&vq->work);
> +}
> +
> +/*
> + * Try to disable callbacks on the used ring (unreliable)
> + */
> +static void vop_disable_cb(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> + =A0 =A0 =A0 struct virtio_device *vdev =3D _vq->vdev;
> +
> + =A0 =A0 =A0 dev_dbg(&vdev->dev, "disable callbacks\n");
> + =A0 =A0 =A0 vq->flags =3D VOP_F_NO_INTERRUPT;
> +#if 0
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* FIXME: using this causes the host -> guest transfer ra=
te to
> + =A0 =A0 =A0 =A0* FIXME: intermittently slow to 1/10th of the normal rat=
e
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 vop_set_guest_flags(vq, vq->flags);
> +#endif
> +}
> +
> +/*
> + * Enable callbacks on changes to the used ring
> + *
> + * @return false if there are more pending buffers
> + * =A0 =A0 =A0 =A0 true otherwise
> + */
> +static bool vop_enable_cb(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> +
> + =A0 =A0 =A0 /* We optimistically enable interrupts, then check if there
> + =A0 =A0 =A0 =A0* was more work to do */
> + =A0 =A0 =A0 dev_dbg(vq->dev, "enable callbacks\n");
> + =A0 =A0 =A0 vq->flags =3D 0;
> +#if 0
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* FIXME: using this causes the host -> guest transfer ra=
te to
> + =A0 =A0 =A0 =A0* FIXME: intermittently slow to 1/10th of the normal rat=
e
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 vop_set_guest_flags(vq, vq->flags);
> +#endif
> +
> + =A0 =A0 =A0 if (unlikely(loc_more_used(vq)))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return false;
> +
> + =A0 =A0 =A0 return true;
> +}
> +
> +static struct virtqueue_ops vop_vq_ops =3D {
> + =A0 =A0 =A0 .add_buf =A0 =A0 =A0 =A0=3D vop_add_buf,
> + =A0 =A0 =A0 .get_buf =A0 =A0 =A0 =A0=3D vop_get_buf,
> + =A0 =A0 =A0 .kick =A0 =A0 =A0 =A0 =A0 =3D vop_kick,
> + =A0 =A0 =A0 .disable_cb =A0 =A0 =3D vop_disable_cb,
> + =A0 =A0 =A0 .enable_cb =A0 =A0 =A0=3D vop_enable_cb,
> +};
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Virtio Device Infrastructure =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +/* Read some bytes from the host's configuration area */
> +static void vopc_get(struct virtio_device *_vdev, unsigned offset, void =
*buf,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned len)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 void __iomem *config =3D vdev->host_status->config;
> +
> + =A0 =A0 =A0 memcpy_fromio(buf, config + offset, len);
> +}
> +
> +/* Write some bytes to the host's configuration area */
> +static void vopc_set(struct virtio_device *_vdev, unsigned offset,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const void *buf, unsigned len)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 void __iomem *config =3D vdev->host_status->config;
> +
> + =A0 =A0 =A0 memcpy_toio(config + offset, buf, len);
> +}
> +
> +/* Read your own status bits */
> +static u8 vopc_get_status(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 u32 status;
> +
> + =A0 =A0 =A0 status =3D le32_to_cpu(vdev->guest_status->status);
> + =A0 =A0 =A0 dev_dbg(&vdev->vdev.dev, "%s(): -> 0x%.2x\n", __func__, (u8=
)status);
> +
> + =A0 =A0 =A0 return (u8)status;
> +}
> +
> +static void vopc_set_status(struct virtio_device *_vdev, u8 status)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 u32 old_status;
> +
> + =A0 =A0 =A0 old_status =3D le32_to_cpu(vdev->guest_status->status);
> + =A0 =A0 =A0 vdev->guest_status->status =3D cpu_to_le32(status);
> +
> + =A0 =A0 =A0 dev_dbg(&vdev->vdev.dev, "%s(): <- 0x%.2x (was 0x%.2x)\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, status, old_statu=
s);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* FIXME: we really need to notify the other side when st=
atus changes
> + =A0 =A0 =A0 =A0* FIXME: happen, so that they can take some action
> + =A0 =A0 =A0 =A0*/
> +}
> +
> +static void vopc_reset(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> +
> + =A0 =A0 =A0 dev_dbg(&vdev->vdev.dev, "%s(): status reset\n", __func__);
> + =A0 =A0 =A0 vdev->guest_status->status =3D cpu_to_le32(0);
> +}
> +
> +/* Find the given virtqueue */
> +static struct virtqueue *vopc_find_vq(struct virtio_device *_vdev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0unsigned index,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0void (*cb)(struct virtqueue *vq))
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 struct vop_vq *vq =3D &vdev->virtqueues[index];
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 /* Check that we support the virtqueue at this index */
> + =A0 =A0 =A0 if (index >=3D ARRAY_SIZE(vdev->virtqueues)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&vdev->vdev.dev, "no virtqueue for =
index %d\n", index);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ERR_PTR(-ENODEV);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* HACK: we only support virtio_net for now */
> + =A0 =A0 =A0 if (vdev->vdev.id.device !=3D VIRTIO_ID_NET) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&vdev->vdev.dev, "only virtio_net i=
s supported\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ERR_PTR(-ENODEV);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Initialize the virtqueue to a clean state */
> + =A0 =A0 =A0 vq->num_free =3D VOP_RING_SIZE;
> + =A0 =A0 =A0 vq->dev =3D &vdev->vdev.dev;
> + =A0 =A0 =A0 vq->vq.vq_ops =3D &vop_vq_ops;
> +
> + =A0 =A0 =A0 /* Hook up the local virtqueues to the corresponding remote=
 virtqueues */
> + =A0 =A0 =A0 /* TODO: maybe move this to the setup_virtio_net() function=
 */
> + =A0 =A0 =A0 switch (index) {
> + =A0 =A0 =A0 case 0: /* x86 xmit virtqueue, hook to ppc recv virtqueue *=
/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->guest =3D vdev->loc + 2048;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->host =A0=3D vdev->rem + 2048;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->resolve =3D vop_dma_recv;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->kick_val =3D 0x8;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 1: /* x86 recv virtqueue, hook to ppc xmit virtqueue *=
/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->guest =3D vdev->loc + 1024;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->host =A0=3D vdev->rem + 1024;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->resolve =3D vop_dma_xmit;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->kick_val =3D 0x4;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 2: /* x86 ctrl virtqueue -- ppc ctrl virtqueue */
> + =A0 =A0 =A0 default:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "Unsupported virtqueue\n")=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ERR_PTR(-ENODEV);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "vq %d guest %p host %p\n", index, vq->gue=
st, vq->host);
> +
> + =A0 =A0 =A0 /* Initialize the descriptor, avail, and used rings */
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_addr(vq, i, 0x0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_len(vq, i, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_flags(vq, i, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_next(vq, i, (i + 1) & (VOP_RIN=
G_SIZE - 1));
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->avail.ring[i] =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->used.ring[i].id =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->used.ring[i].len =3D 0;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 vq->avail.index =3D 0;
> + =A0 =A0 =A0 vop_set_guest_flags(vq, 0);
> +
> + =A0 =A0 =A0 /* This is the guest, the host has already initialized the =
rings for us */
> + =A0 =A0 =A0 debug_dump_rings(vq, "found a virtqueue, dumping rings");
> +
> + =A0 =A0 =A0 vq->vq.callback =3D cb;
> + =A0 =A0 =A0 vq->vq.vdev =3D &vdev->vdev;
> +
> + =A0 =A0 =A0 return &vq->vq;
> +}
> +
> +static void vopc_del_vq(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 /* FIXME: make sure that DMA has stopped by this point */
> +
> + =A0 =A0 =A0 /* Unmap and remove all outstanding descriptors from the ri=
ng */
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (vq->data[i]) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "cleanup d=
etach buffer at index %d\n", i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 detach_buf(vq, i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 debug_dump_rings(vq, "virtqueue destroyed, dumping rings");
> +}
> +
> +/* Read the host's advertised features */
> +static u32 vopc_get_features(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 u32 ret;
> +
> + =A0 =A0 =A0 ret =3D vop_get_host_features(vdev);
> + =A0 =A0 =A0 dev_dbg(&vdev->vdev.dev, "%s(): host features 0x%.8x\n", __=
func__, ret);
> +
> + =A0 =A0 =A0 return ret;
> +}
> +
> +/* At this point, we've chosen whichever features we can use and
> + * put them into the vdev->features array. We should probably notify
> + * the host at this point, but how will virtio react? */
> +static void vopc_finalize_features(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 struct device *dev =3D &vdev->vdev.dev;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* TODO: notify the other side at this point
> + =A0 =A0 =A0 =A0*/
> +
> + =A0 =A0 =A0 vdev->guest_status->features[0] =3D cpu_to_le32(vdev->vdev.=
features[0]);
> + =A0 =A0 =A0 dev_dbg(dev, "%s(): final features 0x%.8lx\n", __func__, vd=
ev->vdev.features[0]);
> +}
> +
> +static struct virtio_config_ops vop_config_ops =3D {
> + =A0 =A0 =A0 .get =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_get,
> + =A0 =A0 =A0 .set =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_set,
> + =A0 =A0 =A0 .get_status =A0 =A0 =A0 =A0 =A0 =A0 =3D vopc_get_status,
> + =A0 =A0 =A0 .set_status =A0 =A0 =A0 =A0 =A0 =A0 =3D vopc_set_status,
> + =A0 =A0 =A0 .reset =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_reset,
> + =A0 =A0 =A0 .find_vq =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_find_vq,
> + =A0 =A0 =A0 .del_vq =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D vopc_del_vq,
> + =A0 =A0 =A0 .get_features =A0 =A0 =A0 =A0 =A0 =3D vopc_get_features,
> + =A0 =A0 =A0 .finalize_features =A0 =A0 =A0=3D vopc_finalize_features,
> +};
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Last-minute device setup code =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * Do the last minute setup for virtio_net, now that the host memory is
> + * valid. This includes setting up pointers to the correct queues so tha=
t
> + * we can just start the virtqueues when the driver registers
> + */
> +static void setup_virtio_net(struct vop_vdev *vdev)
> +{
> + =A0 =A0 =A0 /* TODO: move some of the setup code from find_vq() here */
> +}
> +
> +/*
> + * Do any last minute setup for a device just before starting it
> + *
> + * The host memory is now valid, so you should be setting up any pointer=
s
> + * the device needs to the host memory
> + */
> +static int vop_setup_device(struct vop_dev *priv, int devnum)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D &priv->devices[devnum];
> + =A0 =A0 =A0 struct device *dev =3D priv->dev;
> +
> + =A0 =A0 =A0 if (devnum >=3D ARRAY_SIZE(priv->devices)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(dev, "Unknown virtio_device %d\n", =
devnum);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Setup the device's pointers to host memory */
> + =A0 =A0 =A0 vdev->rem =3D priv->host_mem =A0+ (devnum * 4096);
> + =A0 =A0 =A0 vdev->host_status =3D vdev->rem;
> +
> + =A0 =A0 =A0 switch (devnum) {
> + =A0 =A0 =A0 case 0: /* virtio_net */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 setup_virtio_net(vdev);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 default:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(dev, "Device %d not implemented\n",=
 devnum);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return 0;
> +}
> +
> +/*
> + * Initialize and attempt to register a virtio_device
> + *
> + * @priv the driver data
> + * @devnum the virtio_device number (index into priv->devices)
> + */
> +static int vop_start_device(struct vop_dev *priv, int devnum)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D &priv->devices[devnum];
> + =A0 =A0 =A0 struct device *dev =3D priv->dev;
> + =A0 =A0 =A0 int ret;
> +
> + =A0 =A0 =A0 /* Check that we know about the device */
> + =A0 =A0 =A0 if (devnum >=3D ARRAY_SIZE(priv->devices)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(dev, "Unknown virtio_device %d\n", =
devnum);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 vdev->status =3D 0;
> +
> + =A0 =A0 =A0 /* Do any last minute device-specific setup now that the
> + =A0 =A0 =A0 =A0* host memory is valid */
> + =A0 =A0 =A0 ret =3D vop_setup_device(priv, devnum);
> + =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(dev, "Unable to setup device %d\n",=
 devnum);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Register the device with the virtio subsystem */
> + =A0 =A0 =A0 ret =3D register_virtio_device(&vdev->vdev);
> + =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(dev, "Unable to register device %d\=
n", devnum);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 vdev->status =3D VOP_DEVICE_REGISTERED;
> + =A0 =A0 =A0 return 0;
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Work Functions =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * Start as much DMA as we can on the given virtqueue
> + *
> + * This is put on the system shared queue, and will start us much DMA as=
 is
> + * available when it is called. This should be triggered when the host a=
dds
> + * things to the avail rings, and when the guest adds things to the inte=
rnal
> + * avail rings
> + *
> + * Make sure it doesn't sleep for too long, you're on the shared queue
> + */
> +static void vop_dma_work(struct work_struct *work)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D container_of(work, struct vop_vq, wor=
k);
> + =A0 =A0 =A0 int ret;
> +
> + =A0 =A0 =A0 /* Start as many DMA transactions as we can, immediately */
> + =A0 =A0 =A0 while (true) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D vq->resolve(vq);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 }
> +}
> +
> +/*
> + * Remove all virtio devices immediately
> + *
> + * This will be called by the host to make sure that we are in a stopped
> + * state. It should be callable when everything is already stopped.
> + *
> + * Make sure it doesn't sleep for too long, you're on the shared queue
> + */
> +static void vop_reset_work(struct work_struct *work)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv =3D container_of(work, struct vop_dev,=
 reset_work);
> + =A0 =A0 =A0 struct device *dev =3D priv->dev;
> + =A0 =A0 =A0 struct vop_vdev *vdev;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(dev, "Resetting all virtio devices\n");
> + =A0 =A0 =A0 mutex_lock(&priv->mutex);
> +
> + =A0 =A0 =A0 for (i =3D 0; i < ARRAY_SIZE(priv->devices); i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev =3D &priv->devices[i];
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (vdev->status & VOP_DEVICE_REGISTERED) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(dev, "Unregistering=
 virtio_device #%d\n", i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unregister_virtio_device(&v=
dev->vdev);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev->status &=3D ~VOP_DEVICE_REGISTERED;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 if (priv->host_mem) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(priv->host_mem);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->host_mem =3D NULL;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 mutex_unlock(&priv->mutex);
> +}
> +
> +/*
> + * This will map the host's memory, as well as start the devices that th=
e host
> + * requested
> + *
> + * Mailbox registers contents:
> + * IMR0 - the host memory physical address (must be <1GB)
> + * IMR1 - the devices the host wants started
> + */
> +static void vop_start_work(struct work_struct *work)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv =3D container_of(work, struct vop_dev,=
 start_work);
> + =A0 =A0 =A0 struct device *dev =3D priv->dev;
> + =A0 =A0 =A0 struct vop_vdev *vdev;
> + =A0 =A0 =A0 u32 address, devices;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 dev_dbg(dev, "Starting requested virtio devices\n");
> + =A0 =A0 =A0 mutex_lock(&priv->mutex);
> +
> + =A0 =A0 =A0 /* Read the requested address and devices from the mailbox =
registers */
> + =A0 =A0 =A0 address =3D ioread32(priv->immr + IMR0_OFFSET);
> + =A0 =A0 =A0 devices =3D ioread32(priv->immr + IMR1_OFFSET);
> +
> + =A0 =A0 =A0 dev_dbg(dev, "address 0x%.8x\n", address);
> + =A0 =A0 =A0 dev_dbg(dev, "devices 0x%.8x\n", devices);
> +
> + =A0 =A0 =A0 /* Remap the host's registers */
> + =A0 =A0 =A0 priv->host_mem =3D ioremap(address + 0x80000000, VOP_HOST_M=
EM_SIZE);
> + =A0 =A0 =A0 if (!priv->host_mem) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(dev, "Unable to ioremap host memory=
\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_unlock;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Start the requested devices */
> + =A0 =A0 =A0 for (i =3D 0; i < ARRAY_SIZE(priv->devices); i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev =3D &priv->devices[i];
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (devices & (1 << i)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(dev, "Starting virt=
io_device #%d\n", i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_start_device(priv, i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> +out_unlock:
> + =A0 =A0 =A0 mutex_unlock(&priv->mutex);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Interrupt Handling =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * Schedule the work function for a given virtqueue only if the associat=
ed
> + * device is up and running. Otherwise, ignore the request
> + *
> + * @priv the private driver data
> + * @dev the virtio_device number in priv->devices[]
> + * @queue the virtqueue in vdev->virtqueues[]
> + */
> +static void schedule_work_if_ready(struct vop_dev *priv, int dev, int qu=
eue)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D &priv->devices[dev];
> + =A0 =A0 =A0 struct vop_vq *vq =3D &vdev->virtqueues[queue];
> +
> + =A0 =A0 =A0 if (vdev->status & VOP_DEVICE_REGISTERED)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 schedule_work(&vq->work);
> +}
> +
> +static irqreturn_t vdev_interrupt(int irq, void *dev_id)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv =3D dev_id;
> + =A0 =A0 =A0 struct device *dev =3D priv->dev;
> + =A0 =A0 =A0 u32 imisr, idr;
> +
> + =A0 =A0 =A0 imisr =3D ioread32(priv->immr + IMISR_OFFSET);
> + =A0 =A0 =A0 idr =A0 =3D ioread32(priv->immr + IDR_OFFSET);
> +
> + =A0 =A0 =A0 dev_dbg(dev, "INTERRUPT idr 0x%.8x\n", idr);
> +
> + =A0 =A0 =A0 /* Check the status register for doorbell interrupts */
> + =A0 =A0 =A0 if (!(imisr & 0x8))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return IRQ_NONE;
> +
> + =A0 =A0 =A0 /* Clear all doorbell interrupts */
> + =A0 =A0 =A0 iowrite32(idr, priv->immr + IDR_OFFSET);
> +
> + =A0 =A0 =A0 /* Reset */
> + =A0 =A0 =A0 if (idr & 0x1)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 schedule_work(&priv->reset_work);
> +
> + =A0 =A0 =A0 /* Start */
> + =A0 =A0 =A0 if (idr & 0x2)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 schedule_work(&priv->start_work);
> +
> + =A0 =A0 =A0 /* vdev 0 vq 1 kick */
> + =A0 =A0 =A0 if (idr & 0x4)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 schedule_work_if_ready(priv, 0, 1);
> +
> + =A0 =A0 =A0 /* vdev 0 vq 0 kick */
> + =A0 =A0 =A0 if (idr & 0x8)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 schedule_work_if_ready(priv, 0, 0);
> +
> + =A0 =A0 =A0 if (idr & 0xfffffff0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(dev, "INTERRUPT unhandled 0x%.8x\n"=
, idr & 0xfffffff0);
> +
> + =A0 =A0 =A0 return IRQ_HANDLED;
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Driver insertion time virtio device initialization =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static void vdev_release(struct device *dev)
> +{
> + =A0 =A0 =A0 /* TODO: this should probably do something useful */
> + =A0 =A0 =A0 dev_dbg(dev, "%s: called\n", __func__);
> +}
> +
> +/*
> + * Do any device-specific setup for a virtio device
> + *
> + * This would include things like setting the feature bits for the
> + * device, as well as the device type.
> + *
> + * There is no access to host memory at this point, so don't access it
> + */
> +static void vop_setup_virtio_device(struct vop_dev *priv, int devnum)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D &priv->devices[devnum];
> + =A0 =A0 =A0 struct virtio_net_config *config;
> + =A0 =A0 =A0 unsigned long features =3D 0;
> +
> + =A0 =A0 =A0 /* HACK: we only support device #0 (virtio_net) right now *=
/
> + =A0 =A0 =A0 if (devnum !=3D 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> +
> + =A0 =A0 =A0 /* Generate a random ethernet address for the host to have
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* This way, we could do something board-specific and get=
 an
> + =A0 =A0 =A0 =A0* ethernet address that is consistent per-slot
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 config =3D (struct virtio_net_config *)vdev->guest_status->=
config;
> + =A0 =A0 =A0 random_ether_addr(config->mac);
> + =A0 =A0 =A0 dev_info(priv->dev, "Generated MAC %pM\n", config->mac);
> +
> + =A0 =A0 =A0 /* Set the feature bits for the device */
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_MAC, =A0 =A0 =A0 &features);
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_CSUM, =A0 =A0 =A0&features);
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_GSO, =A0 =A0 =A0 &features);
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_MRG_RXBUF, &features);
> +
> + =A0 =A0 =A0 vdev->guest_status->features[0] =3D cpu_to_le32(features);
> + =A0 =A0 =A0 vdev->vdev.id.device =3D VIRTIO_ID_NET;
> +}
> +
> +/*
> + * Do all of the initialization of all of the virtqueues for a given vir=
tio
> + * device. There is no access to host memory at this point, so don't acc=
ess it
> + *
> + * @devnum the device number in the priv->devices[] array
> + */
> +static void vop_initialize_virtqueues(struct vop_dev *priv, int devnum)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D &priv->devices[devnum];
> + =A0 =A0 =A0 struct vop_vq *vq;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 for (i =3D 0; i < ARRAY_SIZE(vdev->virtqueues); i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq =3D &vdev->virtqueues[i];
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(vq, 0, sizeof(struct vop_vq));
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->immr =3D priv->immr;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->dma.chan =3D priv->chan;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 INIT_WORK(&vq->work, vop_dma_work);
> + =A0 =A0 =A0 }
> +}
> +
> +/*
> + * Do all of the initialization for the virtio devices that is possible =
without
> + * access to the host memory
> + *
> + * This includes setting up the pointers that you can and setting the fe=
ature
> + * bits so that the host can read them before he starts us
> + */
> +static void vop_initialize_devices(struct vop_dev *priv)
> +{
> + =A0 =A0 =A0 struct device *parent =3D priv->dev;
> + =A0 =A0 =A0 struct vop_vdev *vdev;
> + =A0 =A0 =A0 struct device *vdev_dev;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 for (i =3D 0; i < ARRAY_SIZE(priv->devices); i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev =3D &priv->devices[i];
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev_dev =3D &vdev->vdev.dev;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Set up access to the guest memory, host =
memory isn't valid
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* yet, and will have to be set up just b=
efore we start */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev->loc =3D priv->guest_mem + (i * 4096);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev->guest_status =3D vdev->loc;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Initialize all of the device's virtqueue=
s */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_initialize_virtqueues(priv, i);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Zero the configuration space */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(vdev->guest_status, 0, 1024);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Copy parent DMA parameters to this devic=
e */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev_dev->dma_mask =3D parent->dma_mask;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev_dev->dma_parms =3D parent->dma_parms;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev_dev->coherent_dma_mask =3D parent->coh=
erent_dma_mask;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev_dev->release =3D &vdev_release;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev_dev->parent =A0=3D parent;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev->vdev.config =3D &vop_config_ops;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Do any device-specific setup */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_setup_virtio_device(priv, i);
> + =A0 =A0 =A0 }
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* OpenFirmware Device Subsystem =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +static int vdev_of_probe(struct of_device *op, const struct of_device_id=
 *match)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv;
> + =A0 =A0 =A0 dma_cap_mask_t mask;
> + =A0 =A0 =A0 int ret;
> +
> + =A0 =A0 =A0 /* Allocate private data */
> + =A0 =A0 =A0 priv =3D kzalloc(sizeof(*priv), GFP_KERNEL);
> + =A0 =A0 =A0 if (!priv) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "Unable to allocate devic=
e private data\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 dev_set_drvdata(&op->dev, priv);
> + =A0 =A0 =A0 priv->dev =3D &op->dev;
> + =A0 =A0 =A0 mutex_init(&priv->mutex);
> + =A0 =A0 =A0 INIT_WORK(&priv->reset_work, vop_reset_work);
> + =A0 =A0 =A0 INIT_WORK(&priv->start_work, vop_start_work);
> +
> + =A0 =A0 =A0 /* Get a DMA channel */
> + =A0 =A0 =A0 dma_cap_zero(mask);
> + =A0 =A0 =A0 dma_cap_set(DMA_MEMCPY, mask);
> + =A0 =A0 =A0 dma_cap_set(DMA_INTERRUPT, mask);
> + =A0 =A0 =A0 priv->chan =3D dma_request_channel(mask, NULL, NULL);
> + =A0 =A0 =A0 if (!priv->chan) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "Unable to get DMA channe=
l\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free_priv;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Remap IMMR */
> + =A0 =A0 =A0 priv->immr =3D ioremap(get_immrbase(), 0x100000);
> + =A0 =A0 =A0 if (!priv->immr) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "Unable to remap IMMR reg=
isters\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_dma_release_channel;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Set up a static 1GB window into host memory */
> + =A0 =A0 =A0 iowrite32be(LAWAR0_ENABLE | 0x1D, priv->immr + LAWAR0_OFFSE=
T);
> + =A0 =A0 =A0 iowrite32be(POCMR0_ENABLE | 0xC0000, priv->immr + POCMR0_OF=
FSET);
> + =A0 =A0 =A0 iowrite32be(0x0, priv->immr + POTAR0_OFFSET);
> +
> + =A0 =A0 =A0 /* Allocate guest memory */
> + =A0 =A0 =A0 priv->guest_mem =3D dma_alloc_coherent(&op->dev, VOP_GUEST_=
MEM_SIZE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0&priv->guest_mem_addr, GFP_KERNEL);
> + =A0 =A0 =A0 if (!priv->guest_mem) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "Unable to allocate guest=
 memory\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_iounmap_immr;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 memset(priv->guest_mem, 0, VOP_GUEST_MEM_SIZE);
> +
> + =A0 =A0 =A0 /* Program BAR1 so that it will hit the guest memory */
> + =A0 =A0 =A0 iowrite32be(priv->guest_mem_addr >> 12, priv->immr + PITAR0=
_OFFSET);
> +
> + =A0 =A0 =A0 /* Initialize all of the virtio devices with their features=
, etc */
> + =A0 =A0 =A0 vop_initialize_devices(priv);
> +
> + =A0 =A0 =A0 /* Disable mailbox interrupts */
> + =A0 =A0 =A0 iowrite32(0x2 | 0x1, priv->immr + IMIMR_OFFSET);
> +
> + =A0 =A0 =A0 /* Hook up the irq handler */
> + =A0 =A0 =A0 priv->irq =3D irq_of_parse_and_map(op->node, 0);
> + =A0 =A0 =A0 ret =3D request_irq(priv->irq, vdev_interrupt, IRQF_SHARED,=
 driver_name, priv);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free_guest_mem;
> +
> + =A0 =A0 =A0 dev_info(&op->dev, "Virtio-over-PCI guest driver installed\=
n");
> + =A0 =A0 =A0 dev_info(&op->dev, "Physical memory @ 0x%.8x\n", priv->gues=
t_mem_addr);
> + =A0 =A0 =A0 dev_info(&op->dev, "Descriptor ring size: %d entries\n", VO=
P_RING_SIZE);
> + =A0 =A0 =A0 return 0;
> +
> +out_free_guest_mem:
> + =A0 =A0 =A0 dma_free_coherent(&op->dev, VOP_GUEST_MEM_SIZE, priv->guest=
_mem,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->guest_mem_addr);
> +out_iounmap_immr:
> + =A0 =A0 =A0 iounmap(priv->immr);
> +out_dma_release_channel:
> + =A0 =A0 =A0 dma_release_channel(priv->chan);
> +out_free_priv:
> + =A0 =A0 =A0 kfree(priv);
> +out_return:
> + =A0 =A0 =A0 return ret;
> +}
> +
> +static int vdev_of_remove(struct of_device *op)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv =3D dev_get_drvdata(&op->dev);
> +
> + =A0 =A0 =A0 /* Stop the irq handler */
> + =A0 =A0 =A0 free_irq(priv->irq, priv);
> +
> + =A0 =A0 =A0 /* Unregister and reset all of the devices */
> + =A0 =A0 =A0 schedule_work(&priv->reset_work);
> + =A0 =A0 =A0 flush_scheduled_work();
> +
> + =A0 =A0 =A0 dma_free_coherent(&op->dev, VOP_GUEST_MEM_SIZE, priv->guest=
_mem,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->guest_mem_addr);
> + =A0 =A0 =A0 iounmap(priv->immr);
> + =A0 =A0 =A0 dma_release_channel(priv->chan);
> + =A0 =A0 =A0 kfree(priv);
> +
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static struct of_device_id vdev_of_match[] =3D {
> + =A0 =A0 =A0 { .compatible =3D "fsl,mpc8349-mu", },
> + =A0 =A0 =A0 {},
> +};
> +
> +static struct of_platform_driver vdev_of_driver =3D {
> + =A0 =A0 =A0 .owner =A0 =A0 =A0 =A0 =A0=3D THIS_MODULE,
> + =A0 =A0 =A0 .name =A0 =A0 =A0 =A0 =A0 =3D driver_name,
> + =A0 =A0 =A0 .match_table =A0 =A0=3D vdev_of_match,
> + =A0 =A0 =A0 .probe =A0 =A0 =A0 =A0 =A0=3D vdev_of_probe,
> + =A0 =A0 =A0 .remove =A0 =A0 =A0 =A0 =3D vdev_of_remove,
> +};
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Module Init / Exit =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static int __init vdev_init(void)
> +{
> + =A0 =A0 =A0 dma_cache =3D KMEM_CACHE(vop_dma_cbinfo, 0);
> + =A0 =A0 =A0 if (!dma_cache) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: unable to create dma cache\n", =
driver_name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return of_register_platform_driver(&vdev_of_driver);
> +}
> +
> +static void __exit vdev_exit(void)
> +{
> + =A0 =A0 =A0 of_unregister_platform_driver(&vdev_of_driver);
> + =A0 =A0 =A0 kmem_cache_destroy(dma_cache);
> +}
> +
> +MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
> +MODULE_DESCRIPTION("Freescale Virtio-over-PCI Test Driver");
> +MODULE_LICENSE("GPL");
> +
> +module_init(vdev_init);
> +module_exit(vdev_exit);
> diff --git a/drivers/virtio/vop_host.c b/drivers/virtio/vop_host.c
> new file mode 100644
> index 0000000..814fa8a
> --- /dev/null
> +++ b/drivers/virtio/vop_host.c
> @@ -0,0 +1,1071 @@
> +/*
> + * Virtio-over-PCI Host Driver for MPC8349EMDS Guest
> + *
> + * Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu>
> + *
> + * This file is licensed under the terms of the GNU General Public Licen=
se
> + * version 2. This program is licensed "as is" without any warranty of a=
ny
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_config.h>
> +#include <linux/virtio_net.h>
> +#include <linux/workqueue.h>
> +#include <linux/interrupt.h>
> +
> +#include <linux/etherdevice.h>
> +
> +#include "vop_hw.h"
> +#include "vop.h"
> +
> +static const char driver_name[] =3D "vdev";
> +
> +struct vop_loc_desc {
> + =A0 =A0 =A0 u32 addr;
> + =A0 =A0 =A0 u32 len;
> + =A0 =A0 =A0 u16 flags;
> + =A0 =A0 =A0 u16 next;
> +};
> +
> +struct vop_vq {
> +
> + =A0 =A0 =A0 /* The actual virtqueue itself */
> + =A0 =A0 =A0 struct virtqueue vq;
> +
> + =A0 =A0 =A0 struct device *dev;
> +
> + =A0 =A0 =A0 /* The host ring address */
> + =A0 =A0 =A0 struct vop_host_ring *host;
> +
> + =A0 =A0 =A0 /* The guest ring address */
> + =A0 =A0 =A0 struct vop_guest_ring __iomem *guest;
> +
> + =A0 =A0 =A0 /* Local copy of the descriptors for fast access */
> + =A0 =A0 =A0 struct vop_loc_desc desc[VOP_RING_SIZE];
> +
> + =A0 =A0 =A0 /* The data token from add_buf() */
> + =A0 =A0 =A0 void *data[VOP_RING_SIZE];
> +
> + =A0 =A0 =A0 unsigned int num_free;
> + =A0 =A0 =A0 unsigned int free_head;
> + =A0 =A0 =A0 unsigned int num_added;
> +
> + =A0 =A0 =A0 u16 avail_idx;
> + =A0 =A0 =A0 u16 last_used_idx;
> +
> + =A0 =A0 =A0 /* The doorbell to kick() */
> + =A0 =A0 =A0 unsigned int kick_val;
> + =A0 =A0 =A0 void __iomem *immr;
> +};
> +
> +/* Convert from a struct virtqueue to a struct vop_vq */
> +#define to_vop_vq(X) container_of(X, struct vop_vq, vq)
> +
> +/*
> + * This represents a virtio_device for our driver. It follows the memory
> + * layout shown above. It has pointers to all of the host and guest memo=
ry
> + * areas that we need to access
> + */
> +struct vop_vdev {
> +
> + =A0 =A0 =A0 /* The specific virtio device (console, net, blk) */
> + =A0 =A0 =A0 struct virtio_device vdev;
> +
> + =A0 =A0 =A0 /* Local and remote memory */
> + =A0 =A0 =A0 void *loc;
> + =A0 =A0 =A0 void __iomem *rem;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* These are the status, feature, and configuration infor=
mation
> + =A0 =A0 =A0 =A0* for this virtio device. They are exposed in our memory=
 block
> + =A0 =A0 =A0 =A0* starting at offset 0.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 struct vop_status *host_status;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* These are the status, feature, and configuration infor=
mation
> + =A0 =A0 =A0 =A0* for the guest virtio device. They are exposed in the g=
uest
> + =A0 =A0 =A0 =A0* memory block starting at offset 0.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 struct vop_status __iomem *guest_status;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* These are the virtqueues for the virtio driver running=
 this
> + =A0 =A0 =A0 =A0* device to use. The host portions are exposed in our me=
mory block
> + =A0 =A0 =A0 =A0* starting at offset 1024. The exposed areas are aligned=
 to 1024 byte
> + =A0 =A0 =A0 =A0* boundaries, so they appear at offets 1024, 2048, and 3=
072
> + =A0 =A0 =A0 =A0* respectively.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 struct vop_vq virtqueues[3];
> +};
> +
> +#define to_vop_vdev(X) container_of(X, struct vop_vdev, vdev)
> +
> +/*
> + * This is information from the PCI subsystem about each MPC8349EMDS boa=
rd
> + *
> + * It holds information for all of the possible virtio_devices that are
> + * attached to this board.
> + */
> +struct vop_dev {
> +
> + =A0 =A0 =A0 struct pci_dev *pdev;
> + =A0 =A0 =A0 struct device *dev;
> +
> + =A0 =A0 =A0 /* PowerPC memory (PCI BAR0 and BAR1, respectively) */
> + =A0 =A0 =A0 #define VOP_GUEST_MEM_SIZE 16384
> + =A0 =A0 =A0 void __iomem *immr;
> + =A0 =A0 =A0 void __iomem *netregs;
> +
> + =A0 =A0 =A0 /* Host memory, visible to the PowerPC */
> + =A0 =A0 =A0 #define VOP_HOST_MEM_SIZE 16384
> + =A0 =A0 =A0 void *host_mem;
> + =A0 =A0 =A0 dma_addr_t host_mem_addr;
> +
> + =A0 =A0 =A0 /* The virtio devices */
> + =A0 =A0 =A0 struct vop_vdev devices[4];
> +};
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Ring Debugging Helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +#ifdef DEBUG_DUMP_RINGS
> +static void dump_guest_descriptors(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 int i;
> + =A0 =A0 =A0 struct vop_desc __iomem *desc;
> +
> + =A0 =A0 =A0 pr_debug("DESC BG: 0xADDRESSX LENGTH 0xFLAG 0xNEXT\n");
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 desc =3D &vq->guest->desc[i];
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_debug("DESC %.2d: 0x%.8x %.6d 0x%.4x 0x%=
.4x\n", i,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ioread32(&d=
esc->addr), ioread32(&desc->len),
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ioread16(&d=
esc->flags), ioread16(&desc->next));
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 pr_debug("DESC ED\n");
> +}
> +
> +static void dump_guest_avail(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 pr_debug("BEGIN AVAIL DUMP\n");
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_debug("AVAIL %.2d: 0x%.4x\n", i, ioread1=
6(&vq->guest->avail[i]));
> + =A0 =A0 =A0 pr_debug("END AVAIL DUMP\n");
> +}
> +
> +static void dump_guest_ring(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 pr_debug("BEGIN GUEST RING DUMP\n");
> + =A0 =A0 =A0 dump_guest_descriptors(vq);
> + =A0 =A0 =A0 pr_debug("GUEST FLAGS: 0x%.4x\n", ioread16(&vq->guest->flag=
s));
> + =A0 =A0 =A0 pr_debug("GUEST AVAIL_IDX: %d\n", ioread16(&vq->guest->avai=
l_idx));
> + =A0 =A0 =A0 dump_guest_avail(vq);
> + =A0 =A0 =A0 pr_debug("END GUEST RING DUMP\n");
> +}
> +
> +static void dump_host_used(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 int i;
> + =A0 =A0 =A0 struct vop_used_elem *used;
> +
> + =A0 =A0 =A0 pr_debug("USED BG: 0xIDID LENGTH\n");
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 used =3D &vq->host->used[i];
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_debug("USED %.2d: 0x%.4x %.6d\n", i, use=
d->id, used->len);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 pr_debug("USED ED\n");
> +}
> +
> +static void dump_host_ring(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 pr_debug("BEGIN HOST RING DUMP\n");
> + =A0 =A0 =A0 pr_debug("HOST FLAGS: 0x%.4x\n", vq->host->flags);
> + =A0 =A0 =A0 pr_debug("HOST USED_IDX: 0x%.2d\n", vq->host->used_idx);
> + =A0 =A0 =A0 dump_host_used(vq);
> + =A0 =A0 =A0 pr_debug("END HOST RING DUMP\n");
> +}
> +
> +static void debug_dump_rings(struct vop_vq *vq, const char *msg)
> +{
> + =A0 =A0 =A0 dev_dbg(vq->dev, "%s\n", msg);
> + =A0 =A0 =A0 dump_guest_ring(vq);
> + =A0 =A0 =A0 dump_host_ring(vq);
> + =A0 =A0 =A0 pr_debug("\n");
> +}
> +#else
> +static void debug_dump_rings(struct vop_vq *vq, const char *msg)
> +{
> + =A0 =A0 =A0 /* Nothing */
> +}
> +#endif /* DEBUG_DUMP_RINGS */
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Ring Access Helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +static void vop_set_desc_addr(struct vop_vq *vq, unsigned int idx, u32 a=
ddr)
> +{
> + =A0 =A0 =A0 vq->desc[idx].addr =3D addr;
> + =A0 =A0 =A0 iowrite32(addr, &vq->guest->desc[idx].addr);
> +}
> +
> +static void vop_set_desc_len(struct vop_vq *vq, unsigned int idx, u32 le=
n)
> +{
> + =A0 =A0 =A0 vq->desc[idx].len =3D len;
> + =A0 =A0 =A0 iowrite32(len, &vq->guest->desc[idx].len);
> +}
> +
> +static void vop_set_desc_flags(struct vop_vq *vq, unsigned int idx, u16 =
flags)
> +{
> + =A0 =A0 =A0 vq->desc[idx].flags =3D flags;
> + =A0 =A0 =A0 iowrite16(flags, &vq->guest->desc[idx].flags);
> +}
> +
> +static void vop_set_desc_next(struct vop_vq *vq, unsigned int idx, u16 n=
ext)
> +{
> + =A0 =A0 =A0 vq->desc[idx].next =3D next;
> + =A0 =A0 =A0 iowrite16(next, &vq->guest->desc[idx].next);
> +}
> +
> +static u32 vop_get_desc_addr(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 return vq->desc[idx].addr;
> +}
> +
> +static u32 vop_get_desc_len(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 return vq->desc[idx].len;
> +}
> +
> +static u16 vop_get_desc_flags(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 return vq->desc[idx].flags;
> +}
> +
> +static u16 vop_get_desc_next(struct vop_vq *vq, unsigned int idx)
> +{
> + =A0 =A0 =A0 return vq->desc[idx].next;
> +}
> +
> +/*
> + * Add an entry to the available ring at avail_idx pointing to the descr=
iptor
> + * chain at index head
> + *
> + * @vq the virtqueue
> + * @idx the index in the avail ring
> + * @val the value to write
> + */
> +static void vop_set_avail_entry(struct vop_vq *vq, u16 idx, u16 val)
> +{
> + =A0 =A0 =A0 iowrite16(val, &vq->guest->avail[idx]);
> +}
> +
> +/*
> + * Set the available index so the guest knows about buffers that were ad=
ded
> + * with vop_set_avail_entry()
> + *
> + * @vq the virtqueue
> + * @idx the new avail_idx that the guest sees
> + */
> +static void vop_set_avail_idx(struct vop_vq *vq, u16 idx)
> +{
> + =A0 =A0 =A0 iowrite16(idx, &vq->guest->avail_idx);
> +}
> +
> +/*
> + * Set the host's flags (in the guest memory)
> + *
> + * @vq the virtqueue
> + * @flags the new flags that the guest will see
> + */
> +static void vop_set_host_flags(struct vop_vq *vq, u16 flags)
> +{
> + =A0 =A0 =A0 iowrite16(flags, &vq->guest->flags);
> +}
> +
> +/*
> + * Read the guests flags (in local memory)
> + *
> + * @vq the virtqueue
> + * @return the guest's flags
> + */
> +static u16 vop_get_guest_flags(struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 return le16_to_cpu(vq->host->flags);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Remote status helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +static u32 vop_get_guest_status(struct vop_vdev *vdev)
> +{
> + =A0 =A0 =A0 return ioread32(&vdev->guest_status->status);
> +}
> +
> +static u32 vop_get_guest_features(struct vop_vdev *vdev)
> +{
> + =A0 =A0 =A0 return ioread32(&vdev->guest_status->features[0]);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Scatterlist DMA helpers =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * This function abuses some of the scatterlist code and implements
> + * dma_map_sg() in such a way that we don't need to keep the scatterlist
> + * around in order to unmap it.
> + *
> + * It is also designed to never merge scatterlist entries, which is
> + * never what we want for virtio.
> + *
> + * When it is time to unmap the buffer, you can use dma_unmap_single() t=
o
> + * unmap each entry in the chain. Get the address, length, and direction
> + * from the descriptors! (keep a local copy for speed)
> + */
> +static int vop_dma_map_sg(struct device *dev, struct scatterlist sg[],
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigned int out, unsig=
ned int in)
> +{
> + =A0 =A0 =A0 dma_addr_t addr;
> + =A0 =A0 =A0 enum dma_data_direction dir;
> + =A0 =A0 =A0 struct scatterlist *start;
> + =A0 =A0 =A0 unsigned int i, failure;
> +
> + =A0 =A0 =A0 start =3D sg;
> +
> + =A0 =A0 =A0 for (i =3D 0; i < out + in; i++) {
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Check for scatterlist chaining abuse */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 BUG_ON(sg =3D=3D NULL);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dir =3D (i < out) ? DMA_TO_DEVICE : DMA_FRO=
M_DEVICE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 addr =3D dma_map_single(dev, sg_virt(sg), s=
g->length, dir);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (dma_mapping_error(dev, addr))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto unwind;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg_dma_address(sg) =3D addr;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return 0;
> +
> +unwind:
> + =A0 =A0 =A0 failure =3D i;
> + =A0 =A0 =A0 sg =3D start;
> +
> + =A0 =A0 =A0 for (i =3D 0; i < failure; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dir =3D (i < out) ? DMA_TO_DEVICE : DMA_FRO=
M_DEVICE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 addr =3D sg_dma_address(sg);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(dev, addr, sg->length, dir=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return -ENOMEM;
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* struct virtqueue_ops infrastructure =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/*
> + * Modify the struct virtio_net_hdr_mrg_rxbuf's num_buffers field to acc=
ount
> + * for the split that will happen in the DMA xmit routine
> + *
> + * This assumes that both sides have the same PAGE_SIZE
> + */
> +static void vop_fixup_vnet_mrg_hdr(struct scatterlist sg[], unsigned int=
 out)
> +{
> + =A0 =A0 =A0 struct virtio_net_hdr *hdr;
> + =A0 =A0 =A0 struct virtio_net_hdr_mrg_rxbuf *mhdr;
> + =A0 =A0 =A0 unsigned int bytes =3D 0;
> +
> + =A0 =A0 =A0 /* There must be a header + data, at the least */
> + =A0 =A0 =A0 BUG_ON(out < 2);
> +
> + =A0 =A0 =A0 /* The first entry must be the structure */
> + =A0 =A0 =A0 BUG_ON(sg->length !=3D sizeof(struct virtio_net_hdr_mrg_rxb=
uf));
> +
> + =A0 =A0 =A0 hdr =3D sg_virt(sg);
> + =A0 =A0 =A0 mhdr =3D sg_virt(sg);
> +
> + =A0 =A0 =A0 /* We merge buffers together, so just count up the number o=
f bytes
> + =A0 =A0 =A0 =A0* needed, then figure out how many pages that will be */
> + =A0 =A0 =A0 for (/* none */; out; out--, sg =3D sg_next(sg))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 bytes +=3D sg->length;
> +
> + =A0 =A0 =A0 /* Of course, nobody ever imagined that we might actually u=
se
> + =A0 =A0 =A0 =A0* this on machines with different endianness...
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* We force big-endian for now, since that's what our gue=
st is */
> + =A0 =A0 =A0 mhdr->num_buffers =3D cpu_to_be16(DIV_ROUND_UP(bytes, PAGE_=
SIZE));
> +
> + =A0 =A0 =A0 /* Might as well fix up the other fields while we're at it =
*/
> + =A0 =A0 =A0 hdr->hdr_len =3D cpu_to_be16(hdr->hdr_len);
> + =A0 =A0 =A0 hdr->gso_size =3D cpu_to_be16(hdr->gso_size);
> + =A0 =A0 =A0 hdr->csum_start =3D cpu_to_be16(hdr->csum_start);
> + =A0 =A0 =A0 hdr->csum_offset =3D cpu_to_be16(hdr->csum_offset);
> +}
> +
> +static int vop_add_buf(struct virtqueue *_vq, struct scatterlist sg[],
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigned in=
t out, unsigned int in, void *data)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> + =A0 =A0 =A0 unsigned int i, avail, head, uninitialized_var(prev);
> +
> + =A0 =A0 =A0 BUG_ON(data =3D=3D NULL);
> + =A0 =A0 =A0 BUG_ON(out + in =3D=3D 0);
> +
> + =A0 =A0 =A0 /* Make sure we have space for this to succeed */
> + =A0 =A0 =A0 if (vq->num_free < out + in) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "No free space left: len=
=3D%d free=3D%d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out + in, v=
q->num_free);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOSPC;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* If this is an xmit buffer from virtio_net, fixup the hea=
der */
> + =A0 =A0 =A0 if (out > 1) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "Fixing up virtio_net head=
er\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_fixup_vnet_mrg_hdr(sg, out);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 head =3D vq->free_head;
> +
> + =A0 =A0 =A0 /* DMA map the scatterlist */
> + =A0 =A0 =A0 if (vop_dma_map_sg(vq->dev, sg, out, in)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "Failed to DMA map scatter=
list\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* We're about to use some buffers from the free list */
> + =A0 =A0 =A0 vq->num_free -=3D out + in;
> +
> + =A0 =A0 =A0 for (i =3D vq->free_head; out; i =3D vop_get_desc_next(vq, =
i), out--) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_flags(vq, i, VOP_DESC_F_NEXT);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_addr(vq, i, sg_dma_address(sg)=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_len(vq, i, sg->length);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 prev =3D i;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 for (/* none */; in; i =3D vop_get_desc_next(vq, i), in--) =
{
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_flags(vq, i, VOP_DESC_F_NEXT |=
 VOP_DESC_F_WRITE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_addr(vq, i, sg_dma_address(sg)=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_len(vq, i, sg->length);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 prev =3D i;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sg =3D sg_next(sg);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Last one doesn't continue */
> + =A0 =A0 =A0 vop_set_desc_flags(vq, prev, vop_get_desc_flags(vq, prev) &=
 ~VOP_DESC_F_NEXT);
> +
> + =A0 =A0 =A0 /* Update the free pointer */
> + =A0 =A0 =A0 vq->free_head =3D i;
> +
> + =A0 =A0 =A0 /* Set token */
> + =A0 =A0 =A0 vq->data[head] =3D data;
> +
> + =A0 =A0 =A0 /* Add an entry for the head of the chain into the avail ar=
ray, but
> + =A0 =A0 =A0 =A0* don't update avail->idx until kick() */
> + =A0 =A0 =A0 avail =3D (vq->avail_idx + vq->num_added++) & (VOP_RING_SIZ=
E - 1);
> + =A0 =A0 =A0 vop_set_avail_entry(vq, avail, head);
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "Added buffer head %i to %p (num_free %d)\=
n", head, vq, vq->num_free);
> + =A0 =A0 =A0 debug_dump_rings(vq, "Added buffer(s), dumping rings");
> +
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static inline bool more_used(const struct vop_vq *vq)
> +{
> + =A0 =A0 =A0 return vq->last_used_idx !=3D le16_to_cpu(vq->host->used_id=
x);
> +}
> +
> +static void detach_buf(struct vop_vq *vq, unsigned int head)
> +{
> + =A0 =A0 =A0 unsigned int i, len;
> + =A0 =A0 =A0 dma_addr_t addr;
> + =A0 =A0 =A0 enum dma_data_direction dir;
> +
> + =A0 =A0 =A0 /* Clear data pointer */
> + =A0 =A0 =A0 vq->data[head] =3D NULL;
> +
> + =A0 =A0 =A0 /* Put the chain back on the free list, unmapping as we go =
*/
> + =A0 =A0 =A0 i =3D head;
> + =A0 =A0 =A0 while (true) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 addr =3D vop_get_desc_addr(vq, i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 len =3D vop_get_desc_len(vq, i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dir =3D (vop_get_desc_flags(vq, i) & VOP_DE=
SC_F_WRITE) ?
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 DMA_FROM_DE=
VICE : DMA_TO_DEVICE;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Unmap the entry */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(vq->dev, addr, len, dir);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->num_free++;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Check for end-of-chain */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(vop_get_desc_flags(vq, i) & VOP_DESC_=
F_NEXT))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 i =3D vop_get_desc_next(vq, i);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 vop_set_desc_next(vq, i, vq->free_head);
> + =A0 =A0 =A0 vq->free_head =3D head;
> +}
> +
> +static void *vop_get_buf(struct virtqueue *_vq, unsigned int *len)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> + =A0 =A0 =A0 unsigned int head, used_idx;
> + =A0 =A0 =A0 void *ret;
> +
> + =A0 =A0 =A0 if (!more_used(vq)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "No more buffers in queue\=
n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return NULL;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 used_idx =3D vq->last_used_idx & (VOP_RING_SIZE - 1);
> + =A0 =A0 =A0 head =3D le32_to_cpu(vq->host->used[used_idx].id);
> + =A0 =A0 =A0 *len =3D le32_to_cpu(vq->host->used[used_idx].len);
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "REMOVE buffer head %i from %p (len %d)\n"=
, head, vq, *len);
> + =A0 =A0 =A0 debug_dump_rings(vq, "Removing buffer, dumping rings");
> +
> + =A0 =A0 =A0 BUG_ON(head >=3D VOP_RING_SIZE);
> + =A0 =A0 =A0 BUG_ON(!vq->data[head]);
> +
> + =A0 =A0 =A0 /* detach_buf() clears data, save it now */
> + =A0 =A0 =A0 ret =3D vq->data[head];
> + =A0 =A0 =A0 detach_buf(vq, head);
> +
> + =A0 =A0 =A0 /* Update the last used_idx we've consumed */
> + =A0 =A0 =A0 vq->last_used_idx++;
> + =A0 =A0 =A0 return ret;
> +}
> +
> +static void vop_kick(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> +
> + =A0 =A0 =A0 dev_dbg(vq->dev, "making %d new buffers available to guest\=
n", vq->num_added);
> + =A0 =A0 =A0 vq->avail_idx +=3D vq->num_added;
> + =A0 =A0 =A0 vq->num_added =3D 0;
> + =A0 =A0 =A0 vop_set_avail_idx(vq, vq->avail_idx);
> +
> + =A0 =A0 =A0 if (!(vop_get_guest_flags(vq) & VOP_F_NO_INTERRUPT)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "kicking the guest (new bu=
ffers in avail)\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 iowrite32(vq->kick_val, vq->immr + IDR_OFFS=
ET);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 debug_dump_rings(vq, "ran a kick, dumping r=
ings");
> + =A0 =A0 =A0 }
> +}
> +
> +/* Write to the guest's flags register to disable interrupts */
> +static void vop_disable_cb(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> +
> + =A0 =A0 =A0 vop_set_host_flags(vq, VOP_F_NO_INTERRUPT);
> +}
> +
> +static bool vop_enable_cb(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> +
> + =A0 =A0 =A0 /* We optimistically enable interrupts, then check if
> + =A0 =A0 =A0 =A0* there was more to do */
> + =A0 =A0 =A0 vop_set_host_flags(vq, 0);
> +
> + =A0 =A0 =A0 if (unlikely(more_used(vq)))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return false;
> +
> + =A0 =A0 =A0 return true;
> +}
> +
> +static struct virtqueue_ops vop_vq_ops =3D {
> + =A0 =A0 =A0 .add_buf =A0 =A0 =A0 =A0=3D vop_add_buf,
> + =A0 =A0 =A0 .get_buf =A0 =A0 =A0 =A0=3D vop_get_buf,
> + =A0 =A0 =A0 .kick =A0 =A0 =A0 =A0 =A0 =3D vop_kick,
> + =A0 =A0 =A0 .disable_cb =A0 =A0 =3D vop_disable_cb,
> + =A0 =A0 =A0 .enable_cb =A0 =A0 =A0=3D vop_enable_cb,
> +};
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* struct virtio_device infrastructure =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +/* Get something that the other side wants you to have, from configurati=
on
> + * space. This is used to transfer the MAC address from the guest to the=
 host,
> + * for example. It should be reading something from the guest, in this c=
ase */
> +static void vopc_get(struct virtio_device *_vdev, unsigned offset, void =
*buf,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned len)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 void __iomem *config =3D vdev->guest_status->config;
> +
> + =A0 =A0 =A0 memcpy_fromio(buf, config + offset, len);
> +}
> +
> +/* Set something in the configuration space (currently unused) */
> +static void vopc_set(struct virtio_device *_vdev, unsigned offset,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const void *buf, unsigned len)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 void __iomem *config =3D vdev->guest_status->config;
> +
> + =A0 =A0 =A0 memcpy_toio(config + offset, buf, len);
> +}
> +
> +/* Get your own status */
> +static u8 vopc_get_status(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 u32 status;
> +
> + =A0 =A0 =A0 status =3D le32_to_cpu(vdev->host_status->status);
> + =A0 =A0 =A0 dev_dbg(&vdev->vdev.dev, "%s(): -> 0x%.2x\n", __func__, (u8=
)status);
> +
> + =A0 =A0 =A0 return (u8)status;
> +}
> +
> +/* Set your own status */
> +static void vopc_set_status(struct virtio_device *_vdev, u8 status)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 u32 old_status;
> +
> + =A0 =A0 =A0 old_status =3D le32_to_cpu(vdev->host_status->status);
> + =A0 =A0 =A0 vdev->host_status->status =3D cpu_to_le32(status);
> +
> + =A0 =A0 =A0 dev_dbg(&vdev->vdev.dev, "%s(): <- 0x%.2x (was 0x%.2x)\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, status, old_statu=
s);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* FIXME: we really need to notify the other side when st=
atus changes
> + =A0 =A0 =A0 =A0* FIXME: happen, so that they can take some action
> + =A0 =A0 =A0 =A0*/
> +}
> +
> +/* Reset your own status */
> +static void vopc_reset(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> +
> + =A0 =A0 =A0 dev_dbg(&vdev->vdev.dev, "%s(): status reset\n", __func__);
> + =A0 =A0 =A0 vdev->host_status->status =3D cpu_to_le32(0);
> +}
> +
> +static struct virtqueue *vopc_find_vq(struct virtio_device *_vdev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0unsigned index,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0void (*cb)(struct virtqueue *vq))
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 struct vop_vq *vq =3D &vdev->virtqueues[index];
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 /* Check that we support the virtqueue at this index */
> + =A0 =A0 =A0 if (index >=3D ARRAY_SIZE(vdev->virtqueues)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&vdev->vdev.dev, "no virtqueue for =
index %d\n", index);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ERR_PTR(-ENODEV);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* HACK: we only support virtio_net for now */
> + =A0 =A0 =A0 if (vdev->vdev.id.device !=3D VIRTIO_ID_NET) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&vdev->vdev.dev, "only virtio_net i=
s supported\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ERR_PTR(-ENODEV);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Initialize the virtqueue to a clean state */
> + =A0 =A0 =A0 vq->num_free =3D VOP_RING_SIZE;
> + =A0 =A0 =A0 vq->dev =3D &vdev->vdev.dev;
> +
> + =A0 =A0 =A0 switch (index) {
> + =A0 =A0 =A0 case 0: /* x86 recv virtqueue -- ppc xmit virtqueue */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->guest =3D vdev->rem + 1024;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->host =A0=3D vdev->loc + 1024;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 1: /* x86 xmit virtqueue -- ppc recv virtqueue */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->guest =3D vdev->rem + 2048;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->host =A0=3D vdev->loc + 2048;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 default:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(vq->dev, "unknown virtqueue %d\n", =
index);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ERR_PTR(-ENODEV);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Initialize the descriptor, avail, and used rings */
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_addr(vq, i, 0x0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_len(vq, i, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_flags(vq, i, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_desc_next(vq, i, (i + 1) & (VOP_RIN=
G_SIZE - 1));
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vop_set_avail_entry(vq, i, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->host->used[i].id =3D cpu_to_le32(0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->host->used[i].len =3D cpu_to_le32(0);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 vq->avail_idx =3D 0;
> + =A0 =A0 =A0 vop_set_avail_idx(vq, 0);
> + =A0 =A0 =A0 vop_set_host_flags(vq, 0);
> +
> + =A0 =A0 =A0 debug_dump_rings(vq, "found a virtqueue, dumping rings");
> +
> + =A0 =A0 =A0 vq->vq.callback =3D cb;
> + =A0 =A0 =A0 vq->vq.vdev =3D &vdev->vdev;
> + =A0 =A0 =A0 vq->vq.vq_ops =3D &vop_vq_ops;
> +
> + =A0 =A0 =A0 return &vq->vq;
> +}
> +
> +static void vopc_del_vq(struct virtqueue *_vq)
> +{
> + =A0 =A0 =A0 struct vop_vq *vq =3D to_vop_vq(_vq);
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 /* FIXME: make sure that DMA has stopped by this point */
> +
> + =A0 =A0 =A0 /* Unmap and remove all outstanding descriptors from the ri=
ng */
> + =A0 =A0 =A0 for (i =3D 0; i < VOP_RING_SIZE; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (vq->data[i]) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(vq->dev, "cleanup d=
etach buffer at index %d\n", i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 detach_buf(vq, i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 debug_dump_rings(vq, "virtqueue destroyed, dumping rings");
> +}
> +
> +static u32 vopc_get_features(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> + =A0 =A0 =A0 u32 ret;
> +
> + =A0 =A0 =A0 ret =3D vop_get_guest_features(vdev);
> + =A0 =A0 =A0 dev_info(&vdev->vdev.dev, "%s(): guest features 0x%.8x\n", =
__func__, ret);
> +
> + =A0 =A0 =A0 return ret;
> +}
> +
> +static void vopc_finalize_features(struct virtio_device *_vdev)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D to_vop_vdev(_vdev);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* TODO: notify the other side at this point
> + =A0 =A0 =A0 =A0*/
> +
> + =A0 =A0 =A0 vdev->host_status->features[0] =3D cpu_to_le32(vdev->vdev.f=
eatures[0]);
> + =A0 =A0 =A0 dev_info(&vdev->vdev.dev, "%s(): final features 0x%.8lx\n",=
 __func__, vdev->vdev.features[0]);
> +}
> +
> +static struct virtio_config_ops vop_config_ops =3D {
> + =A0 =A0 =A0 .get =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_get,
> + =A0 =A0 =A0 .set =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_set,
> + =A0 =A0 =A0 .get_status =A0 =A0 =A0 =A0 =A0 =A0 =3D vopc_get_status,
> + =A0 =A0 =A0 .set_status =A0 =A0 =A0 =A0 =A0 =A0 =3D vopc_set_status,
> + =A0 =A0 =A0 .reset =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_reset,
> + =A0 =A0 =A0 .find_vq =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D vopc_find_vq,
> + =A0 =A0 =A0 .del_vq =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D vopc_del_vq,
> + =A0 =A0 =A0 .get_features =A0 =A0 =A0 =A0 =A0 =3D vopc_get_features,
> + =A0 =A0 =A0 .finalize_features =A0 =A0 =A0=3D vopc_finalize_features,
> +};
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Setup code for virtio devices =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +static void vop_release(struct device *dev)
> +{
> + =A0 =A0 =A0 dev_dbg(dev, "calling device release\n");
> +}
> +
> +static int setup_virtio_device(struct vop_dev *priv, int devnum)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D &priv->devices[devnum];
> + =A0 =A0 =A0 struct device *dev =3D priv->dev;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 /* Set up the pointers to the guest and host memory areas *=
/
> + =A0 =A0 =A0 vdev->loc =3D priv->host_mem + (devnum * 4096);
> + =A0 =A0 =A0 vdev->rem =3D priv->netregs =A0+ (devnum * 4096);
> + =A0 =A0 =A0 dev_dbg(dev, "memory guest 0x%p host 0x%p\n", vdev->rem, vd=
ev->loc);
> +
> + =A0 =A0 =A0 /* Set up the pointers to the guest and host status areas *=
/
> + =A0 =A0 =A0 vdev->guest_status =3D vdev->rem;
> + =A0 =A0 =A0 vdev->host_status =A0=3D vdev->loc;
> + =A0 =A0 =A0 dev_dbg(dev, "status guest 0x%p host 0x%p\n", vdev->rem, vd=
ev->loc);
> +
> + =A0 =A0 =A0 /* The find_vq() must set up the correct mappings to virtqu=
eues itself,
> + =A0 =A0 =A0 =A0* so we cannot do it here */
> + =A0 =A0 =A0 for (i =3D 0; i < ARRAY_SIZE(vdev->virtqueues); i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(&vdev->virtqueues[i], 0, sizeof(stru=
ct vop_vq));
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev->virtqueues[i].immr =3D priv->immr;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vdev->virtqueues[i].kick_val =3D 1 << ((dev=
num * 4) + i + 2);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(dev, "vq %d cleared, kick %d\n", i,=
 (devnum * 4) + i + 2);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Zero out the configuration space completely */
> + =A0 =A0 =A0 memset(vdev->host_status, 0, 1024);
> +
> + =A0 =A0 =A0 /* Copy the parent DMA parameters to this virtio_device */
> + =A0 =A0 =A0 vdev->vdev.dev.dma_mask =3D dev->dma_mask;
> + =A0 =A0 =A0 vdev->vdev.dev.dma_parms =3D dev->dma_parms;
> + =A0 =A0 =A0 vdev->vdev.dev.coherent_dma_mask =3D dev->coherent_dma_mask=
;
> +
> + =A0 =A0 =A0 /* Setup everything except the device type */
> + =A0 =A0 =A0 vdev->vdev.dev.release =3D &vop_release;
> + =A0 =A0 =A0 vdev->vdev.dev.parent =A0=3D dev;
> + =A0 =A0 =A0 vdev->vdev.config =A0 =A0 =A0=3D &vop_config_ops;
> +
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static int register_virtio_net(struct vop_dev *priv)
> +{
> + =A0 =A0 =A0 struct vop_vdev *vdev =3D &priv->devices[0];
> + =A0 =A0 =A0 struct virtio_net_config *config;
> + =A0 =A0 =A0 unsigned long features =3D 0;
> + =A0 =A0 =A0 int ret;
> +
> + =A0 =A0 =A0 /* Run the common setup routine */
> + =A0 =A0 =A0 ret =3D setup_virtio_device(priv, 0);
> + =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(priv->dev, "unable to setup virtio_=
net\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Generate a random ethernet address for the other side
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* This is necessary so we can allow it to give us a cons=
istent
> + =A0 =A0 =A0 =A0* MAC address for itself, using something board-specific
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* The feature bits must match for it to work correctly
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 config =3D (struct virtio_net_config *)vdev->host_status->c=
onfig;
> + =A0 =A0 =A0 random_ether_addr(config->mac);
> + =A0 =A0 =A0 dev_info(priv->dev, "Generated MAC %pM\n", config->mac);
> +
> + =A0 =A0 =A0 /* Set the feature bits for the device */
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_MAC, =A0 =A0 =A0 &features);
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_CSUM, =A0 =A0 =A0&features);
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_GSO, =A0 =A0 =A0 &features);
> + =A0 =A0 =A0 set_bit(VIRTIO_NET_F_MRG_RXBUF, &features);
> +
> + =A0 =A0 =A0 vdev->host_status->features[0] =3D cpu_to_le32(features);
> + =A0 =A0 =A0 vdev->vdev.id.device =3D VIRTIO_ID_NET;
> +
> + =A0 =A0 =A0 /* Register the virtio device */
> + =A0 =A0 =A0 return register_virtio_device(&vdev->vdev);
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Interrupt Handling =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static irqreturn_t vdev_interrupt(int irq, void *dev_id)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv =3D dev_id;
> + =A0 =A0 =A0 struct virtqueue *vq;
> + =A0 =A0 =A0 u32 omisr, odr;
> +
> + =A0 =A0 =A0 omisr =3D ioread32(priv->immr + OMISR_OFFSET);
> + =A0 =A0 =A0 odr =A0 =3D ioread32(priv->immr + ODR_OFFSET);
> +
> + =A0 =A0 =A0 /* Check the status register for doorbell interrupts */
> + =A0 =A0 =A0 if (!(omisr & 0x8))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return IRQ_NONE;
> +
> + =A0 =A0 =A0 /* Clear all doorbell interrupts */
> + =A0 =A0 =A0 iowrite32(odr, priv->immr + ODR_OFFSET);
> +
> + =A0 =A0 =A0 if (odr & 0x4) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq =3D &priv->devices[0].virtqueues[0].vq;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->callback(vq);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 if (odr & 0x8) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq =3D &priv->devices[0].virtqueues[1].vq;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 vq->callback(vq);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 return IRQ_HANDLED;
> +}
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* PCI Subsystem =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> +/*----------------------------------------------------------------------=
------*/
> +
> +static int vop_probe(struct pci_dev *dev, const struct pci_device_id *id=
)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv;
> + =A0 =A0 =A0 int ret;
> +
> + =A0 =A0 =A0 priv =3D kzalloc(sizeof(*priv), GFP_KERNEL);
> + =A0 =A0 =A0 if (!priv) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 pci_set_drvdata(dev, priv);
> + =A0 =A0 =A0 priv->dev =3D &dev->dev;
> +
> + =A0 =A0 =A0 /* Hardware Initialization */
> + =A0 =A0 =A0 ret =3D pci_enable_device(dev);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_kfree_priv;
> +
> + =A0 =A0 =A0 pci_set_master(dev);
> + =A0 =A0 =A0 ret =3D pci_request_regions(dev, driver_name);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_pci_disable_device;
> +
> + =A0 =A0 =A0 priv->immr =3D pci_ioremap_bar(dev, 0);
> + =A0 =A0 =A0 if (!priv->immr) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_pci_release_regions;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 priv->netregs =3D pci_ioremap_bar(dev, 1);
> + =A0 =A0 =A0 if (!priv->netregs) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_iounmap_immr;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* The device can only see the lowest 1GB of memory over th=
e bus */
> + =A0 =A0 =A0 dev->dev.coherent_dma_mask =3D DMA_BIT_MASK(30);
> + =A0 =A0 =A0 ret =3D dma_set_mask(&dev->dev, DMA_BIT_MASK(30));
> + =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&dev->dev, "Unable to set DMA mask\=
n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_iounmap_netregs;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Allocate the host memory, for writing by the guest */
> + =A0 =A0 =A0 priv->host_mem =3D dma_alloc_coherent(&dev->dev, VOP_HOST_M=
EM_SIZE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &priv->host_mem_addr, GFP_K=
ERNEL);
> + =A0 =A0 =A0 if (!priv->host_mem) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&dev->dev, "Unable to allocate host=
 memory\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_iounmap_netregs;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* We use the guest's mailbox 0 to hold the host memory add=
ress */
> + =A0 =A0 =A0 iowrite32(priv->host_mem_addr, priv->immr + IMR0_OFFSET);
> +
> + =A0 =A0 =A0 /* Reset all of the devices */
> + =A0 =A0 =A0 iowrite32(0x1, priv->immr + IDR_OFFSET);
> +
> + =A0 =A0 =A0 /* Mask all of the MBOX interrupts */
> + =A0 =A0 =A0 iowrite32(0x1 | 0x2, priv->immr + OMIMR_OFFSET);
> +
> + =A0 =A0 =A0 /* Setup the virtio_net instance */
> + =A0 =A0 =A0 ret =3D register_virtio_net(priv);
> + =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&dev->dev, "Unable to register virt=
io_net\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_free_host_mem;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Hook up the interrupt handler */
> + =A0 =A0 =A0 ret =3D request_irq(dev->irq, vdev_interrupt, IRQF_SHARED, =
driver_name, priv);
> + =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&dev->dev, "Unable to register inte=
rrupt handler\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out_unregister_virtio_net;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Start virtio_net */
> + =A0 =A0 =A0 iowrite32(0x1, priv->immr + IMR1_OFFSET);
> + =A0 =A0 =A0 iowrite32(0x2, priv->immr + IDR_OFFSET);
> +
> + =A0 =A0 =A0 return 0;
> +
> +out_unregister_virtio_net:
> + =A0 =A0 =A0 unregister_virtio_device(&priv->devices[0].vdev);
> +out_free_host_mem:
> + =A0 =A0 =A0 dma_free_coherent(&dev->dev, VOP_HOST_MEM_SIZE, priv->host_=
mem,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->host_mem_addr);
> +out_iounmap_netregs:
> + =A0 =A0 =A0 iounmap(priv->netregs);
> +out_iounmap_immr:
> + =A0 =A0 =A0 iounmap(priv->immr);
> +out_pci_release_regions:
> + =A0 =A0 =A0 pci_release_regions(dev);
> +out_pci_disable_device:
> + =A0 =A0 =A0 pci_disable_device(dev);
> +out_kfree_priv:
> + =A0 =A0 =A0 kfree(priv);
> +out_return:
> + =A0 =A0 =A0 return ret;
> +}
> +
> +static void vop_remove(struct pci_dev *dev)
> +{
> + =A0 =A0 =A0 struct vop_dev *priv =3D pci_get_drvdata(dev);
> +
> + =A0 =A0 =A0 free_irq(dev->irq, priv);
> +
> + =A0 =A0 =A0 /* Reset everything */
> + =A0 =A0 =A0 iowrite32(0x1, priv->immr + IDR_OFFSET);
> +
> + =A0 =A0 =A0 /* Unregister virtio_net */
> + =A0 =A0 =A0 unregister_virtio_device(&priv->devices[0].vdev);
> +
> + =A0 =A0 =A0 /* Clear the host memory address from the guest's mailbox 0=
 */
> + =A0 =A0 =A0 iowrite32(0x0, priv->immr + IMR0_OFFSET);
> + =A0 =A0 =A0 iowrite32(0x0, priv->immr + IMR1_OFFSET);
> +
> + =A0 =A0 =A0 dma_free_coherent(&dev->dev, VOP_HOST_MEM_SIZE, priv->host_=
mem,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->host_mem_addr);
> + =A0 =A0 =A0 iounmap(priv->netregs);
> + =A0 =A0 =A0 iounmap(priv->immr);
> + =A0 =A0 =A0 pci_release_regions(dev);
> + =A0 =A0 =A0 pci_disable_device(dev);
> + =A0 =A0 =A0 kfree(priv);
> +}
> +
> +#define PCI_DEVID_FSL_MPC8349EMDS 0x0080
> +
> +/* The list of devices that this module will support */
> +static struct pci_device_id vop_ids[] =3D {
> + =A0 =A0 =A0 { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVID_FSL_MPC8349=
EMDS), },
> + =A0 =A0 =A0 { 0, }
> +};
> +MODULE_DEVICE_TABLE(pci, vop_ids);
> +
> +static struct pci_driver vop_pci_driver =3D {
> + =A0 =A0 =A0 .name =A0 =A0 =3D (char *)driver_name,
> + =A0 =A0 =A0 .id_table =3D vop_ids,
> + =A0 =A0 =A0 .probe =A0 =A0=3D vop_probe,
> + =A0 =A0 =A0 .remove =A0 =3D vop_remove,
> +};
> +
> +/*----------------------------------------------------------------------=
------*/
> +/* Module Init / Exit =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> +/*----------------------------------------------------------------------=
------*/
> +
> +static int __init vop_init(void)
> +{
> + =A0 =A0 =A0 return pci_register_driver(&vop_pci_driver);
> +}
> +
> +static void __exit vop_exit(void)
> +{
> + =A0 =A0 =A0 pci_unregister_driver(&vop_pci_driver);
> +}
> +
> +MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
> +MODULE_DESCRIPTION("Virtio-PCI-Host Test Driver");
> +MODULE_LICENSE("GPL");
> +
> +module_init(vop_init);
> +module_exit(vop_exit);
> diff --git a/drivers/virtio/vop_hw.h b/drivers/virtio/vop_hw.h
> new file mode 100644
> index 0000000..8a19d3f
> --- /dev/null
> +++ b/drivers/virtio/vop_hw.h
> @@ -0,0 +1,80 @@
> +/*
> + * Register offsets for the MPC8349EMDS Message Unit from the IMMR base =
address
> + *
> + * Copyright (c) 2008 Ira W. Snyder <iws@ovro.caltech.edu>
> + *
> + * This file is licensed under the terms of the GNU General Public Licen=
se
> + * version 2. This program is licensed "as is" without any warranty of a=
ny
> + * kind, whether express or implied.
> + */
> +
> +#ifndef PCINET_HW_H
> +#define PCINET_HW_H
> +
> +#define SGPRL_OFFSET =A0 =A0 =A0 =A0 =A0 0x0100
> +#define SGPRH_OFFSET =A0 =A0 =A0 =A0 =A0 0x0104
> +
> +/* mpc8349emds message unit register offsets */
> +#define OMISR_OFFSET =A0 =A0 =A0 =A0 =A0 0x8030
> +#define OMIMR_OFFSET =A0 =A0 =A0 =A0 =A0 0x8034
> +#define IMR0_OFFSET =A0 =A0 =A0 =A0 =A0 =A00x8050
> +#define IMR1_OFFSET =A0 =A0 =A0 =A0 =A0 =A00x8054
> +#define OMR0_OFFSET =A0 =A0 =A0 =A0 =A0 =A00x8058
> +#define OMR1_OFFSET =A0 =A0 =A0 =A0 =A0 =A00x805C
> +#define ODR_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 0x8060
> +#define IDR_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 0x8068
> +#define IMISR_OFFSET =A0 =A0 =A0 =A0 =A0 0x8080
> +#define IMIMR_OFFSET =A0 =A0 =A0 =A0 =A0 0x8084
> +
> +
> +/* mpc8349emds pci and local access window register offsets */
> +#define LAWAR0_OFFSET =A0 =A0 =A0 =A0 =A00x0064
> +#define LAWAR0_ENABLE =A0 =A0 =A0 =A0 =A0(1<<31)
> +
> +#define POCMR0_OFFSET =A0 =A0 =A0 =A0 =A00x8410
> +#define POCMR0_ENABLE =A0 =A0 =A0 =A0 =A0(1<<31)
> +
> +#define POTAR0_OFFSET =A0 =A0 =A0 =A0 =A00x8400
> +
> +#define LAWAR1_OFFSET =A0 =A0 =A0 =A0 =A00x006c
> +#define LAWAR1_ENABLE =A0 =A0 =A0 =A0 =A0(1<<31)
> +
> +#define POCMR1_OFFSET =A0 =A0 =A0 =A0 =A00x8428
> +#define POCMR1_ENABLE =A0 =A0 =A0 =A0 =A0(1<<31)
> +
> +#define POTAR1_OFFSET =A0 =A0 =A0 =A0 =A00x8418
> +
> +
> +/* mpc8349emds dma controller register offsets */
> +#define DMAMR0_OFFSET =A0 =A0 =A0 =A0 =A00x8100
> +#define DMASR0_OFFSET =A0 =A0 =A0 =A0 =A00x8104
> +#define DMASAR0_OFFSET =A0 =A0 =A0 =A0 0x8110
> +#define DMADAR0_OFFSET =A0 =A0 =A0 =A0 0x8118
> +#define DMABCR0_OFFSET =A0 =A0 =A0 =A0 0x8120
> +
> +#define DMA_CHANNEL_BUSY =A0 =A0 =A0 (1<<2)
> +
> +#define DMA_DIRECT_MODE_SNOOP =A0(1<<20)
> +#define DMA_CHANNEL_MODE_DIRECT =A0 =A0 =A0 =A0(1<<2)
> +#define DMA_CHANNEL_START =A0 =A0 =A0(1<<0)
> +
> +
> +/* mpc8349emds pci and local access window register offsets */
> +#define LAWAR0_OFFSET =A0 =A0 =A0 =A0 =A00x0064
> +#define LAWAR0_ENABLE =A0 =A0 =A0 =A0 =A0(1<<31)
> +
> +#define POCMR0_OFFSET =A0 =A0 =A0 =A0 =A00x8410
> +#define POCMR0_ENABLE =A0 =A0 =A0 =A0 =A0(1<<31)
> +
> +#define POTAR0_OFFSET =A0 =A0 =A0 =A0 =A00x8400
> +
> +
> +/* mpc8349emds pci and inbound window register offsets */
> +#define PITAR0_OFFSET =A0 =A0 =A0 =A0 =A00x8568
> +#define PIWAR0_OFFSET =A0 =A0 =A0 =A0 =A00x8578
> +
> +#define PIWAR0_ENABLED =A0 =A0 =A0 =A0 (1<<31)
> +#define PIWAR0_PREFETCH =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1<<29)
> +#define PIWAR0_IWS_4K =A0 =A0 =A0 =A0 =A00xb
> +
> +#endif /* PCINET_HW_H */
> --
> 1.5.4.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" i=
n
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at =A0http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at =A0http://www.tux.org/lkml/
>



--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* [PATCH] [V3] Xilinx : Framebuffer Driver: Add PLB support and cleanup DCR
From: John Linn @ 2009-04-14 20:08 UTC (permalink / raw)
  To: grant.likely, jwboyer, linux-fbdev-devel, linuxppc-dev,
	akonovalov, adaplas
  Cc: Suneel, John Linn

Added support for the new xps tft controller. The new core
has PLB interface support in addition to existing DCR interface.

Removed platform device support as both MicroBlaze and PowerPC
use device tree.

Previously, the dcr interface was assumed to be used in mmio mode,
and the register space of the dcr interface was precomputed and stuffed
into the device tree. This driver now makes use of the new dcr
infrastructure to represent the dcr interface. This enables the dcr
interface to be connected directly to a native dcr interface in a clean
way.

Added compatibility for ml507 dvi core.

Signed-off-by: Suneel <suneelg@xilinx.com>
Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
Signed-off-by: John Linn <john.linn@xilinx.com>
---

V2 - cleanup based on review
V3 - update to be based on top of tree rather than Xilinx tree, sorry for the
 confusion with this, update the name of the patch slightly to be more accurate

 drivers/video/xilinxfb.c |  295 ++++++++++++++++++++++++----------------------
 1 files changed, 154 insertions(+), 141 deletions(-)

diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 40a3a2a..d151237 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -1,13 +1,13 @@
 /*
- * xilinxfb.c
  *
- * Xilinx TFT LCD frame buffer driver
+ * Xilinx TFT frame buffer driver
  *
  * Author: MontaVista Software, Inc.
  *         source@mvista.com
  *
  * 2002-2007 (c) MontaVista Software, Inc.
  * 2007 (c) Secret Lab Technologies, Ltd.
+ * 2009 (c) Xilinx Inc.
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2.  This program is licensed "as is" without any warranty of any
@@ -24,33 +24,38 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#if defined(CONFIG_OF)
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
-#endif
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/xilinxfb.h>
+#include <asm/dcr.h>
 
 #define DRIVER_NAME		"xilinxfb"
-#define DRIVER_DESCRIPTION	"Xilinx TFT LCD frame buffer driver"
+
 
 /*
  * Xilinx calls it "PLB TFT LCD Controller" though it can also be used for
- * the VGA port on the Xilinx ML40x board. This is a hardware display controller
- * for a 640x480 resolution TFT or VGA screen.
+ * the VGA port on the Xilinx ML40x board. This is a hardware display
+ * controller for a 640x480 resolution TFT or VGA screen.
  *
  * The interface to the framebuffer is nice and simple.  There are two
  * control registers.  The first tells the LCD interface where in memory
  * the frame buffer is (only the 11 most significant bits are used, so
  * don't start thinking about scrolling).  The second allows the LCD to
  * be turned on or off as well as rotated 180 degrees.
+ *
+ * In case of direct PLB access the second control register will be at
+ * an offset of 4 as compared to the DCR access where the offset is 1
+ * i.e. REG_CTRL. So this is taken care in the function
+ * xilinx_fb_out_be32 where it left shifts the offset 2 times in case of
+ * direct PLB access.
  */
 #define NUM_REGS	2
 #define REG_FB_ADDR	0
@@ -107,17 +112,28 @@ static struct fb_var_screeninfo xilinx_fb_var = {
 	.activate =	FB_ACTIVATE_NOW
 };
 
+
+#define PLB_ACCESS_FLAG	0x1		/* 1 = PLB, 0 = DCR */
+
 struct xilinxfb_drvdata {
 
 	struct fb_info	info;		/* FB driver info record */
 
-	u32		regs_phys;	/* phys. address of the control registers */
-	u32 __iomem	*regs;		/* virt. address of the control registers */
+	phys_addr_t	regs_phys;	/* phys. address of the control
+						registers */
+	void __iomem	*regs;		/* virt. address of the control
+						registers */
+
+	dcr_host_t      dcr_host;
+	unsigned int    dcr_start;
+	unsigned int    dcr_len;
 
 	void		*fb_virt;	/* virt. address of the frame buffer */
 	dma_addr_t	fb_phys;	/* phys. address of the frame buffer */
 	int		fb_alloced;	/* Flag, was the fb memory alloced? */
 
+	u8 		flags;		/* features of the driver */
+
 	u32		reg_ctrl_default;
 
 	u32		pseudo_palette[PALETTE_ENTRIES_NO];
@@ -128,14 +144,19 @@ struct xilinxfb_drvdata {
 	container_of(_info, struct xilinxfb_drvdata, info)
 
 /*
- * The LCD controller has DCR interface to its registers, but all
- * the boards and configurations the driver has been tested with
- * use opb2dcr bridge. So the registers are seen as memory mapped.
- * This macro is to make it simple to add the direct DCR access
- * when it's needed.
+ * The XPS TFT Controller can be accessed through PLB or DCR interface.
+ * To perform the read/write on the registers we need to check on
+ * which bus its connected and call the appropriate write API.
  */
-#define xilinx_fb_out_be32(driverdata, offset, val) \
-	out_be32(driverdata->regs + offset, val)
+static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset,
+				u32 val)
+{
+	if (drvdata->flags & PLB_ACCESS_FLAG)
+		out_be32(drvdata->regs + (offset << 2), val);
+	else
+		dcr_write(drvdata->dcr_host, offset, val);
+
+}
 
 static int
 xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
@@ -173,7 +194,8 @@ xilinx_fb_blank(int blank_mode, struct fb_info *fbi)
 	switch (blank_mode) {
 	case FB_BLANK_UNBLANK:
 		/* turn on panel */
-		xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
+		xilinx_fb_out_be32(drvdata, REG_CTRL,
+					drvdata->reg_ctrl_default);
 		break;
 
 	case FB_BLANK_NORMAL:
@@ -189,8 +211,7 @@ xilinx_fb_blank(int blank_mode, struct fb_info *fbi)
 	return 0; /* success */
 }
 
-static struct fb_ops xilinxfb_ops =
-{
+static struct fb_ops xilinxfb_ops = {
 	.owner			= THIS_MODULE,
 	.fb_setcolreg		= xilinx_fb_setcolreg,
 	.fb_blank		= xilinx_fb_blank,
@@ -203,35 +224,34 @@ static struct fb_ops xilinxfb_ops =
  * Bus independent setup/teardown
  */
 
-static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
+static int xilinxfb_assign(struct device *dev,
+			   struct xilinxfb_drvdata *drvdata,
+			   unsigned long physaddr,
 			   struct xilinxfb_platform_data *pdata)
 {
-	struct xilinxfb_drvdata *drvdata;
 	int rc;
 	int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL;
 
-	/* Allocate the driver data region */
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata) {
-		dev_err(dev, "Couldn't allocate device private record\n");
-		return -ENOMEM;
-	}
-	dev_set_drvdata(dev, drvdata);
-
-	/* Map the control registers in */
-	if (!request_mem_region(physaddr, 8, DRIVER_NAME)) {
-		dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
-			physaddr);
-		rc = -ENODEV;
-		goto err_region;
-	}
-	drvdata->regs_phys = physaddr;
-	drvdata->regs = ioremap(physaddr, 8);
-	if (!drvdata->regs) {
-		dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
-			physaddr);
-		rc = -ENODEV;
-		goto err_map;
+	if (drvdata->flags & PLB_ACCESS_FLAG) {
+		/*
+		 * Map the control registers in if the controller
+		 * is on direct PLB interface.
+		 */
+		if (!request_mem_region(physaddr, 8, DRIVER_NAME)) {
+			dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
+				physaddr);
+			rc = -ENODEV;
+			goto err_region;
+		}
+
+		drvdata->regs_phys = physaddr;
+		drvdata->regs = ioremap(physaddr, 8);
+		if (!drvdata->regs) {
+			dev_err(dev, "Couldn't lock memory region at 0x%08lX\n",
+				physaddr);
+			rc = -ENODEV;
+			goto err_map;
+		}
 	}
 
 	/* Allocate the framebuffer memory */
@@ -247,7 +267,10 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
 	if (!drvdata->fb_virt) {
 		dev_err(dev, "Could not allocate frame buffer memory\n");
 		rc = -ENOMEM;
-		goto err_fbmem;
+		if (drvdata->flags & PLB_ACCESS_FLAG)
+			goto err_fbmem;
+		else
+			goto err_region;
 	}
 
 	/* Clear (turn to black) the framebuffer */
@@ -260,7 +283,8 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
 	drvdata->reg_ctrl_default = REG_CTRL_ENABLE;
 	if (pdata->rotate_screen)
 		drvdata->reg_ctrl_default |= REG_CTRL_ROTATE;
-	xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
+	xilinx_fb_out_be32(drvdata, REG_CTRL,
+					drvdata->reg_ctrl_default);
 
 	/* Fill struct fb_info */
 	drvdata->info.device = dev;
@@ -296,11 +320,14 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
 		goto err_regfb;
 	}
 
+	if (drvdata->flags & PLB_ACCESS_FLAG) {
+		/* Put a banner in the log (for DEBUG) */
+		dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr,
+					drvdata->regs);
+	}
 	/* Put a banner in the log (for DEBUG) */
-	dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs);
-	dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n",
-		(unsigned long long) drvdata->fb_phys, drvdata->fb_virt,
-		fbsize);
+	dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n",
+		(void *)drvdata->fb_phys, drvdata->fb_virt, fbsize);
 
 	return 0;	/* success */
 
@@ -311,14 +338,19 @@ err_cmap:
 	if (drvdata->fb_alloced)
 		dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
 			drvdata->fb_phys);
+	else
+		iounmap(drvdata->fb_virt);
+
 	/* Turn off the display */
 	xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
 
 err_fbmem:
-	iounmap(drvdata->regs);
+	if (drvdata->flags & PLB_ACCESS_FLAG)
+		iounmap(drvdata->regs);
 
 err_map:
-	release_mem_region(physaddr, 8);
+	if (drvdata->flags & PLB_ACCESS_FLAG)
+		release_mem_region(physaddr, 8);
 
 err_region:
 	kfree(drvdata);
@@ -342,12 +374,18 @@ static int xilinxfb_release(struct device *dev)
 	if (drvdata->fb_alloced)
 		dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
 				  drvdata->fb_virt, drvdata->fb_phys);
+	else
+		iounmap(drvdata->fb_virt);
 
 	/* Turn off the display */
 	xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
-	iounmap(drvdata->regs);
 
-	release_mem_region(drvdata->regs_phys, 8);
+	/* Release the resources, as allocated based on interface */
+	if (drvdata->flags & PLB_ACCESS_FLAG) {
+		iounmap(drvdata->regs);
+		release_mem_region(drvdata->regs_phys, 8);
+	} else
+		dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
 
 	kfree(drvdata);
 	dev_set_drvdata(dev, NULL);
@@ -356,77 +394,57 @@ static int xilinxfb_release(struct device *dev)
 }
 
 /* ---------------------------------------------------------------------
- * Platform bus binding
- */
-
-static int
-xilinxfb_platform_probe(struct platform_device *pdev)
-{
-	struct xilinxfb_platform_data *pdata;
-	struct resource *res;
-
-	/* Find the registers address */
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "Couldn't get registers resource\n");
-		return -ENODEV;
-	}
-
-	/* If a pdata structure is provided, then extract the parameters */
-	pdata = &xilinx_fb_default_pdata;
-	if (pdev->dev.platform_data) {
-		pdata = pdev->dev.platform_data;
-		if (!pdata->xres)
-			pdata->xres = xilinx_fb_default_pdata.xres;
-		if (!pdata->yres)
-			pdata->yres = xilinx_fb_default_pdata.yres;
-		if (!pdata->xvirt)
-			pdata->xvirt = xilinx_fb_default_pdata.xvirt;
-		if (!pdata->yvirt)
-			pdata->yvirt = xilinx_fb_default_pdata.yvirt;
-	}
-
-	return xilinxfb_assign(&pdev->dev, res->start, pdata);
-}
-
-static int
-xilinxfb_platform_remove(struct platform_device *pdev)
-{
-	return xilinxfb_release(&pdev->dev);
-}
-
-
-static struct platform_driver xilinxfb_platform_driver = {
-	.probe		= xilinxfb_platform_probe,
-	.remove		= xilinxfb_platform_remove,
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = DRIVER_NAME,
-	},
-};
-
-/* ---------------------------------------------------------------------
  * OF bus binding
  */
 
-#if defined(CONFIG_OF)
 static int __devinit
 xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
 {
-	struct resource res;
 	const u32 *prop;
+	u32 *p;
+	u32 tft_access;
 	struct xilinxfb_platform_data pdata;
+	struct resource res;
 	int size, rc;
+	int start = 0, len = 0;
+	dcr_host_t dcr_host;
+	struct xilinxfb_drvdata *drvdata;
 
 	/* Copy with the default pdata (not a ptr reference!) */
 	pdata = xilinx_fb_default_pdata;
 
 	dev_dbg(&op->dev, "xilinxfb_of_probe(%p, %p)\n", op, match);
 
-	rc = of_address_to_resource(op->node, 0, &res);
-	if (rc) {
-		dev_err(&op->dev, "invalid address\n");
-		return rc;
+	/*
+	 * To check whether the core is connected directly to DCR or PLB
+	 * interface and initialize the tft_access accordingly.
+	 */
+	p = (u32 *)of_get_property(op->node, "xlnx,dcr-splb-slave-if", NULL);
+
+	if (p)
+		tft_access = *p;
+	else
+		tft_access = 0;		/* For backward compatibility */
+
+	/*
+	 * Fill the resource structure if its direct PLB interface
+	 * otherwise fill the dcr_host structure.
+	 */
+	if (tft_access) {
+		rc = of_address_to_resource(op->node, 0, &res);
+		if (rc) {
+			dev_err(&op->dev, "invalid address\n");
+			return -ENODEV;
+		}
+
+	} else {
+		start = dcr_resource_start(op->node, 0);
+		len = dcr_resource_len(op->node, 0);
+		dcr_host = dcr_map(op->node, start, len);
+		if (!DCR_MAP_OK(dcr_host)) {
+			dev_err(&op->dev, "invalid address\n");
+			return -ENODEV;
+		}
 	}
 
 	prop = of_get_property(op->node, "phys-size", &size);
@@ -450,7 +468,26 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
 	if (of_find_property(op->node, "rotate-display", NULL))
 		pdata.rotate_screen = 1;
 
-	return xilinxfb_assign(&op->dev, res.start, &pdata);
+	/* Allocate the driver data region */
+	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata) {
+		dev_err(&op->dev, "Couldn't allocate device private record\n");
+		return -ENOMEM;
+	}
+	dev_set_drvdata(&op->dev, drvdata);
+
+	if (tft_access)
+		drvdata->flags |= PLB_ACCESS_FLAG;
+
+	/* Arguments are passed based on the interface */
+	if (drvdata->flags & PLB_ACCESS_FLAG) {
+		return xilinxfb_assign(&op->dev, drvdata, res.start, &pdata);
+	} else {
+		drvdata->dcr_start = start;
+		drvdata->dcr_len = len;
+		drvdata->dcr_host = dcr_host;
+		return xilinxfb_assign(&op->dev, drvdata, 0, &pdata);
+	}
 }
 
 static int __devexit xilinxfb_of_remove(struct of_device *op)
@@ -460,7 +497,9 @@ static int __devexit xilinxfb_of_remove(struct of_device *op)
 
 /* Match table for of_platform binding */
 static struct of_device_id xilinxfb_of_match[] __devinitdata = {
+	{ .compatible = "xlnx,xps-tft-1.00.a", },
 	{ .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", },
+	{ .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
@@ -476,22 +515,6 @@ static struct of_platform_driver xilinxfb_of_driver = {
 	},
 };
 
-/* Registration helpers to keep the number of #ifdefs to a minimum */
-static inline int __init xilinxfb_of_register(void)
-{
-	pr_debug("xilinxfb: calling of_register_platform_driver()\n");
-	return of_register_platform_driver(&xilinxfb_of_driver);
-}
-
-static inline void __exit xilinxfb_of_unregister(void)
-{
-	of_unregister_platform_driver(&xilinxfb_of_driver);
-}
-#else /* CONFIG_OF */
-/* CONFIG_OF not enabled; do nothing helpers */
-static inline int __init xilinxfb_of_register(void) { return 0; }
-static inline void __exit xilinxfb_of_unregister(void) { }
-#endif /* CONFIG_OF */
 
 /* ---------------------------------------------------------------------
  * Module setup and teardown
@@ -500,28 +523,18 @@ static inline void __exit xilinxfb_of_unregister(void) { }
 static int __init
 xilinxfb_init(void)
 {
-	int rc;
-	rc = xilinxfb_of_register();
-	if (rc)
-		return rc;
-
-	rc = platform_driver_register(&xilinxfb_platform_driver);
-	if (rc)
-		xilinxfb_of_unregister();
-
-	return rc;
+	return of_register_platform_driver(&xilinxfb_of_driver);
 }
 
 static void __exit
 xilinxfb_cleanup(void)
 {
-	platform_driver_unregister(&xilinxfb_platform_driver);
-	xilinxfb_of_unregister();
+	of_unregister_platform_driver(&xilinxfb_of_driver);
 }
 
 module_init(xilinxfb_init);
 module_exit(xilinxfb_cleanup);
 
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
+MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
 MODULE_LICENSE("GPL");
-- 
1.6.2.1



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply related

* Re: [BUILD FAILURE 07/12] Next April 14 : PPC64 randconfig [drivers/ide/pmac.c]
From: Greg KH @ 2009-04-14 20:04 UTC (permalink / raw)
  To: Subrata Modak
  Cc: sachinp, Stephen Rothwell, Bartlomiej Zolnierkiewicz,
	IDE/ATA development list, linux-kernel, Rafael J. Wysocki,
	Linuxppc-dev, linux-next, Paul Mackerras, Alexander Beregalov
In-Reply-To: <1239733759.5344.79.camel@subratamodak.linux.ibm.com>

On Tue, Apr 14, 2009 at 11:59:19PM +0530, Subrata Modak wrote:
> Observed the following build error:

<snip>

I have no objection on being cc:ed on errors that have something to do
with stuff I maintain, but on areas I don't maintain, it just ends up as
noise in my already-overflowing inbox...

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH] AOA: Convert onyx and tas codecs to new-style i2c    drivers
From: Jean Delvare @ 2009-04-14 19:49 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Benjamin, linuxppc-dev, alsa-devel, Takashi Iwai
In-Reply-To: <1239730915.24771.12.camel@johannes.local>

Hi Johannes,

On Tue, 14 Apr 2009 19:41:55 +0200, Johannes Berg wrote:
> Alright, with the patch Andreas pointed out it loads, but segfaults, as
> below. Works fine without your patch.

Thanks for the quick test and sorry that it didn't work. I'll take a
look at the trace below and try to figure out what went wrong.

Did you remove the 2 MODULE_DEVICE_TABLE from my patch? If you didn't,
please pick the latest version of my patch which doesn't have them:
ftp://ftp.kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/sound-aoa-codecs-convert-to-new-style.patch
I don't think they are the reason of the crash, but who knows...

Are you using a machine with onyx or tas? I guess onyx but I want to be
sure.

> [   10.267137] snd-aoa-codec-onyx: found pcm3052
> [   10.267238] PM: Adding info for i2c:2-0046
> [   10.267926] snd-aoa-fabric-layout: platform-onyx-codec-ref doesn't match!

Does this error also happen without my patch? It would help to see the
logs without my patch to see where it starts diverging.

> [   10.267930] snd-aoa: fabric didn't like codec onyx
> [   10.268041] aoa_codec_onyx: probe of 2-0046 failed with error -22

Apparently aoa_codec_register failed in onyx_i2c_probe(), I have to
understand why.

> [   10.268067] Unable to handle kernel paging request for data at address 0x000000d0
> [   10.268070] Faulting instruction address: 0xd000000001291d68
> [   10.268074] Oops: Kernel access of bad area, sig: 11 [#1]
> [   10.268076] PREEMPT SMP NR_CPUS=4 PowerMac
> [   10.268080] Modules linked in: snd_aoa_codec_onyx(+) firewire_ohci usbhid(+) arc4 snd_aoa_fabric_layout(+) snd_aoa ecb firewire_core crc_itu_t snd_aoa_i2sbus snd_aoa_soundbus iwlagn iwlcore snd_pcm snd_page_alloc ohci_hcd snd_timer ohci1394 ehci_hcd rfkill led_class ieee1394 usbcore snd mac80211 soundcore cfg80211
> [   10.268109] NIP: d000000001291d68 LR: d000000001291d20 CTR: 0000000000000000
> [   10.268113] REGS: c0000001e19a34e0 TRAP: 0300   Not tainted  (2.6.30-rc1-wl-dirty)
> [   10.268115] MSR: 9000000000009032 <EE,ME,IR,DR>  CR: 22000488  XER: 00000000
> [   10.268124] DAR: 00000000000000d0, DSISR: 0000000040000000
> [   10.268127] TASK = c000000205cd9d30[3391] 'modprobe' THREAD: c0000001e19a0000 CPU: 1
> [   10.268130] GPR00: d000000001291d20 c0000001e19a3760 d00000000129cdd8 c000000200c177e0 
> [   10.268135] GPR04: c000000205cda760 0000000000000007 c000000205cd9d68 c000000205cd9d68 
> [   10.268140] GPR08: 0000000000000000 0000000000000000 c000000200c179f0 c0000000010ab590 
> [   10.268145] GPR12: 0000000088000488 c0000000009c2500 0000000000000000 0000000000000000 
> [   10.268150] GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
> [   10.268155] GPR20: 0000000000000000 0000000000000001 000000000054bda0 00000000001ed780 
> [   10.268160] GPR24: 0000000000548080 00000000008c1858 c000000000847b18 0000000000000046 
> [   10.268165] GPR28: c000000217ff56d8 c000000200a59e68 d00000000129c990 c0000001e19a37d8 
> [   10.268175] NIP [d000000001291d68] .onyx_create+0xc0/0x100 [snd_aoa_codec_onyx]
> [   10.268181] LR [d000000001291d20] .onyx_create+0x78/0x100 [snd_aoa_codec_onyx]
> [   10.268183] Call Trace:
> [   10.268188] [c0000001e19a3760] [d000000001291d20] .onyx_create+0x78/0x100 [snd_aoa_codec_onyx] (unreliable)
> [   10.268196] [c0000001e19a3840] [c00000000037f900] .__attach_adapter+0x4c/0x6c
> [   10.268203] [c0000001e19a38d0] [c0000000002f7e34] .class_for_each_device+0xb4/0x10c
> [   10.268208] [c0000001e19a3990] [c00000000037ecec] .i2c_register_driver+0xf0/0x128
> [   10.268214] [c0000001e19a3a30] [d000000001291f20] .onyx_init+0x20/0x668 [snd_aoa_codec_onyx]
> [   10.268219] [c0000001e19a3ab0] [c000000000007f68] .do_one_initcall+0x9c/0x1dc
> [   10.268225] [c0000001e19a3d90] [c000000000099b0c] .SyS_init_module+0xd8/0x238
> [   10.268229] [c0000001e19a3e30] [c000000000007554] syscall_exit+0x0/0x40
> [   10.268232] Instruction dump:
> [   10.268235] a0090022 8129001e b0010074 91210070 48000341 e8410028 2fa30000 3900ffed 
> [   10.268242] 419e0028 e9230020 39430210 39000000 <e96900d0> 380900c8 f94900d0 f8030210 
> [   10.268253] BUG: using smp_processor_id() in preemptible [00000000] code: modprobe/3391
> [   10.268258] caller is .die+0x188/0x1d4
> [   10.268260] Call Trace:
> [   10.268264] [c0000001e19a3210] [c00000000000fcc4] .show_stack+0x6c/0x174 (unreliable)
> [   10.268271] [c0000001e19a32c0] [c00000000029e65c] .debug_smp_processor_id+0xe0/0x118
> [   10.268275] [c0000001e19a3350] [c000000000020918] .die+0x188/0x1d4
> [   10.268280] [c0000001e19a33f0] [c000000000027f74] .bad_page_fault+0xb8/0xd4
> [   10.268284] [c0000001e19a3470] [c00000000000524c] handle_page_fault+0x3c/0x5c
> [   10.268293] --- Exception: 300 at .onyx_create+0xc0/0x100 [snd_aoa_codec_onyx]
> [   10.268295]     LR = .onyx_create+0x78/0x100 [snd_aoa_codec_onyx]
> [   10.268299] [c0000001e19a3840] [c00000000037f900] .__attach_adapter+0x4c/0x6c
> [   10.268304] [c0000001e19a38d0] [c0000000002f7e34] .class_for_each_device+0xb4/0x10c
> [   10.268308] [c0000001e19a3990] [c00000000037ecec] .i2c_register_driver+0xf0/0x128
> [   10.268315] [c0000001e19a3a30] [d000000001291f20] .onyx_init+0x20/0x668 [snd_aoa_codec_onyx]
> [   10.268319] [c0000001e19a3ab0] [c000000000007f68] .do_one_initcall+0x9c/0x1dc
> [   10.268323] [c0000001e19a3d90] [c000000000099b0c] .SyS_init_module+0xd8/0x238
> [   10.268328] [c0000001e19a3e30] [c000000000007554] syscall_exit+0x0/0x40
> [   10.268331] ---[ end trace dbcf63aa775331e7 ]---
> 


-- 
Jean Delvare

^ permalink raw reply

* Re: [Ipw2100-admin] [BUILD FAILURE 04/12] Next April 14 : PPC64 randconfig [drivers/staging/built-in.o]
From: reinette chatre @ 2009-04-14 18:59 UTC (permalink / raw)
  To: subrata@linux.vnet.ibm.com
  Cc: sachinp, Stephen Rothwell, Greg KH, Andrea Merello, linux-kernel,
	Rafael J. Wysocki, Linuxppc-dev, linux-next, Alexander Beregalov,
	James P. Ketrenos
In-Reply-To: <1239733717.5344.76.camel@subratamodak.linux.ibm.com>

Hi Subrata,

On Tue, 2009-04-14 at 11:28 -0700, Subrata Modak wrote:
> Observed the following build error:
> ---
> LD      drivers/built-in.o
> drivers/staging/built-in.o: In function `ieee80211_xmit':
> drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c:528: multiple
> definition of `ieee80211_xmit'
> drivers/net/built-in.o:drivers/net/wireless/ipw2x00/libipw_tx.c:256:
> first defined here
> make[1]: *** [drivers/built-in.o] Error 1
> make: *** [drivers] Error 2

Looks like the rtl8187se driver started with a copy of ipw2x00's
library. Errors like this can thus be expected and should be addressed
by rtl8187se as they are the ones who made the copy.

Reinette

^ permalink raw reply

* Re: [BUILD FAILURE 11/12] Next April 14 : PPC64 randconfig [drivers/spi/mpc52xx_psc_spi.c]
From: Grant Likely @ 2009-04-14 18:42 UTC (permalink / raw)
  To: subrata
  Cc: sachinp, Stephen Rothwell, David Brownell, Greg KH, linux-kernel,
	Rafael J. Wysocki, Linuxppc-dev, linux-next, Paul Mackerras,
	Alexander Beregalov
In-Reply-To: <1239733836.5344.83.camel@subratamodak.linux.ibm.com>

Thanks Subrata.  I'll look into this.

g.

On Tue, Apr 14, 2009 at 12:30 PM, Subrata Modak
<subrata@linux.vnet.ibm.com> wrote:
> Observed the following build error:
> ---
> CC =A0 =A0 =A0drivers/spi/mpc52xx_psc_spi.o
> drivers/spi/mpc52xx_psc_spi.c: In function =91mpc52xx_psc_spi_do_probe=92=
:
> drivers/spi/mpc52xx_psc_spi.c:398: error: =91struct fsl_spi_platform_data=
=92
> has no member named =91activate_cs=92
> drivers/spi/mpc52xx_psc_spi.c:399: error: =91struct fsl_spi_platform_data=
=92
> has no member named =91deactivate_cs=92
> make[2]: *** [drivers/spi/mpc52xx_psc_spi.o] Error 1
> make[1]: *** [drivers/spi] Error 2
> make: *** [drivers] Error 2
> ---
>
> Regards--
> Subrata
>
>



--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [BUILD FAILURE 06/12] Next April 14 : PPC64 randconfig [drivers/net/ehea/ehea_main.c]
From: Alexander Beregalov @ 2009-04-14 18:39 UTC (permalink / raw)
  To: David Miller, netdev, Subrata Modak
  Cc: Thomas Klein, Stephen Rothwell, Jan-Bernd Themann, Greg KH,
	linux-kernel, Rafael J. Wysocki, Linuxppc-dev, sachinp,
	Christoph Raisch, Julia Lawall, linux-next, linux-net, Mel Gorman,
	Jeff Garzik
In-Reply-To: <1239733747.5344.78.camel@subratamodak.linux.ibm.com>

On Tue, Apr 14, 2009 at 11:59:07PM +0530, Subrata Modak wrote:
> Observed the following build error:
> CC      drivers/net/ehea/ehea_main.o
> drivers/net/ehea/ehea_main.c: In function ???ehea_setup_single_port???:
> drivers/net/ehea/ehea_main.c:3145: error: ???struct net_device??? has no
> member named ???tx_timeout???

>From 56142fa2ed992aeee3f2635990ac37807379a310 Mon Sep 17 00:00:00 2001
From: Alexander Beregalov <a.beregalov@gmail.com>
Date: Tue, 14 Apr 2009 22:35:32 +0400
Subject: [PATCH] ehea: Fix incomplete conversion to net_device_ops


Reported-by: Subrata Modak <subrata@linux.vnet.ibm.com>
Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com>
---
 drivers/net/ehea/ehea_main.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index ac0c5b4..604c844 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -3080,7 +3080,8 @@ static const struct net_device_ops ehea_netdev_ops = {
 	.ndo_change_mtu		= ehea_change_mtu,
 	.ndo_vlan_rx_register	= ehea_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= ehea_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= ehea_vlan_rx_kill_vid
+	.ndo_vlan_rx_kill_vid	= ehea_vlan_rx_kill_vid,
+	.ndo_tx_timeout		= ehea_tx_watchdog,
 };
 
 struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
@@ -3142,7 +3143,6 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 		      | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
 		      | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
 		      | NETIF_F_LLTX;
-	dev->tx_timeout = &ehea_tx_watchdog;
 	dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
 	INIT_WORK(&port->reset_task, ehea_reset_port);
-- 
1.6.2.3

^ permalink raw reply related

* [BUILD FAILURE 12/12] Next April 14 : PPC64 randconfig [drivers/macintosh/mediabay.c]
From: Subrata Modak @ 2009-04-14 18:31 UTC (permalink / raw)
  To: Linuxppc-dev, Paul Mackerras, Benjamin Herrenschmidt,
	Stefan Bader, Marcelo Tosatti, Bartlomiej Zolnierkiewicz,
	Adrian Bunk, Greg KH
  Cc: sachinp, Stephen Rothwell, linux-kernel, Rafael J. Wysocki,
	linux-next, Alexander Beregalov

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

Observed the following build error:
---
CC      drivers/macintosh/mediabay.o
In file included from drivers/macintosh/mediabay.c:21:
include/linux/ide.h:605: error: field ‘request_sense_rq’ has incomplete
type
make[2]: *** [drivers/macintosh/mediabay.o] Error 1
make[1]: *** [drivers/macintosh] Error 2
make: *** [drivers] Error 2
---

Regards--
Subrata


[-- Attachment #2: randconfig12-next20090414-ppc64 --]
[-- Type: text/plain, Size: 58412 bytes --]

#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.30-rc1
# Tue Apr 14 07:04:18 2009
#
# CONFIG_PPC64 is not set

#
# Processor support
#
CONFIG_6xx=y
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU=y
CONFIG_FSL_EMB_PERFMON=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_SMP=y
CONFIG_NR_CPUS=4
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
CONFIG_PPC_UDBG_16550=y
CONFIG_GENERIC_TBSYNC=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
CONFIG_REDBOOT=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"

#
# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
# CONFIG_SYSVIPC is not set
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set

#
# RCU Subsystem
#
# CONFIG_CLASSIC_RCU is not set
CONFIG_TREE_RCU=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_RCU_TRACE=y
CONFIG_RCU_FANOUT=32
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_TREE_RCU_TRACE=y
# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HOTPLUG is not set
# CONFIG_PRINTK is not set
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_PCSPKR_PLATFORM=y
# CONFIG_BASE_FULL is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
# CONFIG_EVENTFD is not set
# CONFIG_SHMEM is not set
# CONFIG_AIO is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_COMPAT_BRK=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLQB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
CONFIG_MARKERS=y
CONFIG_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_HAVE_CLK=y
# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=1
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_STOP_MACHINE=y
# CONFIG_BLOCK is not set
# CONFIG_FREEZER is not set
CONFIG_PPC_MSI_BITMAP=y

#
# Platform support
#
CONFIG_PPC_CHRP=y
CONFIG_PPC_MPC512x=y
CONFIG_PPC_MPC5121=y
# CONFIG_MPC5121_ADS is not set
CONFIG_MPC5121_GENERIC=y
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
CONFIG_PPC_EFIKA=y
CONFIG_PPC_LITE5200=y
CONFIG_PPC_MEDIA5200=y
# CONFIG_PPC_MPC5200_BUGFIX is not set
CONFIG_PPC_MPC5200_GPIO=y
CONFIG_PPC_PMAC=y
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
CONFIG_PPC_82xx=y
CONFIG_MPC8272_ADS=y
# CONFIG_PQ2FADS is not set
CONFIG_EP8248E=y
CONFIG_MGCOGE=y
CONFIG_PQ2ADS=y
CONFIG_8260=y
CONFIG_8272=y
CONFIG_PQ2_ADS_PCI_PIC=y
CONFIG_PPC_83xx=y
CONFIG_MPC831x_RDB=y
CONFIG_MPC832x_MDS=y
CONFIG_MPC832x_RDB=y
# CONFIG_MPC834x_MDS is not set
CONFIG_MPC834x_ITX=y
# CONFIG_MPC836x_MDS is not set
CONFIG_MPC836x_RDK=y
CONFIG_MPC837x_MDS=y
CONFIG_MPC837x_RDB=y
CONFIG_SBC834x=y
CONFIG_ASP834x=y
CONFIG_PPC_MPC831x=y
CONFIG_PPC_MPC832x=y
CONFIG_PPC_MPC834x=y
CONFIG_PPC_MPC837x=y
CONFIG_PPC_86xx=y
CONFIG_MPC8641_HPCN=y
CONFIG_SBC8641D=y
CONFIG_MPC8610_HPCD=y
CONFIG_GEF_PPC9A=y
CONFIG_GEF_SBC310=y
CONFIG_GEF_SBC610=y
CONFIG_MPC8641=y
CONFIG_MPC8610=y
CONFIG_PPC_NATIVE=y
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
# CONFIG_UDBG_RTAS_CONSOLE is not set
CONFIG_IPIC=y
CONFIG_MPIC=y
# CONFIG_MPIC_WEIRD is not set
CONFIG_PPC_I8259=y
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
CONFIG_RTAS_PROC=y
# CONFIG_MMIO_NVRAM is not set
CONFIG_PPC_MPC106=y
# CONFIG_PPC_970_NAP is not set
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_PPC601_SYNC_FIX is not set
CONFIG_TAU=y
CONFIG_TAU_INT=y
CONFIG_TAU_AVERAGE=y
# CONFIG_QUICC_ENGINE is not set
CONFIG_CPM2=y
CONFIG_FSL_ULI1575=y
CONFIG_CPM=y
CONFIG_PPC_BESTCOMM=y
CONFIG_PPC_BESTCOMM_FEC=y
CONFIG_MPC8xxx_GPIO=y
CONFIG_SIMPLE_GPIO=y
CONFIG_MCU_MPC8349EMITX=m

#
# Kernel options
#
# CONFIG_HIGHMEM is not set
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
# CONFIG_BINFMT_ELF is not set
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_IRQ_ALL_CPUS=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_MIGRATION is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
CONFIG_HAVE_MLOCK=y
CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
# CONFIG_PPC_64K_PAGES is not set
# CONFIG_PPC_256K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0,9600 console=tty0 root=/dev/sda2"
CONFIG_EXTRA_TARGETS=""
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
CONFIG_ISA_DMA_API=y

#
# Bus options
#
CONFIG_ISA=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_PPC_INDIRECT_PCI=y
CONFIG_FSL_SOC=y
CONFIG_FSL_PCI=y
CONFIG_FSL_LBC=y
CONFIG_FSL_GTM=y
CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
CONFIG_PCI_8260=y
CONFIG_PCIEPORTBUS=y
# CONFIG_PCIEAER is not set
# CONFIG_PCIEASPM is not set
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY is not set
CONFIG_PCI_STUB=y
# CONFIG_PCI_IOV is not set
CONFIG_HAS_RAPIDIO=y
CONFIG_RAPIDIO=y
CONFIG_RAPIDIO_DISC_TIMEOUT=30

#
# Advanced setup
#
CONFIG_ADVANCED_OPTIONS=y
CONFIG_LOWMEM_SIZE_BOOL=y
CONFIG_LOWMEM_SIZE=0x30000000
# CONFIG_PAGE_OFFSET_BOOL is not set
CONFIG_PAGE_OFFSET=0xc0000000
# CONFIG_KERNEL_START_BOOL is not set
CONFIG_KERNEL_START=0xc2000000
CONFIG_PHYSICAL_START=0x02000000
# CONFIG_TASK_SIZE_BOOL is not set
CONFIG_TASK_SIZE=0xc0000000
CONFIG_NET=y

#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
CONFIG_XFRM_SUB_POLICY=y
CONFIG_XFRM_MIGRATE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_XFRM_IPCOMP=y
CONFIG_NET_KEY=m
CONFIG_NET_KEY_MIGRATE=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_ASK_IP_FIB_HASH=y
# CONFIG_IP_FIB_TRIE is not set
CONFIG_IP_FIB_HASH=y
# CONFIG_IP_MULTIPLE_TABLES is not set
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
CONFIG_NET_IPGRE=m
CONFIG_NET_IPGRE_BROADCAST=y
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_LRO=y
# CONFIG_INET_DIAG is not set
CONFIG_TCP_CONG_ADVANCED=y
# CONFIG_TCP_CONG_BIC is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_CONG_WESTWOOD=y
CONFIG_TCP_CONG_HTCP=m
CONFIG_TCP_CONG_HSTCP=y
# CONFIG_TCP_CONG_HYBLA is not set
CONFIG_TCP_CONG_VEGAS=m
# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_TCP_CONG_LP is not set
# CONFIG_TCP_CONG_VENO is not set
# CONFIG_TCP_CONG_YEAH is not set
CONFIG_TCP_CONG_ILLINOIS=m
# CONFIG_DEFAULT_BIC is not set
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_HTCP is not set
# CONFIG_DEFAULT_VEGAS is not set
# CONFIG_DEFAULT_WESTWOOD is not set
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_TCP_MD5SIG=y
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=m
CONFIG_INET6_XFRM_TUNNEL=y
CONFIG_INET6_TUNNEL=y
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
CONFIG_INET6_XFRM_MODE_TUNNEL=y
# CONFIG_INET6_XFRM_MODE_BEET is not set
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=m
CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not set
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETLABEL=y
CONFIG_NETWORK_SECMARK=y
# CONFIG_NETFILTER is not set
CONFIG_IP_DCCP=m

#
# DCCP CCIDs Configuration (EXPERIMENTAL)
#
CONFIG_IP_DCCP_CCID2_DEBUG=y
CONFIG_IP_DCCP_CCID3=y
CONFIG_IP_DCCP_CCID3_DEBUG=y
CONFIG_IP_DCCP_CCID3_RTO=100
CONFIG_IP_DCCP_TFRC_LIB=y
CONFIG_IP_DCCP_TFRC_DEBUG=y
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
CONFIG_SCTP_DBG_OBJCNT=y
CONFIG_SCTP_HMAC_NONE=y
# CONFIG_SCTP_HMAC_SHA1 is not set
# CONFIG_SCTP_HMAC_MD5 is not set
# CONFIG_TIPC is not set
CONFIG_ATM=y
CONFIG_ATM_CLIP=m
# CONFIG_ATM_CLIP_NO_ICMP is not set
CONFIG_ATM_LANE=m
CONFIG_ATM_MPOA=m
CONFIG_ATM_BR2684=y
# CONFIG_ATM_BR2684_IPFILTER is not set
CONFIG_STP=y
CONFIG_GARP=y
CONFIG_BRIDGE=m
CONFIG_NET_DSA=y
CONFIG_NET_DSA_TAG_DSA=y
CONFIG_NET_DSA_TAG_EDSA=y
CONFIG_NET_DSA_TAG_TRAILER=y
CONFIG_NET_DSA_MV88E6XXX=y
CONFIG_NET_DSA_MV88E6060=y
CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y
CONFIG_NET_DSA_MV88E6131=y
CONFIG_NET_DSA_MV88E6123_61_65=y
CONFIG_VLAN_8021Q=y
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_DECNET=y
CONFIG_DECNET_ROUTER=y
CONFIG_LLC=y
CONFIG_LLC2=m
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
CONFIG_ECONET=m
# CONFIG_ECONET_AUNUDP is not set
CONFIG_ECONET_NATIVE=y
CONFIG_WAN_ROUTER=m
CONFIG_PHONET=y
CONFIG_NET_SCHED=y

#
# Queueing/Scheduling
#
CONFIG_NET_SCH_CBQ=m
# CONFIG_NET_SCH_HTB is not set
CONFIG_NET_SCH_HFSC=y
CONFIG_NET_SCH_ATM=y
CONFIG_NET_SCH_PRIO=m
# CONFIG_NET_SCH_MULTIQ is not set
CONFIG_NET_SCH_RED=y
# CONFIG_NET_SCH_SFQ is not set
# CONFIG_NET_SCH_TEQL is not set
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=y
# CONFIG_NET_SCH_NETEM is not set
CONFIG_NET_SCH_DRR=m
CONFIG_NET_SCH_INGRESS=m

#
# Classification
#
CONFIG_NET_CLS=y
# CONFIG_NET_CLS_BASIC is not set
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_PERF=y
CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_RSVP=y
# CONFIG_NET_CLS_RSVP6 is not set
# CONFIG_NET_CLS_FLOW is not set
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_STACK=32
CONFIG_NET_EMATCH_CMP=y
CONFIG_NET_EMATCH_NBYTE=m
CONFIG_NET_EMATCH_U32=m
CONFIG_NET_EMATCH_META=m
CONFIG_NET_EMATCH_TEXT=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_GACT=y
# CONFIG_GACT_PROB is not set
CONFIG_NET_ACT_MIRRED=y
CONFIG_NET_ACT_NAT=m
CONFIG_NET_ACT_PEDIT=y
CONFIG_NET_ACT_SIMP=y
CONFIG_NET_ACT_SKBEDIT=y
CONFIG_NET_CLS_IND=y
CONFIG_NET_SCH_FIFO=y
CONFIG_DCB=y

#
# Network testing
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_DROP_MONITOR is not set
CONFIG_HAMRADIO=y

#
# Packet Radio protocols
#
CONFIG_AX25=y
CONFIG_AX25_DAMA_SLAVE=y
CONFIG_NETROM=y
CONFIG_ROSE=m

#
# AX.25 network device drivers
#
# CONFIG_MKISS is not set
CONFIG_6PACK=m
# CONFIG_BPQETHER is not set
# CONFIG_SCC is not set
CONFIG_BAYCOM_SER_FDX=m
# CONFIG_BAYCOM_SER_HDX is not set
CONFIG_BAYCOM_PAR=m
# CONFIG_BAYCOM_EPP is not set
CONFIG_YAM=m
CONFIG_CAN=y
# CONFIG_CAN_RAW is not set
# CONFIG_CAN_BCM is not set

#
# CAN Device Drivers
#
CONFIG_CAN_VCAN=y
CONFIG_CAN_DEBUG_DEVICES=y
CONFIG_IRDA=y

#
# IrDA protocols
#
# CONFIG_IRLAN is not set
# CONFIG_IRCOMM is not set
CONFIG_IRDA_ULTRA=y

#
# IrDA options
#
# CONFIG_IRDA_CACHE_LAST_LSAP is not set
CONFIG_IRDA_FAST_RR=y
CONFIG_IRDA_DEBUG=y

#
# Infrared-port device drivers
#

#
# SIR device drivers
#
CONFIG_IRTTY_SIR=y

#
# Dongle support
#
CONFIG_DONGLE=y
# CONFIG_ESI_DONGLE is not set
CONFIG_ACTISYS_DONGLE=y
# CONFIG_TEKRAM_DONGLE is not set
# CONFIG_TOIM3232_DONGLE is not set
CONFIG_LITELINK_DONGLE=y
CONFIG_MA600_DONGLE=m
CONFIG_GIRBIL_DONGLE=m
CONFIG_MCP2120_DONGLE=m
CONFIG_OLD_BELKIN_DONGLE=m
CONFIG_ACT200L_DONGLE=y
CONFIG_KINGSUN_DONGLE=y
CONFIG_KSDAZZLE_DONGLE=m
CONFIG_KS959_DONGLE=m

#
# FIR device drivers
#
# CONFIG_USB_IRDA is not set
# CONFIG_SIGMATEL_FIR is not set
# CONFIG_NSC_FIR is not set
CONFIG_WINBOND_FIR=m
CONFIG_TOSHIBA_FIR=y
# CONFIG_SMC_IRCC_FIR is not set
CONFIG_ALI_FIR=m
# CONFIG_VLSI_FIR is not set
# CONFIG_VIA_FIR is not set
CONFIG_MCS_FIR=y
CONFIG_BT=y
CONFIG_BT_L2CAP=m
CONFIG_BT_SCO=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
# CONFIG_BT_BNEP is not set
CONFIG_BT_HIDP=m

#
# Bluetooth device drivers
#
# CONFIG_BT_HCIBTUSB is not set
CONFIG_BT_HCIBTSDIO=m
# CONFIG_BT_HCIUART is not set
CONFIG_BT_HCIBCM203X=y
# CONFIG_BT_HCIBPA10X is not set
CONFIG_BT_HCIBFUSB=y
# CONFIG_BT_HCIVHCI is not set
CONFIG_AF_RXRPC=m
# CONFIG_AF_RXRPC_DEBUG is not set
CONFIG_RXKAD=m
CONFIG_FIB_RULES=y
# CONFIG_WIRELESS is not set
CONFIG_WIRELESS_EXT=y
CONFIG_LIB80211=y
CONFIG_LIB80211_CRYPT_WEP=y
CONFIG_LIB80211_CRYPT_CCMP=y
CONFIG_LIB80211_CRYPT_TKIP=y
CONFIG_WIMAX=m
CONFIG_WIMAX_DEBUG_LEVEL=8
CONFIG_RFKILL=m
CONFIG_RFKILL_INPUT=m
# CONFIG_NET_9P is not set

#
# Device Drivers
#

#
# Generic Driver Options
#
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=m
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=0
CONFIG_MTD_CONCAT=m
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_REDBOOT_PARTS=m
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_OF_PARTS=m
# CONFIG_MTD_AR7_PARTS is not set

#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=m
CONFIG_HAVE_MTD_OTP=y
CONFIG_MTD_OOPS=y

#
# RAM/ROM/Flash chip drivers
#
# CONFIG_MTD_CFI is not set
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
CONFIG_MTD_MAP_BANK_WIDTH_8=y
CONFIG_MTD_MAP_BANK_WIDTH_16=y
CONFIG_MTD_MAP_BANK_WIDTH_32=y
# CONFIG_MTD_CFI_I1 is not set
# CONFIG_MTD_CFI_I2 is not set
CONFIG_MTD_CFI_I4=y
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_OTP=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=m
# CONFIG_MTD_ROM is not set
CONFIG_MTD_ABSENT=y

#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_SBC8240=m
CONFIG_MTD_INTEL_VR_NOR=y
# CONFIG_MTD_PLATRAM is not set

#
# Self-contained MTD device drivers
#
CONFIG_MTD_PMC551=y
CONFIG_MTD_PMC551_BUGFIX=y
CONFIG_MTD_PMC551_DEBUG=y
# CONFIG_MTD_DATAFLASH is not set
CONFIG_MTD_M25P80=y
CONFIG_M25PXX_USE_FAST_READ=y
CONFIG_MTD_SLRAM=m
CONFIG_MTD_PHRAM=m
# CONFIG_MTD_MTDRAM is not set

#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOC2000 is not set
CONFIG_MTD_DOC2001=m
CONFIG_MTD_DOC2001PLUS=m
CONFIG_MTD_DOCPROBE=m
CONFIG_MTD_DOCECC=m
# CONFIG_MTD_DOCPROBE_ADVANCED is not set
CONFIG_MTD_DOCPROBE_ADDRESS=0
# CONFIG_MTD_NAND is not set
CONFIG_MTD_NAND_IDS=m
# CONFIG_MTD_ONENAND is not set

#
# LPDDR flash memory drivers
#
CONFIG_MTD_LPDDR=y
CONFIG_MTD_QINFO_PROBE=y

#
# UBI - Unsorted block images
#
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_RESERVE=1
# CONFIG_MTD_UBI_GLUEBI is not set

#
# UBI debugging options
#
# CONFIG_MTD_UBI_DEBUG is not set
CONFIG_OF_DEVICE=y
CONFIG_OF_GPIO=y
CONFIG_OF_I2C=m
CONFIG_OF_SPI=y
CONFIG_PARPORT=y
# CONFIG_PARPORT_PC is not set
# CONFIG_PARPORT_GSC is not set
CONFIG_PARPORT_AX88796=y
# CONFIG_PARPORT_1284 is not set
CONFIG_PARPORT_NOT_PC=y
# CONFIG_PNP is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
CONFIG_SGI_IOC4=y
CONFIG_TIFM_CORE=m
CONFIG_TIFM_7XX1=m
CONFIG_ICS932S401=m
CONFIG_ENCLOSURE_SERVICES=y
CONFIG_HP_ILO=y
CONFIG_ISL29003=m
CONFIG_C2PORT=y

#
# EEPROM support
#
CONFIG_EEPROM_AT24=m
CONFIG_EEPROM_AT25=y
CONFIG_EEPROM_LEGACY=m
# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y

#
# SCSI device support
#
# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_FUSION=y
CONFIG_FUSION_MAX_SGE=128
CONFIG_FUSION_LOGGING=y

#
# IEEE 1394 (FireWire) support
#

#
# Enable only one of the two stacks, unless you know what you are doing
#
# CONFIG_FIREWIRE is not set
CONFIG_IEEE1394=m
# CONFIG_IEEE1394_OHCI1394 is not set
# CONFIG_IEEE1394_PCILYNX is not set

#
# SBP-2 support (for storage devices) requires SCSI
#
# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
# CONFIG_IEEE1394_ETH1394 is not set
CONFIG_IEEE1394_RAWIO=m
CONFIG_IEEE1394_VERBOSEDEBUG=y
CONFIG_I2O=m
CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
CONFIG_I2O_EXT_ADAPTEC=y
CONFIG_I2O_CONFIG=m
CONFIG_I2O_CONFIG_OLD_IOCTL=y
# CONFIG_I2O_BUS is not set
# CONFIG_I2O_PROC is not set
CONFIG_MACINTOSH_DRIVERS=y
# CONFIG_ADB is not set
# CONFIG_ADB_CUDA is not set
# CONFIG_ADB_PMU is not set
CONFIG_PMAC_MEDIABAY=y
# CONFIG_MAC_EMUMOUSEBTN is not set
CONFIG_THERM_WINDTUNNEL=m
# CONFIG_THERM_ADT746X is not set
# CONFIG_WINDFARM is not set
CONFIG_PMAC_RACKMETER=y
CONFIG_NETDEVICES=y
CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_IFB is not set
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
CONFIG_MACVLAN=y
CONFIG_EQUALIZER=y
CONFIG_TUN=y
CONFIG_VETH=y
# CONFIG_ARCNET is not set
CONFIG_PHYLIB=y

#
# MII PHY device drivers
#
CONFIG_MARVELL_PHY=y
# CONFIG_DAVICOM_PHY is not set
CONFIG_QSEMI_PHY=y
CONFIG_LXT_PHY=y
CONFIG_CICADA_PHY=m
CONFIG_VITESSE_PHY=y
CONFIG_SMSC_PHY=y
CONFIG_BROADCOM_PHY=m
# CONFIG_ICPLUS_PHY is not set
CONFIG_REALTEK_PHY=m
CONFIG_NATIONAL_PHY=m
# CONFIG_STE10XP is not set
CONFIG_LSI_ET1011C_PHY=y
CONFIG_FIXED_PHY=y
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_GPIO=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_MACE is not set
CONFIG_BMAC=m
CONFIG_HAPPYMEAL=y
CONFIG_SUNGEM=y
CONFIG_CASSINI=y
CONFIG_NET_VENDOR_3COM=y
CONFIG_EL1=m
CONFIG_EL2=m
CONFIG_ELPLUS=m
# CONFIG_EL16 is not set
CONFIG_EL3=y
# CONFIG_3C515 is not set
CONFIG_VORTEX=y
# CONFIG_TYPHOON is not set
# CONFIG_LANCE is not set
CONFIG_NET_VENDOR_SMC=y
CONFIG_WD80x3=y
# CONFIG_ULTRA is not set
CONFIG_SMC9194=m
CONFIG_ENC28J60=m
CONFIG_ENC28J60_WRITEVERIFY=y
# CONFIG_ETHOC is not set
CONFIG_NET_VENDOR_RACAL=y
CONFIG_NI52=m
# CONFIG_NI65 is not set
CONFIG_DNET=y
CONFIG_NET_TULIP=y
# CONFIG_DE2104X is not set
CONFIG_TULIP=y
# CONFIG_TULIP_MWI is not set
# CONFIG_TULIP_MMIO is not set
# CONFIG_TULIP_NAPI is not set
# CONFIG_DE4X5 is not set
# CONFIG_WINBOND_840 is not set
CONFIG_DM9102=y
# CONFIG_ULI526X is not set
CONFIG_AT1700=m
CONFIG_DEPCA=y
CONFIG_HP100=y
CONFIG_NET_ISA=y
CONFIG_E2100=m
CONFIG_EWRK3=y
CONFIG_EEXPRESS=y
# CONFIG_EEXPRESS_PRO is not set
CONFIG_HPLAN_PLUS=y
CONFIG_HPLAN=m
# CONFIG_LP486E is not set
# CONFIG_ETH16I is not set
# CONFIG_NE2000 is not set
CONFIG_ZNET=y
CONFIG_SEEQ8005=y
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
# CONFIG_AMD8111_ETH is not set
CONFIG_ADAPTEC_STARFIRE=y
CONFIG_AC3200=m
CONFIG_APRICOT=y
CONFIG_B44=y
CONFIG_B44_PCI_AUTOSELECT=y
CONFIG_B44_PCICORE_AUTOSELECT=y
CONFIG_B44_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_CS89x0 is not set
# CONFIG_E100 is not set
CONFIG_FEALNX=y
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
CONFIG_8139CP=m
CONFIG_8139TOO=m
CONFIG_8139TOO_PIO=y
CONFIG_8139TOO_TUNE_TWISTER=y
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_OLD_RX_RESET is not set
CONFIG_R6040=m
CONFIG_SIS900=y
# CONFIG_EPIC100 is not set
CONFIG_SMSC9420=y
# CONFIG_SUNDANCE is not set
CONFIG_TLAN=m
CONFIG_VIA_RHINE=m
# CONFIG_VIA_RHINE_MMIO is not set
CONFIG_SC92031=m
# CONFIG_NET_POCKET is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
CONFIG_ATL2=y
CONFIG_FS_ENET=m
CONFIG_FS_ENET_HAS_SCC=y
# CONFIG_FS_ENET_HAS_FCC is not set
# CONFIG_FS_ENET_MDIO_FCC is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
CONFIG_DL2K=m
# CONFIG_E1000 is not set
# CONFIG_E1000E is not set
CONFIG_IP1000=y
# CONFIG_IGB is not set
CONFIG_IGBVF=y
CONFIG_NS83820=m
CONFIG_HAMACHI=m
CONFIG_YELLOWFIN=y
# CONFIG_R8169 is not set
CONFIG_SIS190=y
CONFIG_SKGE=m
CONFIG_SKGE_DEBUG=y
# CONFIG_SKY2 is not set
CONFIG_VIA_VELOCITY=m
CONFIG_TIGON3=y
CONFIG_BNX2=m
CONFIG_FSL_PQ_MDIO=y
# CONFIG_GIANFAR is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
CONFIG_ATL1E=m
CONFIG_ATL1C=y
CONFIG_JME=m
CONFIG_NETDEV_10000=y
CONFIG_CHELSIO_T1=y
# CONFIG_CHELSIO_T1_1G is not set
CONFIG_CHELSIO_T3_DEPENDS=y
CONFIG_CHELSIO_T3=y
CONFIG_ENIC=y
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
CONFIG_S2IO=y
# CONFIG_VXGE is not set
CONFIG_MYRI10GE=m
CONFIG_NETXEN_NIC=y
# CONFIG_NIU is not set
CONFIG_MLX4_EN=y
CONFIG_MLX4_CORE=y
# CONFIG_MLX4_DEBUG is not set
CONFIG_TEHUTI=m
CONFIG_BNX2X=m
CONFIG_QLGE=y
# CONFIG_SFC is not set
CONFIG_BE2NET=m
CONFIG_TR=m
CONFIG_IBMTR=m
# CONFIG_IBMOL is not set
CONFIG_IBMLS=m
# CONFIG_3C359 is not set
# CONFIG_TMS380TR is not set
# CONFIG_SMCTR is not set

#
# Wireless LAN
#
CONFIG_WLAN_PRE80211=y
CONFIG_STRIP=m
# CONFIG_ARLAN is not set
# CONFIG_WAVELAN is not set
CONFIG_WLAN_80211=y
CONFIG_LIBERTAS=m
# CONFIG_LIBERTAS_USB is not set
CONFIG_LIBERTAS_SDIO=m
# CONFIG_LIBERTAS_SPI is not set
CONFIG_LIBERTAS_DEBUG=y
CONFIG_AIRO=y
CONFIG_ATMEL=m
CONFIG_PCI_ATMEL=m
CONFIG_PRISM54=y
CONFIG_USB_ZD1201=m
# CONFIG_USB_NET_RNDIS_WLAN is not set
# CONFIG_IPW2100 is not set
CONFIG_IPW2200=y
CONFIG_IPW2200_MONITOR=y
CONFIG_IPW2200_RADIOTAP=y
# CONFIG_IPW2200_PROMISCUOUS is not set
# CONFIG_IPW2200_QOS is not set
# CONFIG_IPW2200_DEBUG is not set
CONFIG_LIBIPW=y
CONFIG_LIBIPW_DEBUG=y
CONFIG_HOSTAP=y
# CONFIG_HOSTAP_FIRMWARE is not set
CONFIG_HOSTAP_PLX=m
# CONFIG_HOSTAP_PCI is not set
CONFIG_HERMES=y
CONFIG_HERMES_CACHE_FW_ON_INIT=y
# CONFIG_APPLE_AIRPORT is not set
# CONFIG_PLX_HERMES is not set
CONFIG_TMD_HERMES=m
# CONFIG_NORTEL_HERMES is not set
CONFIG_PCI_HERMES=y

#
# WiMAX Wireless Broadband devices
#
CONFIG_WIMAX_I2400M=m
# CONFIG_WIMAX_I2400M_USB is not set
CONFIG_WIMAX_I2400M_SDIO=m
CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8

#
# USB Network Adapters
#
CONFIG_USB_CATC=m
CONFIG_USB_KAWETH=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_AX8817X=y
CONFIG_USB_NET_CDCETHER=y
CONFIG_USB_NET_DM9601=y
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_GL620A=m
CONFIG_USB_NET_NET1080=y
CONFIG_USB_NET_PLUSB=y
CONFIG_USB_NET_MCS7830=y
CONFIG_USB_NET_RNDIS_HOST=m
CONFIG_USB_NET_CDC_SUBSET=m
# CONFIG_USB_ALI_M5632 is not set
CONFIG_USB_AN2720=y
CONFIG_USB_BELKIN=y
CONFIG_USB_ARMLINUX=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_KC2190=y
CONFIG_USB_NET_ZAURUS=y
# CONFIG_USB_HSO is not set
# CONFIG_WAN is not set
CONFIG_ATM_DRIVERS=y
CONFIG_ATM_DUMMY=y
CONFIG_ATM_TCP=y
CONFIG_ATM_LANAI=y
CONFIG_ATM_ENI=y
# CONFIG_ATM_ENI_DEBUG is not set
CONFIG_ATM_ENI_TUNE_BURST=y
# CONFIG_ATM_ENI_BURST_TX_16W is not set
CONFIG_ATM_ENI_BURST_TX_8W=y
# CONFIG_ATM_ENI_BURST_TX_4W is not set
CONFIG_ATM_ENI_BURST_TX_2W=y
CONFIG_ATM_ENI_BURST_RX_16W=y
CONFIG_ATM_ENI_BURST_RX_8W=y
# CONFIG_ATM_ENI_BURST_RX_4W is not set
# CONFIG_ATM_ENI_BURST_RX_2W is not set
# CONFIG_ATM_FIRESTREAM is not set
# CONFIG_ATM_ZATM is not set
# CONFIG_ATM_NICSTAR is not set
CONFIG_ATM_IDT77252=y
CONFIG_ATM_IDT77252_DEBUG=y
# CONFIG_ATM_IDT77252_RCV_ALL is not set
CONFIG_ATM_IDT77252_USE_SUNI=y
# CONFIG_ATM_AMBASSADOR is not set
# CONFIG_ATM_HORIZON is not set
CONFIG_ATM_IA=y
CONFIG_ATM_IA_DEBUG=y
# CONFIG_ATM_FORE200E is not set
CONFIG_ATM_HE=m
# CONFIG_ATM_HE_USE_SUNI is not set
CONFIG_ATM_SOLOS=y
# CONFIG_RIONET is not set
CONFIG_FDDI=m
# CONFIG_DEFXX is not set
# CONFIG_SKFP is not set
# CONFIG_HIPPI is not set
# CONFIG_PLIP is not set
# CONFIG_PPP is not set
CONFIG_SLIP=m
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLHC=m
CONFIG_SLIP_SMART=y
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_ISDN is not set
CONFIG_PHONE=y
CONFIG_PHONE_IXJ=m

#
# Input device support
#
CONFIG_INPUT=y
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_POLLDEV=y

#
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=m
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_JOYDEV=m
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set

#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_SUNKBD=y
CONFIG_KEYBOARD_LKKBD=m
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_APPLETOUCH is not set
CONFIG_MOUSE_BCM5974=y
CONFIG_MOUSE_INPORT=y
CONFIG_MOUSE_ATIXL=y
CONFIG_MOUSE_LOGIBM=y
# CONFIG_MOUSE_PC110PAD is not set
CONFIG_MOUSE_VSXXXAA=m
CONFIG_MOUSE_GPIO=y
# CONFIG_INPUT_JOYSTICK is not set
CONFIG_INPUT_TABLET=y
# CONFIG_TABLET_USB_ACECAD is not set
CONFIG_TABLET_USB_AIPTEK=m
# CONFIG_TABLET_USB_GTCO is not set
CONFIG_TABLET_USB_KBTAB=m
CONFIG_TABLET_USB_WACOM=m
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ADS7846=m
# CONFIG_TOUCHSCREEN_AD7877 is not set
CONFIG_TOUCHSCREEN_AD7879_I2C=m
CONFIG_TOUCHSCREEN_AD7879=m
CONFIG_TOUCHSCREEN_FUJITSU=m
CONFIG_TOUCHSCREEN_GUNZE=m
CONFIG_TOUCHSCREEN_ELO=m
CONFIG_TOUCHSCREEN_WACOM_W8001=m
CONFIG_TOUCHSCREEN_MTOUCH=y
CONFIG_TOUCHSCREEN_INEXIO=y
# CONFIG_TOUCHSCREEN_MK712 is not set
CONFIG_TOUCHSCREEN_HTCPEN=m
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
CONFIG_TOUCHSCREEN_TOUCHWIN=m
CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
CONFIG_TOUCHSCREEN_USB_EGALAX=y
# CONFIG_TOUCHSCREEN_USB_PANJIT is not set
CONFIG_TOUCHSCREEN_USB_3M=y
CONFIG_TOUCHSCREEN_USB_ITM=y
# CONFIG_TOUCHSCREEN_USB_ETURBO is not set
# CONFIG_TOUCHSCREEN_USB_GUNZE is not set
CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
# CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH is not set
CONFIG_TOUCHSCREEN_USB_GOTOP=y
CONFIG_TOUCHSCREEN_TOUCHIT213=y
CONFIG_TOUCHSCREEN_TSC2007=m
# CONFIG_INPUT_MISC is not set

#
# Hardware I/O ports
#
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_PARKBD=y
# CONFIG_SERIO_PCIPS2 is not set
# CONFIG_SERIO_LIBPS2 is not set
# CONFIG_SERIO_RAW is not set
# CONFIG_SERIO_XILINX_XPS_PS2 is not set
CONFIG_GAMEPORT=y
# CONFIG_GAMEPORT_NS558 is not set
CONFIG_GAMEPORT_L4=m
CONFIG_GAMEPORT_EMU10K1=y
# CONFIG_GAMEPORT_FM801 is not set

#
# Character devices
#
CONFIG_VT=y
# CONFIG_CONSOLE_TRANSLATIONS is not set
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
CONFIG_DEVKMEM=y
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_COMPUTONE is not set
# CONFIG_ROCKETPORT is not set
CONFIG_CYCLADES=m
CONFIG_CYZ_INTR=y
CONFIG_DIGIEPCA=y
CONFIG_MOXA_INTELLIO=y
# CONFIG_MOXA_SMARTIO is not set
CONFIG_ISI=y
# CONFIG_SYNCLINK is not set
CONFIG_SYNCLINKMP=y
CONFIG_SYNCLINK_GT=y
# CONFIG_N_HDLC is not set
CONFIG_RISCOM8=y
CONFIG_SPECIALIX=m
CONFIG_SX=y
CONFIG_RIO=m
# CONFIG_RIO_OLDPCI is not set
CONFIG_STALDRV=y
CONFIG_STALLION=m
# CONFIG_ISTALLION is not set
CONFIG_NOZOMI=y

#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set

#
# Non-8250 serial port support
#
# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_UARTLITE=y
CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_PMACZILOG is not set
CONFIG_SERIAL_CPM=y
# CONFIG_SERIAL_CPM_CONSOLE is not set
CONFIG_SERIAL_MPC52xx=m
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_BRIQ_PANEL=y
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
CONFIG_HVC_DRIVER=y
CONFIG_HVC_RTAS=y
# CONFIG_HVC_UDBG is not set
CONFIG_IPMI_HANDLER=y
CONFIG_IPMI_PANIC_EVENT=y
CONFIG_IPMI_PANIC_STRING=y
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
# CONFIG_IPMI_WATCHDOG is not set
# CONFIG_IPMI_POWEROFF is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
CONFIG_APPLICOM=y
CONFIG_TCG_TPM=m
# CONFIG_TCG_NSC is not set
CONFIG_TCG_ATMEL=m
CONFIG_DEVPORT=y
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_CHARDEV is not set
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_ALGOBIT=m
CONFIG_I2C_ALGOPCA=m

#
# I2C Hardware Bus support
#

#
# PC SMBus host controller drivers
#
CONFIG_I2C_ALI1535=m
CONFIG_I2C_ALI1563=m
# CONFIG_I2C_ALI15X3 is not set
CONFIG_I2C_AMD756=m
# CONFIG_I2C_AMD8111 is not set
CONFIG_I2C_I801=m
# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_SIS5595 is not set
CONFIG_I2C_SIS630=m
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_VIA is not set
CONFIG_I2C_VIAPRO=m

#
# Mac SMBus host controller drivers
#
CONFIG_I2C_HYDRA=m
CONFIG_I2C_POWERMAC=m

#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_CPM=m
# CONFIG_I2C_GPIO is not set
CONFIG_I2C_MPC=m
# CONFIG_I2C_OCORES is not set
CONFIG_I2C_SIMTEC=m

#
# External I2C/SMBus adapter drivers
#
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
CONFIG_I2C_TAOS_EVM=m
# CONFIG_I2C_TINY_USB is not set

#
# Graphics adapter I2C/DDC channel drivers
#
# CONFIG_I2C_VOODOO3 is not set

#
# Other I2C/SMBus bus drivers
#
CONFIG_I2C_PCA_ISA=m
CONFIG_I2C_PCA_PLATFORM=m
# CONFIG_I2C_STUB is not set

#
# Miscellaneous I2C Chip support
#
CONFIG_DS1682=m
CONFIG_SENSORS_PCF8574=m
CONFIG_PCF8575=m
# CONFIG_SENSORS_PCA9539 is not set
CONFIG_SENSORS_MAX6875=m
CONFIG_SENSORS_TSL2550=m
# CONFIG_I2C_DEBUG_CORE is not set
CONFIG_I2C_DEBUG_ALGO=y
CONFIG_I2C_DEBUG_BUS=y
# CONFIG_I2C_DEBUG_CHIP is not set
CONFIG_SPI=y
CONFIG_SPI_MASTER=y

#
# SPI Master Controller Drivers
#
CONFIG_SPI_BITBANG=y
CONFIG_SPI_BUTTERFLY=m
CONFIG_SPI_GPIO=m
CONFIG_SPI_LM70_LLP=y
# CONFIG_SPI_MPC52xx_PSC is not set
# CONFIG_SPI_MPC83xx is not set

#
# SPI Protocol Masters
#
CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set

#
# Memory mapped GPIO expanders:
#
CONFIG_GPIO_XILINX=y

#
# I2C GPIO expanders:
#
CONFIG_GPIO_MAX732X=m
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCF857X is not set

#
# PCI GPIO expanders:
#

#
# SPI GPIO expanders:
#
CONFIG_GPIO_MAX7301=y
# CONFIG_GPIO_MCP23S08 is not set
CONFIG_W1=m
CONFIG_W1_CON=y

#
# 1-wire Bus Masters
#
# CONFIG_W1_MASTER_MATROX is not set
# CONFIG_W1_MASTER_DS2490 is not set
# CONFIG_W1_MASTER_DS2482 is not set
# CONFIG_W1_MASTER_GPIO is not set

#
# 1-wire Slaves
#
CONFIG_W1_SLAVE_THERM=m
CONFIG_W1_SLAVE_SMEM=m
# CONFIG_W1_SLAVE_DS2431 is not set
CONFIG_W1_SLAVE_DS2433=m
CONFIG_W1_SLAVE_DS2433_CRC=y
CONFIG_W1_SLAVE_DS2760=m
CONFIG_W1_SLAVE_BQ27000=m
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=m
CONFIG_HWMON_VID=m
# CONFIG_SENSORS_AD7414 is not set
CONFIG_SENSORS_AD7418=m
# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
CONFIG_SENSORS_ADM1025=m
CONFIG_SENSORS_ADM1026=m
CONFIG_SENSORS_ADM1029=m
# CONFIG_SENSORS_ADM1031 is not set
CONFIG_SENSORS_ADM9240=m
# CONFIG_SENSORS_ADT7462 is not set
CONFIG_SENSORS_ADT7470=m
CONFIG_SENSORS_ADT7473=m
# CONFIG_SENSORS_ADT7475 is not set
CONFIG_SENSORS_AMS=m
CONFIG_SENSORS_AMS_I2C=y
CONFIG_SENSORS_ATXP1=m
CONFIG_SENSORS_DS1621=m
CONFIG_SENSORS_I5K_AMB=m
CONFIG_SENSORS_F71805F=m
CONFIG_SENSORS_F71882FG=m
CONFIG_SENSORS_F75375S=m
CONFIG_SENSORS_G760A=m
CONFIG_SENSORS_GL518SM=m
CONFIG_SENSORS_GL520SM=m
CONFIG_SENSORS_IBMAEM=m
CONFIG_SENSORS_IBMPEX=m
CONFIG_SENSORS_IT87=m
CONFIG_SENSORS_LM63=m
CONFIG_SENSORS_LM70=m
# CONFIG_SENSORS_LM75 is not set
CONFIG_SENSORS_LM77=m
CONFIG_SENSORS_LM78=m
CONFIG_SENSORS_LM80=m
# CONFIG_SENSORS_LM83 is not set
CONFIG_SENSORS_LM85=m
CONFIG_SENSORS_LM87=m
CONFIG_SENSORS_LM90=m
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
CONFIG_SENSORS_LTC4215=m
CONFIG_SENSORS_LTC4245=m
CONFIG_SENSORS_LM95241=m
CONFIG_SENSORS_MAX1111=m
# CONFIG_SENSORS_MAX1619 is not set
CONFIG_SENSORS_MAX6650=m
CONFIG_SENSORS_PC87360=m
CONFIG_SENSORS_PC87427=m
CONFIG_SENSORS_PCF8591=m
CONFIG_SENSORS_SHT15=m
CONFIG_SENSORS_SIS5595=m
# CONFIG_SENSORS_DME1737 is not set
CONFIG_SENSORS_SMSC47M1=m
CONFIG_SENSORS_SMSC47M192=m
# CONFIG_SENSORS_SMSC47B397 is not set
CONFIG_SENSORS_ADS7828=m
# CONFIG_SENSORS_THMC50 is not set
CONFIG_SENSORS_VIA686A=m
CONFIG_SENSORS_VT1211=m
CONFIG_SENSORS_VT8231=m
# CONFIG_SENSORS_W83781D is not set
CONFIG_SENSORS_W83791D=m
CONFIG_SENSORS_W83792D=m
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
CONFIG_SENSORS_W83L786NG=m
CONFIG_SENSORS_W83627HF=m
# CONFIG_SENSORS_W83627EHF is not set
CONFIG_SENSORS_LIS3_SPI=m
CONFIG_HWMON_DEBUG_CHIP=y
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y

#
# Sonics Silicon Backplane
#
CONFIG_SSB=y
CONFIG_SSB_SPROM=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
# CONFIG_SSB_B43_PCI_BRIDGE is not set
CONFIG_SSB_SILENT=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_DRIVER_PCICORE=y

#
# Multifunction device drivers
#
CONFIG_MFD_CORE=m
CONFIG_MFD_SM501=y
CONFIG_MFD_SM501_GPIO=y
CONFIG_HTC_PASIC3=m
# CONFIG_TPS65010 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set

#
# Multimedia devices
#

#
# Multimedia core support
#
CONFIG_VIDEO_DEV=m
CONFIG_VIDEO_V4L2_COMMON=m
CONFIG_VIDEO_ALLOW_V4L1=y
CONFIG_VIDEO_V4L1_COMPAT=y
CONFIG_DVB_CORE=m
CONFIG_VIDEO_MEDIA=m

#
# Multimedia drivers
#
CONFIG_VIDEO_SAA7146=m
CONFIG_VIDEO_SAA7146_VV=m
CONFIG_MEDIA_ATTACH=y
CONFIG_MEDIA_TUNER=m
CONFIG_MEDIA_TUNER_CUSTOMISE=y
# CONFIG_MEDIA_TUNER_SIMPLE is not set
CONFIG_MEDIA_TUNER_TDA8290=m
CONFIG_MEDIA_TUNER_TDA827X=m
CONFIG_MEDIA_TUNER_TDA18271=m
CONFIG_MEDIA_TUNER_TDA9887=m
# CONFIG_MEDIA_TUNER_TEA5761 is not set
CONFIG_MEDIA_TUNER_TEA5767=m
# CONFIG_MEDIA_TUNER_MT20XX is not set
CONFIG_MEDIA_TUNER_MT2060=m
CONFIG_MEDIA_TUNER_MT2266=m
# CONFIG_MEDIA_TUNER_MT2131 is not set
# CONFIG_MEDIA_TUNER_QT1010 is not set
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
# CONFIG_MEDIA_TUNER_MXL5005S is not set
CONFIG_MEDIA_TUNER_MXL5007T=m
CONFIG_MEDIA_TUNER_MC44S803=m
CONFIG_VIDEO_V4L2=m
CONFIG_VIDEO_V4L1=m
CONFIG_VIDEOBUF_GEN=m
CONFIG_VIDEOBUF_DMA_SG=m
CONFIG_VIDEOBUF_VMALLOC=m
CONFIG_VIDEOBUF_DMA_CONTIG=m
CONFIG_VIDEOBUF_DVB=m
CONFIG_VIDEO_BTCX=m
CONFIG_VIDEO_IR=m
CONFIG_VIDEO_TVEEPROM=m
CONFIG_VIDEO_TUNER=m
CONFIG_VIDEO_CAPTURE_DRIVERS=y
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_VIDEO_FIXED_MINOR_RANGES=y
# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
# CONFIG_VIDEO_IR_I2C is not set

#
# Encoders/decoders and other helper chips
#

#
# Audio decoders
#
# CONFIG_VIDEO_TVAUDIO is not set
CONFIG_VIDEO_TDA7432=m
CONFIG_VIDEO_TDA9840=m
# CONFIG_VIDEO_TDA9875 is not set
CONFIG_VIDEO_TEA6415C=m
CONFIG_VIDEO_TEA6420=m
CONFIG_VIDEO_MSP3400=m
CONFIG_VIDEO_CS5345=m
CONFIG_VIDEO_CS53L32A=m
CONFIG_VIDEO_M52790=m
CONFIG_VIDEO_TLV320AIC23B=m
CONFIG_VIDEO_WM8775=m
CONFIG_VIDEO_WM8739=m
CONFIG_VIDEO_VP27SMPX=m

#
# RDS decoders
#
# CONFIG_VIDEO_SAA6588 is not set

#
# Video decoders
#
# CONFIG_VIDEO_BT819 is not set
CONFIG_VIDEO_BT856=m
# CONFIG_VIDEO_BT866 is not set
CONFIG_VIDEO_KS0127=m
CONFIG_VIDEO_OV7670=m
CONFIG_VIDEO_TCM825X=m
CONFIG_VIDEO_SAA7110=m
CONFIG_VIDEO_SAA711X=m
CONFIG_VIDEO_SAA717X=m
# CONFIG_VIDEO_SAA7191 is not set
CONFIG_VIDEO_TVP514X=m
CONFIG_VIDEO_TVP5150=m
# CONFIG_VIDEO_VPX3220 is not set

#
# Video and audio decoders
#
CONFIG_VIDEO_CX25840=m

#
# MPEG video encoders
#
CONFIG_VIDEO_CX2341X=m

#
# Video encoders
#
CONFIG_VIDEO_SAA7127=m
# CONFIG_VIDEO_SAA7185 is not set
# CONFIG_VIDEO_ADV7170 is not set
# CONFIG_VIDEO_ADV7175 is not set

#
# Video improvement chips
#
CONFIG_VIDEO_UPD64031A=m
CONFIG_VIDEO_UPD64083=m
# CONFIG_VIDEO_VIVI is not set
CONFIG_VIDEO_BT848=m
CONFIG_VIDEO_BT848_DVB=y
# CONFIG_VIDEO_PMS is not set
CONFIG_VIDEO_BWQCAM=m
CONFIG_VIDEO_CQCAM=m
CONFIG_VIDEO_CPIA=m
# CONFIG_VIDEO_CPIA_USB is not set
CONFIG_VIDEO_CPIA2=m
CONFIG_VIDEO_SAA5246A=m
CONFIG_VIDEO_SAA5249=m
CONFIG_VIDEO_STRADIS=m
CONFIG_VIDEO_ZORAN=m
CONFIG_VIDEO_ZORAN_DC30=m
CONFIG_VIDEO_ZORAN_ZR36060=m
CONFIG_VIDEO_ZORAN_BUZ=m
CONFIG_VIDEO_ZORAN_DC10=m
CONFIG_VIDEO_ZORAN_LML33=m
CONFIG_VIDEO_ZORAN_LML33R10=m
# CONFIG_VIDEO_ZORAN_AVS6EYES is not set
CONFIG_VIDEO_SAA7134=m
CONFIG_VIDEO_SAA7134_DVB=m
# CONFIG_VIDEO_MXB is not set
CONFIG_VIDEO_HEXIUM_ORION=m
CONFIG_VIDEO_HEXIUM_GEMINI=m
CONFIG_VIDEO_CX88=m
CONFIG_VIDEO_CX88_BLACKBIRD=m
# CONFIG_VIDEO_CX88_DVB is not set
CONFIG_VIDEO_CX88_MPEG=m
CONFIG_VIDEO_CX23885=m
CONFIG_VIDEO_AU0828=m
CONFIG_VIDEO_IVTV=m
CONFIG_VIDEO_CX18=m
CONFIG_VIDEO_CAFE_CCIC=m
CONFIG_SOC_CAMERA=m
CONFIG_SOC_CAMERA_MT9M001=m
CONFIG_SOC_CAMERA_MT9M111=m
# CONFIG_SOC_CAMERA_MT9T031 is not set
CONFIG_SOC_CAMERA_MT9V022=m
CONFIG_SOC_CAMERA_TW9910=m
# CONFIG_SOC_CAMERA_PLATFORM is not set
# CONFIG_SOC_CAMERA_OV772X is not set
CONFIG_VIDEO_SH_MOBILE_CEU=m
# CONFIG_V4L_USB_DRIVERS is not set
CONFIG_RADIO_ADAPTERS=y
CONFIG_RADIO_CADET=m
# CONFIG_RADIO_RTRACK is not set
CONFIG_RADIO_RTRACK2=m
CONFIG_RADIO_AZTECH=m
# CONFIG_RADIO_GEMTEK is not set
CONFIG_RADIO_GEMTEK_PCI=m
# CONFIG_RADIO_MAXIRADIO is not set
CONFIG_RADIO_MAESTRO=m
# CONFIG_RADIO_SF16FMI is not set
CONFIG_RADIO_SF16FMR2=m
CONFIG_RADIO_TERRATEC=m
CONFIG_RADIO_TRUST=m
CONFIG_RADIO_TYPHOON=m
CONFIG_RADIO_TYPHOON_PROC_FS=y
CONFIG_RADIO_ZOLTRIX=m
CONFIG_USB_DSBR=m
CONFIG_USB_SI470X=m
CONFIG_USB_MR800=m
CONFIG_RADIO_TEA5764=m
# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y

#
# Supported SAA7146 based PCI Adapters
#
CONFIG_TTPCI_EEPROM=m
CONFIG_DVB_AV7110=m
CONFIG_DVB_AV7110_OSD=y
# CONFIG_DVB_BUDGET_CORE is not set

#
# Supported USB Adapters
#
# CONFIG_DVB_USB is not set
CONFIG_DVB_TTUSB_BUDGET=m
CONFIG_DVB_TTUSB_DEC=m
CONFIG_DVB_SIANO_SMS1XXX=m
# CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS is not set

#
# Supported FlexCopII (B2C2) Adapters
#
# CONFIG_DVB_B2C2_FLEXCOP is not set

#
# Supported BT878 Adapters
#
CONFIG_DVB_BT8XX=m

#
# Supported Pluto2 Adapters
#
CONFIG_DVB_PLUTO2=m

#
# Supported SDMC DM1105 Adapters
#
CONFIG_DVB_DM1105=m

#
# Supported FireWire (IEEE 1394) Adapters
#
CONFIG_DVB_FIREDTV=m
CONFIG_DVB_FIREDTV_IEEE1394=y
CONFIG_DVB_FIREDTV_INPUT=y

#
# Supported DVB Frontends
#
# CONFIG_DVB_FE_CUSTOMISE is not set
CONFIG_DVB_CX24110=m
CONFIG_DVB_MT312=m
CONFIG_DVB_ZL10036=m
CONFIG_DVB_STV0288=m
CONFIG_DVB_STB6000=m
CONFIG_DVB_STV0299=m
CONFIG_DVB_STV6110=m
CONFIG_DVB_STV0900=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA10086=m
CONFIG_DVB_VES1X93=m
CONFIG_DVB_TDA826X=m
CONFIG_DVB_CX24116=m
CONFIG_DVB_SI21XX=m
CONFIG_DVB_SP8870=m
CONFIG_DVB_SP887X=m
CONFIG_DVB_CX22700=m
CONFIG_DVB_L64781=m
CONFIG_DVB_TDA1004X=m
CONFIG_DVB_NXT6000=m
CONFIG_DVB_MT352=m
CONFIG_DVB_ZL10353=m
CONFIG_DVB_DIB7000P=m
CONFIG_DVB_TDA10048=m
CONFIG_DVB_VES1820=m
CONFIG_DVB_STV0297=m
CONFIG_DVB_NXT200X=m
CONFIG_DVB_OR51211=m
CONFIG_DVB_LGDT330X=m
CONFIG_DVB_LGDT3305=m
CONFIG_DVB_S5H1409=m
CONFIG_DVB_AU8522=m
CONFIG_DVB_S5H1411=m
CONFIG_DVB_PLL=m
CONFIG_DVB_LNBP21=m
CONFIG_DVB_ISL6405=m
CONFIG_DVB_ISL6421=m
# CONFIG_DAB is not set

#
# Graphics support
#
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
# CONFIG_FB is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_GENERIC is not set

#
# Display device support
#
CONFIG_DISPLAY_SUPPORT=m

#
# Display hardware drivers
#

#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_SOUND=m
CONFIG_SOUND_OSS_CORE=y
# CONFIG_SND is not set
CONFIG_SOUND_PRIME=m
CONFIG_SOUND_MSNDCLAS=m
CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin"
CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin"
CONFIG_SOUND_MSNDPIN=m
CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin"
CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin"
CONFIG_SOUND_OSS=m
# CONFIG_SOUND_TRACEINIT is not set
CONFIG_SOUND_DMAP=y
CONFIG_SOUND_SSCAPE=m
CONFIG_SOUND_VMIDI=m
# CONFIG_SOUND_TRIX is not set
CONFIG_SOUND_MSS=m
# CONFIG_SOUND_MPU401 is not set
CONFIG_SOUND_PAS=m
CONFIG_SOUND_PSS=m
# CONFIG_PSS_MIXER is not set
CONFIG_PSS_HAVE_BOOT=y
CONFIG_PSS_BOOT_FILE="/etc/sound/dsp001.ld"
CONFIG_SOUND_SB=m
CONFIG_SOUND_YM3812=m
# CONFIG_SOUND_UART6850 is not set
CONFIG_SOUND_AEDSP16=m
# CONFIG_SC6600 is not set
CONFIG_SOUND_KAHLUA=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=m
CONFIG_HID_DEBUG=y
CONFIG_HIDRAW=y

#
# USB Input Devices
#
CONFIG_USB_HID=m
# CONFIG_HID_PID is not set
CONFIG_USB_HIDDEV=y

#
# USB HID Boot Protocol drivers
#
CONFIG_USB_KBD=y
CONFIG_USB_MOUSE=y

#
# Special HID drivers
#
# CONFIG_HID_A4TECH is not set
CONFIG_HID_APPLE=m
CONFIG_HID_BELKIN=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
CONFIG_HID_CYPRESS=m
CONFIG_DRAGONRISE_FF=m
# CONFIG_HID_EZKEY is not set
CONFIG_HID_KYE=m
# CONFIG_HID_GYRATION is not set
# CONFIG_HID_KENSINGTON is not set
CONFIG_HID_LOGITECH=m
CONFIG_LOGITECH_FF=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
# CONFIG_HID_MICROSOFT is not set
CONFIG_HID_MONTEREY=m
# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=m
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=m
# CONFIG_HID_SAMSUNG is not set
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
CONFIG_GREENASIA_FF=m
CONFIG_HID_TOPSEED=m
CONFIG_THRUSTMASTER_FF=m
# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y

#
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_OTG is not set
CONFIG_USB_OTG_WHITELIST=y
CONFIG_USB_OTG_BLACKLIST_HUB=y
# CONFIG_USB_MON is not set
CONFIG_USB_WUSB=m
CONFIG_USB_WUSB_CBAF=y
CONFIG_USB_WUSB_CBAF_DEBUG=y

#
# USB Host Controller Drivers
#
CONFIG_USB_C67X00_HCD=m
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
CONFIG_USB_OXU210HP_HCD=y
CONFIG_USB_ISP116X_HCD=y
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_U132_HCD is not set
CONFIG_USB_SL811_HCD=m
CONFIG_USB_R8A66597_HCD=m
CONFIG_USB_WHCI_HCD=m
# CONFIG_USB_HWA_HCD is not set
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_TUSB6010=y
CONFIG_USB_MUSB_HOST=y
# CONFIG_USB_MUSB_PERIPHERAL is not set
# CONFIG_USB_MUSB_OTG is not set
# CONFIG_USB_GADGET_MUSB_HDRC is not set
CONFIG_USB_MUSB_HDRC_HCD=y
# CONFIG_MUSB_PIO_ONLY is not set
# CONFIG_USB_INVENTRA_DMA is not set
# CONFIG_USB_TI_CPPI_DMA is not set
# CONFIG_USB_MUSB_DEBUG is not set

#
# USB Device Class drivers
#
CONFIG_USB_ACM=y
# CONFIG_USB_PRINTER is not set
CONFIG_USB_WDM=y
CONFIG_USB_TMC=y

#
# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#

#
# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_LIBUSUAL=y

#
# USB Imaging devices
#
CONFIG_USB_MDC800=y

#
# USB port drivers
#
CONFIG_USB_USS720=m
CONFIG_USB_SERIAL=m
CONFIG_USB_EZUSB=y
# CONFIG_USB_SERIAL_GENERIC is not set
CONFIG_USB_SERIAL_AIRCABLE=m
CONFIG_USB_SERIAL_ARK3116=m
# CONFIG_USB_SERIAL_BELKIN is not set
CONFIG_USB_SERIAL_CH341=m
# CONFIG_USB_SERIAL_WHITEHEAT is not set
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
CONFIG_USB_SERIAL_CP210X=m
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_EMPEG=m
# CONFIG_USB_SERIAL_FTDI_SIO is not set
CONFIG_USB_SERIAL_FUNSOFT=m
# CONFIG_USB_SERIAL_VISOR is not set
CONFIG_USB_SERIAL_IPAQ=m
# CONFIG_USB_SERIAL_IR is not set
CONFIG_USB_SERIAL_EDGEPORT=m
CONFIG_USB_SERIAL_EDGEPORT_TI=m
CONFIG_USB_SERIAL_GARMIN=m
# CONFIG_USB_SERIAL_IPW is not set
CONFIG_USB_SERIAL_IUU=m
CONFIG_USB_SERIAL_KEYSPAN_PDA=m
# CONFIG_USB_SERIAL_KEYSPAN is not set
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_MOS7720=m
CONFIG_USB_SERIAL_MOS7840=m
# CONFIG_USB_SERIAL_MOTOROLA is not set
CONFIG_USB_SERIAL_NAVMAN=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_OTI6858=m
CONFIG_USB_SERIAL_QUALCOMM=m
CONFIG_USB_SERIAL_SPCP8X5=m
# CONFIG_USB_SERIAL_HP4X is not set
CONFIG_USB_SERIAL_SAFE=m
CONFIG_USB_SERIAL_SAFE_PADDED=y
CONFIG_USB_SERIAL_SIEMENS_MPI=m
CONFIG_USB_SERIAL_SIERRAWIRELESS=m
CONFIG_USB_SERIAL_SYMBOL=m
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
# CONFIG_USB_SERIAL_XIRCOM is not set
CONFIG_USB_SERIAL_OPTION=m
# CONFIG_USB_SERIAL_OMNINET is not set
# CONFIG_USB_SERIAL_OPTICON is not set
# CONFIG_USB_SERIAL_DEBUG is not set

#
# USB Miscellaneous drivers
#
CONFIG_USB_EMI62=m
CONFIG_USB_EMI26=m
# CONFIG_USB_ADUTUX is not set
CONFIG_USB_SEVSEG=y
CONFIG_USB_RIO500=y
CONFIG_USB_LEGOTOWER=y
# CONFIG_USB_LCD is not set
CONFIG_USB_BERRY_CHARGE=m
CONFIG_USB_LED=y
CONFIG_USB_CYPRESS_CY7C63=y
CONFIG_USB_CYTHERM=y
CONFIG_USB_IDMOUSE=y
CONFIG_USB_FTDI_ELAN=m
CONFIG_USB_APPLEDISPLAY=m
CONFIG_USB_SISUSBVGA=m
# CONFIG_USB_SISUSBVGA_CON is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_ATM is not set
CONFIG_USB_GADGET=m
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_GADGET_VBUS_DRAW=2
CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_AT91 is not set
# CONFIG_USB_GADGET_ATMEL_USBA is not set
CONFIG_USB_GADGET_FSL_USB2=y
CONFIG_USB_FSL_USB2=m
# CONFIG_USB_GADGET_LH7A40X is not set
# CONFIG_USB_GADGET_OMAP is not set
# CONFIG_USB_GADGET_PXA25X is not set
# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_S3C2410 is not set
# CONFIG_USB_GADGET_IMX is not set
# CONFIG_USB_GADGET_M66592 is not set
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_FSL_QE is not set
# CONFIG_USB_GADGET_CI13XXX is not set
# CONFIG_USB_GADGET_NET2280 is not set
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
CONFIG_USB_GADGET_DUALSPEED=y
# CONFIG_USB_ZERO is not set
CONFIG_USB_ETH=m
CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_GADGETFS is not set
# CONFIG_USB_FILE_STORAGE is not set
CONFIG_USB_G_SERIAL=m
# CONFIG_USB_MIDI_GADGET is not set
CONFIG_USB_G_PRINTER=m
CONFIG_USB_CDC_COMPOSITE=m

#
# OTG and related infrastructure
#
CONFIG_USB_OTG_UTILS=y
CONFIG_USB_GPIO_VBUS=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_UWB=m
CONFIG_UWB_HWA=m
CONFIG_UWB_WHCI=m
CONFIG_UWB_WLP=m
# CONFIG_UWB_I1480U is not set
CONFIG_MMC=m
CONFIG_MMC_DEBUG=y
CONFIG_MMC_UNSAFE_RESUME=y

#
# MMC/SD/SDIO Card Drivers
#
CONFIG_SDIO_UART=m
# CONFIG_MMC_TEST is not set

#
# MMC/SD/SDIO Host Controller Drivers
#
CONFIG_MMC_SDHCI=m
# CONFIG_MMC_SDHCI_PCI is not set
# CONFIG_MMC_SDHCI_OF is not set
CONFIG_MMC_WBSD=m
# CONFIG_MMC_TIFM_SD is not set
CONFIG_MMC_SPI=m
# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
# CONFIG_LEDS_CLASS is not set

#
# LED drivers
#

#
# LED Triggers
#
# CONFIG_LEDS_TRIGGERS is not set
CONFIG_ACCESSIBILITY=y
# CONFIG_A11Y_BRAILLE_CONSOLE is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
CONFIG_RTC_DEBUG=y

#
# RTC interfaces
#
# CONFIG_RTC_INTF_SYSFS is not set
# CONFIG_RTC_INTF_PROC is not set
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
# CONFIG_RTC_DRV_TEST is not set

#
# I2C RTC drivers
#
CONFIG_RTC_DRV_DS1307=m
CONFIG_RTC_DRV_DS1374=m
CONFIG_RTC_DRV_DS1672=m
CONFIG_RTC_DRV_MAX6900=m
CONFIG_RTC_DRV_RS5C372=m
# CONFIG_RTC_DRV_ISL1208 is not set
CONFIG_RTC_DRV_X1205=m
CONFIG_RTC_DRV_PCF8563=m
CONFIG_RTC_DRV_PCF8583=m
# CONFIG_RTC_DRV_M41T80 is not set
CONFIG_RTC_DRV_S35390A=m
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set

#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
CONFIG_RTC_DRV_R9701=m
# CONFIG_RTC_DRV_RS5C348 is not set
# CONFIG_RTC_DRV_DS3234 is not set

#
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
CONFIG_RTC_DRV_DS1553=m
CONFIG_RTC_DRV_DS1742=y
# CONFIG_RTC_DRV_STK17TA8 is not set
CONFIG_RTC_DRV_M48T86=y
CONFIG_RTC_DRV_M48T35=y
CONFIG_RTC_DRV_M48T59=y
CONFIG_RTC_DRV_BQ4802=m
# CONFIG_RTC_DRV_V3020 is not set

#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_GENERIC=m
# CONFIG_DMADEVICES is not set
CONFIG_AUXDISPLAY=y
# CONFIG_UIO is not set
CONFIG_STAGING=y
CONFIG_STAGING_EXCLUDE_BUILD=y

#
# File systems
#
CONFIG_FS_POSIX_ACL=y
CONFIG_DNOTIFY=y
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=m
# CONFIG_AUTOFS4_FS is not set
CONFIG_FUSE_FS=m
CONFIG_GENERIC_ACL=y

#
# Caches
#
# CONFIG_FSCACHE is not set

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
# CONFIG_PROC_VMCORE is not set
# CONFIG_PROC_SYSCTL is not set
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ECRYPT_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
CONFIG_JFFS2_FS_WBUF_VERIFY=y
# CONFIG_JFFS2_SUMMARY is not set
CONFIG_JFFS2_FS_XATTR=y
# CONFIG_JFFS2_FS_POSIX_ACL is not set
CONFIG_JFFS2_FS_SECURITY=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_XATTR=y
# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_UBIFS_FS_DEBUG is not set
CONFIG_ROMFS_FS=m
# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
CONFIG_ROMFS_BACKED_BY_MTD=y
# CONFIG_ROMFS_BACKED_BY_BOTH is not set
CONFIG_ROMFS_ON_MTD=y
CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
CONFIG_SMB_FS=m
# CONFIG_SMB_NLS_DEFAULT is not set
CONFIG_CIFS=m
CONFIG_CIFS_STATS=y
CONFIG_CIFS_STATS2=y
CONFIG_CIFS_WEAK_PW_HASH=y
CONFIG_CIFS_UPCALL=y
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_CIFS_DEBUG2=y
# CONFIG_CIFS_DFS_UPCALL is not set
# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
CONFIG_NLS=m
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_737=m
CONFIG_NLS_CODEPAGE_775=m
# CONFIG_NLS_CODEPAGE_850 is not set
CONFIG_NLS_CODEPAGE_852=m
CONFIG_NLS_CODEPAGE_855=m
CONFIG_NLS_CODEPAGE_857=m
# CONFIG_NLS_CODEPAGE_860 is not set
CONFIG_NLS_CODEPAGE_861=m
# CONFIG_NLS_CODEPAGE_862 is not set
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
CONFIG_NLS_CODEPAGE_869=m
# CONFIG_NLS_CODEPAGE_936 is not set
CONFIG_NLS_CODEPAGE_950=m
# CONFIG_NLS_CODEPAGE_932 is not set
CONFIG_NLS_CODEPAGE_949=m
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
CONFIG_NLS_CODEPAGE_1251=m
# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
# CONFIG_NLS_ISO8859_3 is not set
CONFIG_NLS_ISO8859_4=m
# CONFIG_NLS_ISO8859_5 is not set
CONFIG_NLS_ISO8859_6=m
# CONFIG_NLS_ISO8859_7 is not set
CONFIG_NLS_ISO8859_9=m
CONFIG_NLS_ISO8859_13=m
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
CONFIG_DLM=m
# CONFIG_DLM_DEBUG is not set
CONFIG_BINARY_PRINTF=y

#
# Library routines
#
CONFIG_BITREVERSE=y
CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=m
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
CONFIG_CRC7=m
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=y
CONFIG_TEXTSEARCH_BM=y
CONFIG_TEXTSEARCH_FSM=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
CONFIG_NLATTR=y

#
# Kernel hacking
#
CONFIG_ENABLE_WARN_DEPRECATED=y
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
CONFIG_HEADERS_CHECK=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_LATENCYTOP=y
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
CONFIG_TRACING_SUPPORT=y

#
# Tracers
#
CONFIG_FUNCTION_TRACER=y
# CONFIG_FUNCTION_GRAPH_TRACER is not set
# CONFIG_SCHED_TRACER is not set
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_EVENT_TRACER=y
# CONFIG_BOOT_TRACER is not set
CONFIG_TRACE_BRANCH_PROFILING=y
CONFIG_PROFILE_ALL_BRANCHES=y
# CONFIG_BRANCH_TRACER is not set
CONFIG_STACK_TRACER=y
CONFIG_KMEMTRACE=y
# CONFIG_WORKQUEUE_TRACER is not set
# CONFIG_DYNAMIC_FTRACE is not set
CONFIG_FTRACE_SELFTEST=y
CONFIG_FTRACE_STARTUP_TEST=y
CONFIG_BUILD_DOCSRC=y
CONFIG_SAMPLES=y
CONFIG_SAMPLE_MARKERS=m
# CONFIG_SAMPLE_TRACEPOINTS is not set
# CONFIG_SAMPLE_KOBJECT is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_PRINT_STACK_DEPTH=64
CONFIG_IRQSTACKS=y
# CONFIG_VIRQ_DEBUG is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_PPC_EARLY_DEBUG is not set

#
# Security options
#
CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_NETWORK_XFRM=y
CONFIG_SECURITY_PATH=y
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_SECURITY_ROOTPLUG is not set
CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX=y
CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE=19
CONFIG_SECURITY_SMACK=y
# CONFIG_SECURITY_TOMOYO is not set
CONFIG_CRYPTO=y

#
# Crypto core or helper
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=y
# CONFIG_CRYPTO_NULL is not set
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_TEST=m

#
# Authenticated Encryption with Associated Data
#
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_SEQIV=y

#
# Block modes
#
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_ECB=y
# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_XTS is not set

#
# Hash modes
#
CONFIG_CRYPTO_HMAC=m
CONFIG_CRYPTO_XCBC=m

#
# Digest
#
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_RMD128=y
CONFIG_CRYPTO_RMD160=y
CONFIG_CRYPTO_RMD256=m
CONFIG_CRYPTO_RMD320=y
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=m
# CONFIG_CRYPTO_TGR192 is not set
CONFIG_CRYPTO_WP512=m

#
# Ciphers
#
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ANUBIS=y
CONFIG_CRYPTO_ARC4=y
# CONFIG_CRYPTO_BLOWFISH is not set
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
# CONFIG_CRYPTO_CAST6 is not set
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=y
CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TEA=y
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m

#
# Compression
#
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=y

#
# Random Number Generation
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_HIFN_795X=m
# CONFIG_CRYPTO_DEV_HIFN_795X_RNG is not set
# CONFIG_CRYPTO_DEV_TALITOS is not set
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
# CONFIG_VIRTUALIZATION is not set

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox