All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Xen-devel] [PATCH 3/3] xen/blk[front|back]: Enhance discard support with secure erasing support.
From: Konrad Rzeszutek Wilk @ 2011-10-20  3:46 UTC (permalink / raw)
  To: Li Dongyang
  Cc: Jan Beulich, Dong Yang Li, xen-devel@lists.xensource.com,
	Ian Campbell, linux-kernel@vger.kernel.org, hch@infradead.org
In-Reply-To: <CAKH3R4_TDxyNcsgZBOxQRS4U61h=bhY+Vap72AWa4CdQyQ7QfQ@mail.gmail.com>

On Thu, Oct 20, 2011 at 11:17:14AM +0800, Li Dongyang wrote:
> I think we also should mark the vbd has discard_secure if we are
> usingthe file backend,as if we punch a hole in the image, those blocks
> are freed tofilesystem and hardly to getthem back, or maybe write
> zeros to the range before we punch the hole is better?

You would have to write zeros to that range (or perhaps random values)
to emulate the secure delete. If you have a patch for that I would be interested
in seeing it.

Hmm, which reminds me - I should repost this patch series.

> On Mon, Oct 17, 2011 at 9:23 PM, Jan Beulich <JBeulich@suse.com> wrote:
> >>>> On 11.10.11 at 22:57, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> wrote:
> >> --- a/drivers/block/xen-blkfront.c
> >> +++ b/drivers/block/xen-blkfront.c
> >>...
> >> @@ -705,7 +711,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
> >>  static void blkif_completion(struct blk_shadow *s)
> >>  {
> >>       int i;
> >
> > This function gets called for all types of requests, and hence must filter
> > discard ones now that what would be nr_segments can be non-zero,
> > e.g.
> >
> >        if (s->req.operation == BLKIF_OP_DISCARD)
> >                return;
> >
> > Jan
> >
> >> -     for (i = 0; i < s->req.nr_segments; i++)
> >> +     for (i = 0; i < s->req.u1.nr_segments; i++)
> >>               gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL);
> >>  }
> >>
> >
> >
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel

^ permalink raw reply

* Re: [Xen-devel] [PATCH 3/3] xen/blk[front|back]: Enhance discard support with secure erasing support.
From: Konrad Rzeszutek Wilk @ 2011-10-21  0:06 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Ian Campbell, hch@infradead.org, xen-devel@lists.xensource.com,
	Dong Yang Li, linux-kernel@vger.kernel.org
In-Reply-To: <4E9C4855020000780005BA73@nat28.tlf.novell.com>

On Mon, Oct 17, 2011 at 02:23:01PM +0100, Jan Beulich wrote:
> >>> On 11.10.11 at 22:57, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> wrote:
> > --- a/drivers/block/xen-blkfront.c
> > +++ b/drivers/block/xen-blkfront.c
> >...
> > @@ -705,7 +711,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
> >  static void blkif_completion(struct blk_shadow *s)
> >  {
> >  	int i;
> 
> This function gets called for all types of requests, and hence must filter
> discard ones now that what would be nr_segments can be non-zero,


Oooh, nice catch.

> e.g.
> 
> 	if (s->req.operation == BLKIF_OP_DISCARD)
> 		return;
> 
> Jan
> 
> > -	for (i = 0; i < s->req.nr_segments; i++)
> > +	for (i = 0; i < s->req.u1.nr_segments; i++)
> >  		gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL);
> >  }
> >  
> 

^ permalink raw reply

* Re: [PATCH 3/4] net: xen-netback: use API provided by xenbus module to map rings
From: Konrad Rzeszutek Wilk @ 2011-10-20 21:00 UTC (permalink / raw)
  To: David Vrabel, davem; +Cc: xen-devel, linux-kernel, netdev, David S . Miller
In-Reply-To: <1319107519-2253-4-git-send-email-david.vrabel@citrix.com>

On Thu, Oct 20, 2011 at 11:45:18AM +0100, David Vrabel wrote:
> The xenbus module provides xenbus_map_ring_valloc() and
> xenbus_map_ring_vfree().  Use these to map the Tx and Rx ring pages
> granted by the frontend.
> 
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>


Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

> Dave, this is a standalone patch and can be applied independently of
> the rest of the series.

.. or Dave, if you would like I can carry these patches.

> 
>  drivers/net/xen-netback/common.h  |   11 ++---
>  drivers/net/xen-netback/netback.c |   80 ++++++++-----------------------------
>  2 files changed, 22 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
> index 161f207..94b79c3 100644
> --- a/drivers/net/xen-netback/common.h
> +++ b/drivers/net/xen-netback/common.h
> @@ -58,10 +58,6 @@ struct xenvif {
>  	u8               fe_dev_addr[6];
>  
>  	/* Physical parameters of the comms window. */
> -	grant_handle_t   tx_shmem_handle;
> -	grant_ref_t      tx_shmem_ref;
> -	grant_handle_t   rx_shmem_handle;
> -	grant_ref_t      rx_shmem_ref;
>  	unsigned int     irq;
>  
>  	/* List of frontends to notify after a batch of frames sent. */
> @@ -70,8 +66,6 @@ struct xenvif {
>  	/* The shared rings and indexes. */
>  	struct xen_netif_tx_back_ring tx;
>  	struct xen_netif_rx_back_ring rx;
> -	struct vm_struct *tx_comms_area;
> -	struct vm_struct *rx_comms_area;
>  
>  	/* Frontend feature information. */
>  	u8 can_sg:1;
> @@ -106,6 +100,11 @@ struct xenvif {
>  	wait_queue_head_t waiting_to_free;
>  };
>  
> +static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif)
> +{
> +	return to_xenbus_device(vif->dev->dev.parent);
> +}
> +
>  #define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
>  #define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
>  
> diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index fd00f25..3af2924 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -1577,88 +1577,42 @@ static int xen_netbk_kthread(void *data)
>  
>  void xen_netbk_unmap_frontend_rings(struct xenvif *vif)
>  {
> -	struct gnttab_unmap_grant_ref op;
> -
> -	if (vif->tx.sring) {
> -		gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr,
> -				    GNTMAP_host_map, vif->tx_shmem_handle);
> -
> -		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
> -			BUG();
> -	}
> -
> -	if (vif->rx.sring) {
> -		gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr,
> -				    GNTMAP_host_map, vif->rx_shmem_handle);
> -
> -		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
> -			BUG();
> -	}
> -	if (vif->rx_comms_area)
> -		free_vm_area(vif->rx_comms_area);
> -	if (vif->tx_comms_area)
> -		free_vm_area(vif->tx_comms_area);
> +	if (vif->tx.sring)
> +		xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif),
> +					vif->tx.sring);
> +	if (vif->rx.sring)
> +		xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif),
> +					vif->rx.sring);
>  }
>  
>  int xen_netbk_map_frontend_rings(struct xenvif *vif,
>  				 grant_ref_t tx_ring_ref,
>  				 grant_ref_t rx_ring_ref)
>  {
> -	struct gnttab_map_grant_ref op;
> +	void *addr;
>  	struct xen_netif_tx_sring *txs;
>  	struct xen_netif_rx_sring *rxs;
>  
>  	int err = -ENOMEM;
>  
> -	vif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
> -	if (vif->tx_comms_area == NULL)
> +	err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif),
> +				     tx_ring_ref, &addr);
> +	if (err)
>  		goto err;
>  
> -	vif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
> -	if (vif->rx_comms_area == NULL)
> -		goto err;
> -
> -	gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr,
> -			  GNTMAP_host_map, tx_ring_ref, vif->domid);
> -
> -	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -		BUG();
> -
> -	if (op.status) {
> -		netdev_warn(vif->dev,
> -			    "failed to map tx ring. err=%d status=%d\n",
> -			    err, op.status);
> -		err = op.status;
> -		goto err;
> -	}
> -
> -	vif->tx_shmem_ref    = tx_ring_ref;
> -	vif->tx_shmem_handle = op.handle;
> -
> -	txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr;
> +	txs = (struct xen_netif_tx_sring *)addr;
>  	BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE);
>  
> -	gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr,
> -			  GNTMAP_host_map, rx_ring_ref, vif->domid);
> -
> -	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -		BUG();
> -
> -	if (op.status) {
> -		netdev_warn(vif->dev,
> -			    "failed to map rx ring. err=%d status=%d\n",
> -			    err, op.status);
> -		err = op.status;
> +	err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif),
> +				     rx_ring_ref, &addr);
> +	if (err)
>  		goto err;
> -	}
> -
> -	vif->rx_shmem_ref     = rx_ring_ref;
> -	vif->rx_shmem_handle  = op.handle;
> -	vif->rx_req_cons_peek = 0;
>  
> -	rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr;
> +	rxs = (struct xen_netif_rx_sring *)addr;
>  	BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE);
>  
> +	vif->rx_req_cons_peek = 0;
> +
>  	return 0;
>  
>  err:
> -- 
> 1.7.2.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/4] xen: use generic functions instead of xen_{alloc,free}_vm_area()
From: Konrad Rzeszutek Wilk @ 2011-10-20 23:45 UTC (permalink / raw)
  To: David Vrabel; +Cc: xen-devel, linux-kernel
In-Reply-To: <1319107519-2253-2-git-send-email-david.vrabel@citrix.com>

On Thu, Oct 20, 2011 at 11:45:16AM +0100, David Vrabel wrote:
> Replace calls to the Xen-specific xen_alloc_vm_area() and
> xen_free_vm_area() functions with the generic equivalent
> (alloc_vm_area() and free_vm_area()).
> 
> On x86, these were identical already.
> 
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>

Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
>  arch/ia64/include/asm/xen/grant_table.h |   29 --------------
>  arch/ia64/xen/grant-table.c             |   62 -------------------------------
>  arch/x86/include/asm/xen/grant_table.h  |    7 ---
>  arch/x86/xen/grant-table.c              |    2 +-
>  drivers/xen/xenbus/xenbus_client.c      |    6 +-
>  include/xen/grant_table.h               |    1 -
>  6 files changed, 4 insertions(+), 103 deletions(-)
>  delete mode 100644 arch/ia64/include/asm/xen/grant_table.h
>  delete mode 100644 arch/x86/include/asm/xen/grant_table.h
> 
> diff --git a/arch/ia64/include/asm/xen/grant_table.h b/arch/ia64/include/asm/xen/grant_table.h
> deleted file mode 100644
> index 2b1fae0..0000000
> --- a/arch/ia64/include/asm/xen/grant_table.h
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -/******************************************************************************
> - * arch/ia64/include/asm/xen/grant_table.h
> - *
> - * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
> - *                    VA Linux Systems Japan K.K.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> - *
> - */
> -
> -#ifndef _ASM_IA64_XEN_GRANT_TABLE_H
> -#define _ASM_IA64_XEN_GRANT_TABLE_H
> -
> -struct vm_struct *xen_alloc_vm_area(unsigned long size);
> -void xen_free_vm_area(struct vm_struct *area);
> -
> -#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */
> diff --git a/arch/ia64/xen/grant-table.c b/arch/ia64/xen/grant-table.c
> index 48cca37..c182813 100644
> --- a/arch/ia64/xen/grant-table.c
> +++ b/arch/ia64/xen/grant-table.c
> @@ -31,68 +31,6 @@
>  
>  #include <asm/xen/hypervisor.h>
>  
> -struct vm_struct *xen_alloc_vm_area(unsigned long size)
> -{
> -	int order;
> -	unsigned long virt;
> -	unsigned long nr_pages;
> -	struct vm_struct *area;
> -
> -	order = get_order(size);
> -	virt = __get_free_pages(GFP_KERNEL, order);
> -	if (virt == 0)
> -		goto err0;
> -	nr_pages = 1 << order;
> -	scrub_pages(virt, nr_pages);
> -
> -	area = kmalloc(sizeof(*area), GFP_KERNEL);
> -	if (area == NULL)
> -		goto err1;
> -
> -	area->flags = VM_IOREMAP;
> -	area->addr = (void *)virt;
> -	area->size = size;
> -	area->pages = NULL;
> -	area->nr_pages = nr_pages;
> -	area->phys_addr = 0;	/* xenbus_map_ring_valloc uses this field!  */
> -
> -	return area;
> -
> -err1:
> -	free_pages(virt, order);
> -err0:
> -	return NULL;
> -}
> -EXPORT_SYMBOL_GPL(xen_alloc_vm_area);
> -
> -void xen_free_vm_area(struct vm_struct *area)
> -{
> -	unsigned int order = get_order(area->size);
> -	unsigned long i;
> -	unsigned long phys_addr = __pa(area->addr);
> -
> -	/* This area is used for foreign page mappping.
> -	 * So underlying machine page may not be assigned. */
> -	for (i = 0; i < (1 << order); i++) {
> -		unsigned long ret;
> -		unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i;
> -		struct xen_memory_reservation reservation = {
> -			.nr_extents   = 1,
> -			.address_bits = 0,
> -			.extent_order = 0,
> -			.domid        = DOMID_SELF
> -		};
> -		set_xen_guest_handle(reservation.extent_start, &gpfn);
> -		ret = HYPERVISOR_memory_op(XENMEM_populate_physmap,
> -					   &reservation);
> -		BUG_ON(ret != 1);
> -	}
> -	free_pages((unsigned long)area->addr, order);
> -	kfree(area);
> -}
> -EXPORT_SYMBOL_GPL(xen_free_vm_area);
> -
> -
>  /****************************************************************************
>   * grant table hack
>   * cmd: GNTTABOP_xxx
> diff --git a/arch/x86/include/asm/xen/grant_table.h b/arch/x86/include/asm/xen/grant_table.h
> deleted file mode 100644
> index fdbbb45..0000000
> --- a/arch/x86/include/asm/xen/grant_table.h
> +++ /dev/null
> @@ -1,7 +0,0 @@
> -#ifndef _ASM_X86_XEN_GRANT_TABLE_H
> -#define _ASM_X86_XEN_GRANT_TABLE_H
> -
> -#define xen_alloc_vm_area(size)	alloc_vm_area(size)
> -#define xen_free_vm_area(area)	free_vm_area(area)
> -
> -#endif /* _ASM_X86_XEN_GRANT_TABLE_H */
> diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
> index 49ba9b5..6bbfd7a 100644
> --- a/arch/x86/xen/grant-table.c
> +++ b/arch/x86/xen/grant-table.c
> @@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
>  
>  	if (shared == NULL) {
>  		struct vm_struct *area =
> -			xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes);
> +			alloc_vm_area(PAGE_SIZE * max_nr_gframes);
>  		BUG_ON(area == NULL);
>  		shared = area->addr;
>  		*__shared = shared;
> diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
> index cdacf92..229d3ad 100644
> --- a/drivers/xen/xenbus/xenbus_client.c
> +++ b/drivers/xen/xenbus/xenbus_client.c
> @@ -443,7 +443,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
>  
>  	*vaddr = NULL;
>  
> -	area = xen_alloc_vm_area(PAGE_SIZE);
> +	area = alloc_vm_area(PAGE_SIZE);
>  	if (!area)
>  		return -ENOMEM;
>  
> @@ -453,7 +453,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
>  		BUG();
>  
>  	if (op.status != GNTST_okay) {
> -		xen_free_vm_area(area);
> +		free_vm_area(area);
>  		xenbus_dev_fatal(dev, op.status,
>  				 "mapping in shared page %d from domain %d",
>  				 gnt_ref, dev->otherend_id);
> @@ -552,7 +552,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
>  		BUG();
>  
>  	if (op.status == GNTST_okay)
> -		xen_free_vm_area(area);
> +		free_vm_area(area);
>  	else
>  		xenbus_dev_error(dev, op.status,
>  				 "unmapping page at handle %d error %d",
> diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
> index b1fab6b..8a8bb76 100644
> --- a/include/xen/grant_table.h
> +++ b/include/xen/grant_table.h
> @@ -43,7 +43,6 @@
>  #include <xen/interface/grant_table.h>
>  
>  #include <asm/xen/hypervisor.h>
> -#include <asm/xen/grant_table.h>
>  
>  #include <xen/features.h>
>  
> -- 
> 1.7.2.5

^ permalink raw reply

* [PATCH v4] virtio: Add platform bus driver for memory mapped virtio device
From: Pawel Moll @ 2011-10-24 13:07 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, virtualization
  Cc: Pawel Moll, Rusty Russell, Anthony Liguori, Michael S.Tsirkin
In-Reply-To: <1319461560.3668.16.camel@hornet.cambridge.arm.com>

This patch, based on virtio PCI driver, adds support for memory
mapped (platform) virtio device. This should allow environments
like qemu to use virtio-based block & network devices even on
platforms without PCI support.

One can define and register a platform device which resources
will describe memory mapped control registers and "mailbox"
interrupt. Such device can be also instantiated using the Device
Tree node with compatible property equal "virtio,mmio".

Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: Michael S.Tsirkin <mst@redhat.com>
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---

Changes since v3:

* Dynamic config changes are handled now
* Interrupt acknowledge register moved to 0x064
* Added interrupt status register at 0x060
* Added interrupt flags (VIRTIO_MMIO_INT_VRING & VIRTIO_MMIO_INT_CONFIG)

Changes since v2:

* Fixed bug a bug in vm_find_vqs() error handling code (interrupt was
  freed twice)

Changes since v1:

* Added new QueueNumMax register at 0x034, shifting QueueNum,
  QueueAlign and QueuePFN by 4 bytes
* Queue page allocation strategy changed

 Documentation/devicetree/bindings/virtio/mmio.txt |   17 +
 drivers/virtio/Kconfig                            |   11 +
 drivers/virtio/Makefile                           |    1 +
 drivers/virtio/virtio_mmio.c                      |  479 +++++++++++++++++++++
 include/linux/virtio_mmio.h                       |  111 +++++
 5 files changed, 619 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/virtio/mmio.txt
 create mode 100644 drivers/virtio/virtio_mmio.c
 create mode 100644 include/linux/virtio_mmio.h

diff --git a/Documentation/devicetree/bindings/virtio/mmio.txt b/Documentation/devicetree/bindings/virtio/mmio.txt
new file mode 100644
index 0000000..5069c1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/virtio/mmio.txt
@@ -0,0 +1,17 @@
+* virtio memory mapped device
+
+See http://ozlabs.org/~rusty/virtio-spec/ for more details.
+
+Required properties:
+
+- compatible:	"virtio,mmio" compatibility string
+- reg:		control registers base address and size including configuration space
+- interrupts:	interrupt generated by the device
+
+Example:
+
+	virtio_block@3000 {
+		compatible = "virtio,mmio";
+		reg = <0x3000 0x100>;
+		interrupts = <41>;
+	}
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 57e493b..816ed08 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -35,4 +35,15 @@ config VIRTIO_BALLOON
 
 	 If unsure, say M.
 
+ config VIRTIO_MMIO
+ 	tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+ 	select VIRTIO
+ 	select VIRTIO_RING
+ 	---help---
+ 	 This drivers provides support for memory mapped virtio
+	 platform device driver.
+
+ 	 If unsure, say N.
+
 endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 6738c44..5a4c63c 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_VIRTIO) += virtio.o
 obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
+obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
 obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
new file mode 100644
index 0000000..acc5e43
--- /dev/null
+++ b/drivers/virtio/virtio_mmio.c
@@ -0,0 +1,479 @@
+/*
+ * Virtio memory mapped device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * This module allows virtio devices to be used over a virtual, memory mapped
+ * platform device.
+ *
+ * Registers layout (all 32-bit wide):
+ *
+ * offset d. name             description
+ * ------ -- ---------------- -----------------
+ *
+ * 0x000  R  MagicValue       Magic value "virt"
+ * 0x004  R  Version          Device version (current max. 1)
+ * 0x008  R  DeviceID         Virtio device ID
+ * 0x00c  R  VendorID         Virtio vendor ID
+ *
+ * 0x010  R  HostFeatures     Features supported by the host
+ * 0x014  W  HostFeaturesSel  Set of host features to access via HostFeatures
+ *
+ * 0x020  W  GuestFeatures    Features activated by the guest
+ * 0x024  W  GuestFeaturesSel Set of activated features to set via GuestFeatures
+ * 0x028  W  GuestPageSize    Size of guest's memory page in bytes
+ *
+ * 0x030  W  QueueSel         Queue selector
+ * 0x034  R  QueueNumMax      Maximum size of the currently selected queue
+ * 0x038  W  QueueNum         Queue size for the currently selected queue
+ * 0x03c  W  QueueAlign       Used Ring alignment for the current queue
+ * 0x040  RW QueuePFN         PFN for the currently selected queue
+ *
+ * 0x050  W  QueueNotify      Queue notifier
+ * 0x060  R  InterruptStatus  Interrupt status register
+ * 0x060  W  InterruptACK     Interrupt acknowledge register
+ * 0x070  RW Status           Device status register
+ *
+ * 0x100+ RW                  Device-specific configuration space
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_mmio.h>
+#include <linux/virtio_ring.h>
+
+
+
+/* The alignment to use between consumer and producer parts of vring.
+ * Currently hardcoded to the page size. */
+#define VIRTIO_MMIO_VRING_ALIGN		PAGE_SIZE
+
+
+
+#define to_virtio_mmio_device(_plat_dev) \
+	container_of(_plat_dev, struct virtio_mmio_device, vdev)
+
+struct virtio_mmio_device {
+	struct virtio_device vdev;
+	struct platform_device *pdev;
+
+	void __iomem *base;
+	unsigned long version;
+
+	/* a list of queues so we can dispatch IRQs */
+	spinlock_t lock;
+	struct list_head virtqueues;
+};
+
+struct virtio_mmio_vq_info {
+	/* the actual virtqueue */
+	struct virtqueue *vq;
+
+	/* the number of entries in the queue */
+	unsigned int num;
+
+	/* the index of the queue */
+	int queue_index;
+
+	/* the virtual address of the ring queue */
+	void *queue;
+
+	/* the list node for the virtqueues list */
+	struct list_head node;
+};
+
+
+
+/* Configuration interface */
+
+static u32 vm_get_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* TODO: Features > 32 bits */
+	writel(0, vm_dev->base + VIRTIO_MMIO_HOST_FEATURES_SEL);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_HOST_FEATURES);
+}
+
+static void vm_finalize_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	int i;
+
+	/* Give virtio_ring a chance to accept features. */
+	vring_transport_features(vdev);
+
+	for (i = 0; i < ARRAY_SIZE(vdev->features); i++) {
+		writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SET);
+		writel(vdev->features[i],
+				vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES);
+	}
+}
+
+static void vm_get(struct virtio_device *vdev, unsigned offset,
+		   void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static void vm_set(struct virtio_device *vdev, unsigned offset,
+		   const void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	const u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static u8 vm_get_status(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_STATUS) & 0xff;
+}
+
+static void vm_set_status(struct virtio_device *vdev, u8 status)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* We should never be setting status to 0. */
+	BUG_ON(status == 0);
+
+	writel(status, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+static void vm_reset(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* 0 status means a reset. */
+	writel(0, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+
+
+/* Transport interface */
+
+/* the notify function used when creating a virt queue */
+static void vm_notify(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+
+	/* We write the queue's selector into the notification register to
+	 * signal the other end */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+}
+
+/* Notify all virtqueues on an interrupt. */
+static irqreturn_t vm_interrupt(int irq, void *opaque)
+{
+	struct virtio_mmio_device *vm_dev = opaque;
+	struct virtio_mmio_vq_info *info;
+	struct virtio_driver *vdrv = container_of(vm_dev->vdev.dev.driver,
+			struct virtio_driver, driver);
+	unsigned long status;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+
+	/* Read and acknowledge interrupts */
+	status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS);
+	writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK);
+
+	if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)
+			&& vdrv && vdrv->config_changed) {
+		vdrv->config_changed(&vm_dev->vdev);
+		ret = IRQ_HANDLED;
+	}
+
+	if (likely(status & VIRTIO_MMIO_INT_VRING)) {
+		spin_lock_irqsave(&vm_dev->lock, flags);
+		list_for_each_entry(info, &vm_dev->virtqueues, node)
+			ret |= vring_interrupt(irq, info->vq);
+		spin_unlock_irqrestore(&vm_dev->lock, flags);
+	}
+
+	return ret;
+}
+
+
+
+static void vm_del_vq(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+	unsigned long flags, size;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_del(&info->node);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	vring_del_virtqueue(vq);
+
+	/* Select and deactivate the queue */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN));
+	free_pages_exact(info->queue, size);
+	kfree(info);
+}
+
+static void vm_del_vqs(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtqueue *vq, *n;
+
+	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+		vm_del_vq(vq);
+
+	free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev);
+}
+
+
+
+static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
+				  void (*callback)(struct virtqueue *vq),
+				  const char *name)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtio_mmio_vq_info *info;
+	struct virtqueue *vq;
+	unsigned long flags, size;
+	int err;
+
+	/* Select the queue we're interested in */
+	writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+
+	/* Queue shouldn't already be set up. */
+	if (readl(vm_dev->base + VIRTIO_MMIO_QUEUE_PFN)) {
+		err = -ENOENT;
+		goto error_available;
+	}
+
+	/* Allocate and fill out our active queue description */
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		err = -ENOMEM;
+		goto error_kmalloc;
+	}
+	info->queue_index = index;
+
+	/* Allocate pages for the queue - start with a queue as big as
+	 * possible (limited by maximum size allowed by device), drop down
+	 * to a minimal size, just big enough to fit descriptor table
+	 * and two rings (which makes it "alignment_size * 2")
+	 */
+	info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
+	while (1) {
+		size = PAGE_ALIGN(vring_size(info->num,
+				VIRTIO_MMIO_VRING_ALIGN));
+		/* Already smallest possible allocation? */
+		if (size <= VIRTIO_MMIO_VRING_ALIGN * 2) {
+			err = -ENOMEM;
+			goto error_alloc_pages;
+		}
+
+		info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
+		if (info->queue)
+			break;
+
+		info->num /= 2;
+	}
+
+	/* Activate the queue */
+	writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
+	writel(VIRTIO_MMIO_VRING_ALIGN,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
+	writel(virt_to_phys(info->queue) >> PAGE_SHIFT,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	/* Create the vring */
+	vq = vring_new_virtqueue(info->num, VIRTIO_MMIO_VRING_ALIGN,
+				 vdev, info->queue, vm_notify, callback, name);
+	if (!vq) {
+		err = -ENOMEM;
+		goto error_new_virtqueue;
+	}
+
+	vq->priv = info;
+	info->vq = vq;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_add(&info->node, &vm_dev->virtqueues);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	return vq;
+
+error_new_virtqueue:
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+	free_pages_exact(info->queue, size);
+error_alloc_pages:
+	kfree(info);
+error_kmalloc:
+error_available:
+	return ERR_PTR(err);
+}
+
+static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+		       struct virtqueue *vqs[],
+		       vq_callback_t *callbacks[],
+		       const char *names[])
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
+	int i, err;
+
+	err = request_irq(irq, vm_interrupt, IRQF_SHARED,
+			dev_name(&vdev->dev), vm_dev);
+	if (err)
+		return err;
+
+	for (i = 0; i < nvqs; ++i) {
+		vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]);
+		if (IS_ERR(vqs[i])) {
+			vm_del_vqs(vdev);
+			return PTR_ERR(vqs[i]);
+		}
+	}
+
+	return 0;
+}
+
+
+
+static struct virtio_config_ops virtio_mmio_config_ops = {
+	.get		= vm_get,
+	.set		= vm_set,
+	.get_status	= vm_get_status,
+	.set_status	= vm_set_status,
+	.reset		= vm_reset,
+	.find_vqs	= vm_find_vqs,
+	.del_vqs	= vm_del_vqs,
+	.get_features	= vm_get_features,
+	.finalize_features = vm_finalize_features,
+};
+
+
+
+/* Platform device */
+
+static int __devinit virtio_mmio_probe(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev;
+	struct resource *mem;
+	unsigned long magic;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start,
+			resource_size(mem), pdev->name))
+		return -EBUSY;
+
+	vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
+	if (!vm_dev)
+		return  -ENOMEM;
+
+	vm_dev->vdev.dev.parent = &pdev->dev;
+	vm_dev->vdev.config = &virtio_mmio_config_ops;
+	vm_dev->pdev = pdev;
+	INIT_LIST_HEAD(&vm_dev->virtqueues);
+	spin_lock_init(&vm_dev->lock);
+
+	vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (vm_dev->base == NULL)
+		return -EFAULT;
+
+	/* Check magic value */
+	magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
+	if (memcmp(&magic, "virt", 4) != 0) {
+		dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic);
+		return -ENODEV;
+	}
+
+	/* Check device version */
+	vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION);
+	if (vm_dev->version != 1) {
+		dev_err(&pdev->dev, "Version %ld not supported!\n",
+				vm_dev->version);
+		return -ENXIO;
+	}
+
+	vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
+	vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
+
+	writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+
+	platform_set_drvdata(pdev, vm_dev);
+
+	return register_virtio_device(&vm_dev->vdev);
+}
+
+static int __devexit virtio_mmio_remove(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev);
+
+	unregister_virtio_device(&vm_dev->vdev);
+
+	return 0;
+}
+
+
+
+/* Platform driver */
+
+static struct of_device_id virtio_mmio_match[] = {
+	{ .compatible = "virtio,mmio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, virtio_mmio_match);
+
+static struct platform_driver virtio_mmio_driver = {
+	.probe		= virtio_mmio_probe,
+	.remove		= __devexit_p(virtio_mmio_remove),
+	.driver		= {
+		.name	= "virtio-mmio",
+		.owner	= THIS_MODULE,
+		.of_match_table	= virtio_mmio_match,
+	},
+};
+
+static int __init virtio_mmio_init(void)
+{
+	return platform_driver_register(&virtio_mmio_driver);
+}
+
+static void __exit virtio_mmio_exit(void)
+{
+	platform_driver_unregister(&virtio_mmio_driver);
+}
+
+module_init(virtio_mmio_init);
+module_exit(virtio_mmio_exit);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Platform bus driver for memory mapped virtio devices");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/virtio_mmio.h b/include/linux/virtio_mmio.h
new file mode 100644
index 0000000..27c7ede
--- /dev/null
+++ b/include/linux/virtio_mmio.h
@@ -0,0 +1,111 @@
+/*
+ * Virtio platform device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_VIRTIO_MMIO_H
+#define _LINUX_VIRTIO_MMIO_H
+
+/*
+ * Control registers
+ */
+
+/* Magic value ("virt" string) - Read Only */
+#define VIRTIO_MMIO_MAGIC_VALUE		0x000
+
+/* Virtio device version - Read Only */
+#define VIRTIO_MMIO_VERSION		0x004
+
+/* Virtio device ID - Read Only */
+#define VIRTIO_MMIO_DEVICE_ID		0x008
+
+/* Virtio vendor ID - Read Only */
+#define VIRTIO_MMIO_VENDOR_ID		0x00c
+
+/* Bitmask of the features supported by the host
+ * (32 bits per set) - Read Only */
+#define VIRTIO_MMIO_HOST_FEATURES	0x010
+
+/* Host features set selector - Write Only */
+#define VIRTIO_MMIO_HOST_FEATURES_SEL	0x014
+
+/* Bitmask of features activated by the guest
+ * (32 bits per set) - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES	0x020
+
+/* Activated features set selector - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES_SET	0x024
+
+/* Guest's memory page size in bytes - Write Only */
+#define VIRTIO_MMIO_GUEST_PAGE_SIZE	0x028
+
+/* Queue selector - Write Only */
+#define VIRTIO_MMIO_QUEUE_SEL		0x030
+
+/* Maximum size of the currently selected queue - Read Only */
+#define VIRTIO_MMIO_QUEUE_NUM_MAX	0x034
+
+/* Queue size for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_NUM		0x038
+
+/* Used Ring alignment for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_ALIGN		0x03c
+
+/* Guest's PFN for the currently selected queue - Read Write */
+#define VIRTIO_MMIO_QUEUE_PFN		0x040
+
+/* Queue notifier - Write Only */
+#define VIRTIO_MMIO_QUEUE_NOTIFY	0x050
+
+/* Interrupt status - Read Only */
+#define VIRTIO_MMIO_INTERRUPT_STATUS	0x060
+
+/* Interrupt acknowledge - Write Only */
+#define VIRTIO_MMIO_INTERRUPT_ACK	0x064
+
+/* Device status register - Read Write */
+#define VIRTIO_MMIO_STATUS		0x070
+
+/* The config space is defined by each driver as
+ * the per-driver configuration space - Read Write */
+#define VIRTIO_MMIO_CONFIG		0x100
+
+
+
+/*
+ * Interrupt flags (re: interrupt status & acknowledge registers)
+ */
+
+#define VIRTIO_MMIO_INT_VRING		(1 << 0)
+#define VIRTIO_MMIO_INT_CONFIG		(1 << 1)
+
+#endif
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH v4] virtio: Add platform bus driver for memory mapped virtio device
From: Pawel Moll @ 2011-10-24 13:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1319461560.3668.16.camel@hornet.cambridge.arm.com>

This patch, based on virtio PCI driver, adds support for memory
mapped (platform) virtio device. This should allow environments
like qemu to use virtio-based block & network devices even on
platforms without PCI support.

One can define and register a platform device which resources
will describe memory mapped control registers and "mailbox"
interrupt. Such device can be also instantiated using the Device
Tree node with compatible property equal "virtio,mmio".

Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: Michael S.Tsirkin <mst@redhat.com>
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---

Changes since v3:

* Dynamic config changes are handled now
* Interrupt acknowledge register moved to 0x064
* Added interrupt status register at 0x060
* Added interrupt flags (VIRTIO_MMIO_INT_VRING & VIRTIO_MMIO_INT_CONFIG)

Changes since v2:

* Fixed bug a bug in vm_find_vqs() error handling code (interrupt was
  freed twice)

Changes since v1:

* Added new QueueNumMax register at 0x034, shifting QueueNum,
  QueueAlign and QueuePFN by 4 bytes
* Queue page allocation strategy changed

 Documentation/devicetree/bindings/virtio/mmio.txt |   17 +
 drivers/virtio/Kconfig                            |   11 +
 drivers/virtio/Makefile                           |    1 +
 drivers/virtio/virtio_mmio.c                      |  479 +++++++++++++++++++++
 include/linux/virtio_mmio.h                       |  111 +++++
 5 files changed, 619 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/virtio/mmio.txt
 create mode 100644 drivers/virtio/virtio_mmio.c
 create mode 100644 include/linux/virtio_mmio.h

diff --git a/Documentation/devicetree/bindings/virtio/mmio.txt b/Documentation/devicetree/bindings/virtio/mmio.txt
new file mode 100644
index 0000000..5069c1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/virtio/mmio.txt
@@ -0,0 +1,17 @@
+* virtio memory mapped device
+
+See http://ozlabs.org/~rusty/virtio-spec/ for more details.
+
+Required properties:
+
+- compatible:	"virtio,mmio" compatibility string
+- reg:		control registers base address and size including configuration space
+- interrupts:	interrupt generated by the device
+
+Example:
+
+	virtio_block at 3000 {
+		compatible = "virtio,mmio";
+		reg = <0x3000 0x100>;
+		interrupts = <41>;
+	}
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 57e493b..816ed08 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -35,4 +35,15 @@ config VIRTIO_BALLOON
 
 	 If unsure, say M.
 
+ config VIRTIO_MMIO
+ 	tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+ 	select VIRTIO
+ 	select VIRTIO_RING
+ 	---help---
+ 	 This drivers provides support for memory mapped virtio
+	 platform device driver.
+
+ 	 If unsure, say N.
+
 endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 6738c44..5a4c63c 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_VIRTIO) += virtio.o
 obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
+obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
 obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
new file mode 100644
index 0000000..acc5e43
--- /dev/null
+++ b/drivers/virtio/virtio_mmio.c
@@ -0,0 +1,479 @@
+/*
+ * Virtio memory mapped device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * This module allows virtio devices to be used over a virtual, memory mapped
+ * platform device.
+ *
+ * Registers layout (all 32-bit wide):
+ *
+ * offset d. name             description
+ * ------ -- ---------------- -----------------
+ *
+ * 0x000  R  MagicValue       Magic value "virt"
+ * 0x004  R  Version          Device version (current max. 1)
+ * 0x008  R  DeviceID         Virtio device ID
+ * 0x00c  R  VendorID         Virtio vendor ID
+ *
+ * 0x010  R  HostFeatures     Features supported by the host
+ * 0x014  W  HostFeaturesSel  Set of host features to access via HostFeatures
+ *
+ * 0x020  W  GuestFeatures    Features activated by the guest
+ * 0x024  W  GuestFeaturesSel Set of activated features to set via GuestFeatures
+ * 0x028  W  GuestPageSize    Size of guest's memory page in bytes
+ *
+ * 0x030  W  QueueSel         Queue selector
+ * 0x034  R  QueueNumMax      Maximum size of the currently selected queue
+ * 0x038  W  QueueNum         Queue size for the currently selected queue
+ * 0x03c  W  QueueAlign       Used Ring alignment for the current queue
+ * 0x040  RW QueuePFN         PFN for the currently selected queue
+ *
+ * 0x050  W  QueueNotify      Queue notifier
+ * 0x060  R  InterruptStatus  Interrupt status register
+ * 0x060  W  InterruptACK     Interrupt acknowledge register
+ * 0x070  RW Status           Device status register
+ *
+ * 0x100+ RW                  Device-specific configuration space
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_mmio.h>
+#include <linux/virtio_ring.h>
+
+
+
+/* The alignment to use between consumer and producer parts of vring.
+ * Currently hardcoded to the page size. */
+#define VIRTIO_MMIO_VRING_ALIGN		PAGE_SIZE
+
+
+
+#define to_virtio_mmio_device(_plat_dev) \
+	container_of(_plat_dev, struct virtio_mmio_device, vdev)
+
+struct virtio_mmio_device {
+	struct virtio_device vdev;
+	struct platform_device *pdev;
+
+	void __iomem *base;
+	unsigned long version;
+
+	/* a list of queues so we can dispatch IRQs */
+	spinlock_t lock;
+	struct list_head virtqueues;
+};
+
+struct virtio_mmio_vq_info {
+	/* the actual virtqueue */
+	struct virtqueue *vq;
+
+	/* the number of entries in the queue */
+	unsigned int num;
+
+	/* the index of the queue */
+	int queue_index;
+
+	/* the virtual address of the ring queue */
+	void *queue;
+
+	/* the list node for the virtqueues list */
+	struct list_head node;
+};
+
+
+
+/* Configuration interface */
+
+static u32 vm_get_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* TODO: Features > 32 bits */
+	writel(0, vm_dev->base + VIRTIO_MMIO_HOST_FEATURES_SEL);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_HOST_FEATURES);
+}
+
+static void vm_finalize_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	int i;
+
+	/* Give virtio_ring a chance to accept features. */
+	vring_transport_features(vdev);
+
+	for (i = 0; i < ARRAY_SIZE(vdev->features); i++) {
+		writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SET);
+		writel(vdev->features[i],
+				vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES);
+	}
+}
+
+static void vm_get(struct virtio_device *vdev, unsigned offset,
+		   void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static void vm_set(struct virtio_device *vdev, unsigned offset,
+		   const void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	const u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static u8 vm_get_status(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_STATUS) & 0xff;
+}
+
+static void vm_set_status(struct virtio_device *vdev, u8 status)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* We should never be setting status to 0. */
+	BUG_ON(status == 0);
+
+	writel(status, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+static void vm_reset(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* 0 status means a reset. */
+	writel(0, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+
+
+/* Transport interface */
+
+/* the notify function used when creating a virt queue */
+static void vm_notify(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+
+	/* We write the queue's selector into the notification register to
+	 * signal the other end */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+}
+
+/* Notify all virtqueues on an interrupt. */
+static irqreturn_t vm_interrupt(int irq, void *opaque)
+{
+	struct virtio_mmio_device *vm_dev = opaque;
+	struct virtio_mmio_vq_info *info;
+	struct virtio_driver *vdrv = container_of(vm_dev->vdev.dev.driver,
+			struct virtio_driver, driver);
+	unsigned long status;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+
+	/* Read and acknowledge interrupts */
+	status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS);
+	writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK);
+
+	if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)
+			&& vdrv && vdrv->config_changed) {
+		vdrv->config_changed(&vm_dev->vdev);
+		ret = IRQ_HANDLED;
+	}
+
+	if (likely(status & VIRTIO_MMIO_INT_VRING)) {
+		spin_lock_irqsave(&vm_dev->lock, flags);
+		list_for_each_entry(info, &vm_dev->virtqueues, node)
+			ret |= vring_interrupt(irq, info->vq);
+		spin_unlock_irqrestore(&vm_dev->lock, flags);
+	}
+
+	return ret;
+}
+
+
+
+static void vm_del_vq(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+	unsigned long flags, size;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_del(&info->node);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	vring_del_virtqueue(vq);
+
+	/* Select and deactivate the queue */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN));
+	free_pages_exact(info->queue, size);
+	kfree(info);
+}
+
+static void vm_del_vqs(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtqueue *vq, *n;
+
+	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+		vm_del_vq(vq);
+
+	free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev);
+}
+
+
+
+static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
+				  void (*callback)(struct virtqueue *vq),
+				  const char *name)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtio_mmio_vq_info *info;
+	struct virtqueue *vq;
+	unsigned long flags, size;
+	int err;
+
+	/* Select the queue we're interested in */
+	writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+
+	/* Queue shouldn't already be set up. */
+	if (readl(vm_dev->base + VIRTIO_MMIO_QUEUE_PFN)) {
+		err = -ENOENT;
+		goto error_available;
+	}
+
+	/* Allocate and fill out our active queue description */
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		err = -ENOMEM;
+		goto error_kmalloc;
+	}
+	info->queue_index = index;
+
+	/* Allocate pages for the queue - start with a queue as big as
+	 * possible (limited by maximum size allowed by device), drop down
+	 * to a minimal size, just big enough to fit descriptor table
+	 * and two rings (which makes it "alignment_size * 2")
+	 */
+	info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
+	while (1) {
+		size = PAGE_ALIGN(vring_size(info->num,
+				VIRTIO_MMIO_VRING_ALIGN));
+		/* Already smallest possible allocation? */
+		if (size <= VIRTIO_MMIO_VRING_ALIGN * 2) {
+			err = -ENOMEM;
+			goto error_alloc_pages;
+		}
+
+		info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
+		if (info->queue)
+			break;
+
+		info->num /= 2;
+	}
+
+	/* Activate the queue */
+	writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
+	writel(VIRTIO_MMIO_VRING_ALIGN,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
+	writel(virt_to_phys(info->queue) >> PAGE_SHIFT,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	/* Create the vring */
+	vq = vring_new_virtqueue(info->num, VIRTIO_MMIO_VRING_ALIGN,
+				 vdev, info->queue, vm_notify, callback, name);
+	if (!vq) {
+		err = -ENOMEM;
+		goto error_new_virtqueue;
+	}
+
+	vq->priv = info;
+	info->vq = vq;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_add(&info->node, &vm_dev->virtqueues);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	return vq;
+
+error_new_virtqueue:
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+	free_pages_exact(info->queue, size);
+error_alloc_pages:
+	kfree(info);
+error_kmalloc:
+error_available:
+	return ERR_PTR(err);
+}
+
+static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+		       struct virtqueue *vqs[],
+		       vq_callback_t *callbacks[],
+		       const char *names[])
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
+	int i, err;
+
+	err = request_irq(irq, vm_interrupt, IRQF_SHARED,
+			dev_name(&vdev->dev), vm_dev);
+	if (err)
+		return err;
+
+	for (i = 0; i < nvqs; ++i) {
+		vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]);
+		if (IS_ERR(vqs[i])) {
+			vm_del_vqs(vdev);
+			return PTR_ERR(vqs[i]);
+		}
+	}
+
+	return 0;
+}
+
+
+
+static struct virtio_config_ops virtio_mmio_config_ops = {
+	.get		= vm_get,
+	.set		= vm_set,
+	.get_status	= vm_get_status,
+	.set_status	= vm_set_status,
+	.reset		= vm_reset,
+	.find_vqs	= vm_find_vqs,
+	.del_vqs	= vm_del_vqs,
+	.get_features	= vm_get_features,
+	.finalize_features = vm_finalize_features,
+};
+
+
+
+/* Platform device */
+
+static int __devinit virtio_mmio_probe(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev;
+	struct resource *mem;
+	unsigned long magic;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start,
+			resource_size(mem), pdev->name))
+		return -EBUSY;
+
+	vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
+	if (!vm_dev)
+		return  -ENOMEM;
+
+	vm_dev->vdev.dev.parent = &pdev->dev;
+	vm_dev->vdev.config = &virtio_mmio_config_ops;
+	vm_dev->pdev = pdev;
+	INIT_LIST_HEAD(&vm_dev->virtqueues);
+	spin_lock_init(&vm_dev->lock);
+
+	vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (vm_dev->base == NULL)
+		return -EFAULT;
+
+	/* Check magic value */
+	magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
+	if (memcmp(&magic, "virt", 4) != 0) {
+		dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic);
+		return -ENODEV;
+	}
+
+	/* Check device version */
+	vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION);
+	if (vm_dev->version != 1) {
+		dev_err(&pdev->dev, "Version %ld not supported!\n",
+				vm_dev->version);
+		return -ENXIO;
+	}
+
+	vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
+	vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
+
+	writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+
+	platform_set_drvdata(pdev, vm_dev);
+
+	return register_virtio_device(&vm_dev->vdev);
+}
+
+static int __devexit virtio_mmio_remove(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev);
+
+	unregister_virtio_device(&vm_dev->vdev);
+
+	return 0;
+}
+
+
+
+/* Platform driver */
+
+static struct of_device_id virtio_mmio_match[] = {
+	{ .compatible = "virtio,mmio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, virtio_mmio_match);
+
+static struct platform_driver virtio_mmio_driver = {
+	.probe		= virtio_mmio_probe,
+	.remove		= __devexit_p(virtio_mmio_remove),
+	.driver		= {
+		.name	= "virtio-mmio",
+		.owner	= THIS_MODULE,
+		.of_match_table	= virtio_mmio_match,
+	},
+};
+
+static int __init virtio_mmio_init(void)
+{
+	return platform_driver_register(&virtio_mmio_driver);
+}
+
+static void __exit virtio_mmio_exit(void)
+{
+	platform_driver_unregister(&virtio_mmio_driver);
+}
+
+module_init(virtio_mmio_init);
+module_exit(virtio_mmio_exit);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Platform bus driver for memory mapped virtio devices");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/virtio_mmio.h b/include/linux/virtio_mmio.h
new file mode 100644
index 0000000..27c7ede
--- /dev/null
+++ b/include/linux/virtio_mmio.h
@@ -0,0 +1,111 @@
+/*
+ * Virtio platform device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_VIRTIO_MMIO_H
+#define _LINUX_VIRTIO_MMIO_H
+
+/*
+ * Control registers
+ */
+
+/* Magic value ("virt" string) - Read Only */
+#define VIRTIO_MMIO_MAGIC_VALUE		0x000
+
+/* Virtio device version - Read Only */
+#define VIRTIO_MMIO_VERSION		0x004
+
+/* Virtio device ID - Read Only */
+#define VIRTIO_MMIO_DEVICE_ID		0x008
+
+/* Virtio vendor ID - Read Only */
+#define VIRTIO_MMIO_VENDOR_ID		0x00c
+
+/* Bitmask of the features supported by the host
+ * (32 bits per set) - Read Only */
+#define VIRTIO_MMIO_HOST_FEATURES	0x010
+
+/* Host features set selector - Write Only */
+#define VIRTIO_MMIO_HOST_FEATURES_SEL	0x014
+
+/* Bitmask of features activated by the guest
+ * (32 bits per set) - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES	0x020
+
+/* Activated features set selector - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES_SET	0x024
+
+/* Guest's memory page size in bytes - Write Only */
+#define VIRTIO_MMIO_GUEST_PAGE_SIZE	0x028
+
+/* Queue selector - Write Only */
+#define VIRTIO_MMIO_QUEUE_SEL		0x030
+
+/* Maximum size of the currently selected queue - Read Only */
+#define VIRTIO_MMIO_QUEUE_NUM_MAX	0x034
+
+/* Queue size for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_NUM		0x038
+
+/* Used Ring alignment for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_ALIGN		0x03c
+
+/* Guest's PFN for the currently selected queue - Read Write */
+#define VIRTIO_MMIO_QUEUE_PFN		0x040
+
+/* Queue notifier - Write Only */
+#define VIRTIO_MMIO_QUEUE_NOTIFY	0x050
+
+/* Interrupt status - Read Only */
+#define VIRTIO_MMIO_INTERRUPT_STATUS	0x060
+
+/* Interrupt acknowledge - Write Only */
+#define VIRTIO_MMIO_INTERRUPT_ACK	0x064
+
+/* Device status register - Read Write */
+#define VIRTIO_MMIO_STATUS		0x070
+
+/* The config space is defined by each driver as
+ * the per-driver configuration space - Read Write */
+#define VIRTIO_MMIO_CONFIG		0x100
+
+
+
+/*
+ * Interrupt flags (re: interrupt status & acknowledge registers)
+ */
+
+#define VIRTIO_MMIO_INT_VRING		(1 << 0)
+#define VIRTIO_MMIO_INT_CONFIG		(1 << 1)
+
+#endif
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH v4] virtio: Add platform bus driver for memory mapped virtio device
From: Pawel Moll @ 2011-10-24 13:07 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, virtualization
  Cc: Anthony Liguori, Pawel Moll, Michael S.Tsirkin
In-Reply-To: <1319461560.3668.16.camel@hornet.cambridge.arm.com>

This patch, based on virtio PCI driver, adds support for memory
mapped (platform) virtio device. This should allow environments
like qemu to use virtio-based block & network devices even on
platforms without PCI support.

One can define and register a platform device which resources
will describe memory mapped control registers and "mailbox"
interrupt. Such device can be also instantiated using the Device
Tree node with compatible property equal "virtio,mmio".

Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: Michael S.Tsirkin <mst@redhat.com>
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---

Changes since v3:

* Dynamic config changes are handled now
* Interrupt acknowledge register moved to 0x064
* Added interrupt status register at 0x060
* Added interrupt flags (VIRTIO_MMIO_INT_VRING & VIRTIO_MMIO_INT_CONFIG)

Changes since v2:

* Fixed bug a bug in vm_find_vqs() error handling code (interrupt was
  freed twice)

Changes since v1:

* Added new QueueNumMax register at 0x034, shifting QueueNum,
  QueueAlign and QueuePFN by 4 bytes
* Queue page allocation strategy changed

 Documentation/devicetree/bindings/virtio/mmio.txt |   17 +
 drivers/virtio/Kconfig                            |   11 +
 drivers/virtio/Makefile                           |    1 +
 drivers/virtio/virtio_mmio.c                      |  479 +++++++++++++++++++++
 include/linux/virtio_mmio.h                       |  111 +++++
 5 files changed, 619 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/virtio/mmio.txt
 create mode 100644 drivers/virtio/virtio_mmio.c
 create mode 100644 include/linux/virtio_mmio.h

diff --git a/Documentation/devicetree/bindings/virtio/mmio.txt b/Documentation/devicetree/bindings/virtio/mmio.txt
new file mode 100644
index 0000000..5069c1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/virtio/mmio.txt
@@ -0,0 +1,17 @@
+* virtio memory mapped device
+
+See http://ozlabs.org/~rusty/virtio-spec/ for more details.
+
+Required properties:
+
+- compatible:	"virtio,mmio" compatibility string
+- reg:		control registers base address and size including configuration space
+- interrupts:	interrupt generated by the device
+
+Example:
+
+	virtio_block@3000 {
+		compatible = "virtio,mmio";
+		reg = <0x3000 0x100>;
+		interrupts = <41>;
+	}
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 57e493b..816ed08 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -35,4 +35,15 @@ config VIRTIO_BALLOON
 
 	 If unsure, say M.
 
+ config VIRTIO_MMIO
+ 	tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+ 	select VIRTIO
+ 	select VIRTIO_RING
+ 	---help---
+ 	 This drivers provides support for memory mapped virtio
+	 platform device driver.
+
+ 	 If unsure, say N.
+
 endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 6738c44..5a4c63c 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_VIRTIO) += virtio.o
 obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
+obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
 obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
new file mode 100644
index 0000000..acc5e43
--- /dev/null
+++ b/drivers/virtio/virtio_mmio.c
@@ -0,0 +1,479 @@
+/*
+ * Virtio memory mapped device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * This module allows virtio devices to be used over a virtual, memory mapped
+ * platform device.
+ *
+ * Registers layout (all 32-bit wide):
+ *
+ * offset d. name             description
+ * ------ -- ---------------- -----------------
+ *
+ * 0x000  R  MagicValue       Magic value "virt"
+ * 0x004  R  Version          Device version (current max. 1)
+ * 0x008  R  DeviceID         Virtio device ID
+ * 0x00c  R  VendorID         Virtio vendor ID
+ *
+ * 0x010  R  HostFeatures     Features supported by the host
+ * 0x014  W  HostFeaturesSel  Set of host features to access via HostFeatures
+ *
+ * 0x020  W  GuestFeatures    Features activated by the guest
+ * 0x024  W  GuestFeaturesSel Set of activated features to set via GuestFeatures
+ * 0x028  W  GuestPageSize    Size of guest's memory page in bytes
+ *
+ * 0x030  W  QueueSel         Queue selector
+ * 0x034  R  QueueNumMax      Maximum size of the currently selected queue
+ * 0x038  W  QueueNum         Queue size for the currently selected queue
+ * 0x03c  W  QueueAlign       Used Ring alignment for the current queue
+ * 0x040  RW QueuePFN         PFN for the currently selected queue
+ *
+ * 0x050  W  QueueNotify      Queue notifier
+ * 0x060  R  InterruptStatus  Interrupt status register
+ * 0x060  W  InterruptACK     Interrupt acknowledge register
+ * 0x070  RW Status           Device status register
+ *
+ * 0x100+ RW                  Device-specific configuration space
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_mmio.h>
+#include <linux/virtio_ring.h>
+
+
+
+/* The alignment to use between consumer and producer parts of vring.
+ * Currently hardcoded to the page size. */
+#define VIRTIO_MMIO_VRING_ALIGN		PAGE_SIZE
+
+
+
+#define to_virtio_mmio_device(_plat_dev) \
+	container_of(_plat_dev, struct virtio_mmio_device, vdev)
+
+struct virtio_mmio_device {
+	struct virtio_device vdev;
+	struct platform_device *pdev;
+
+	void __iomem *base;
+	unsigned long version;
+
+	/* a list of queues so we can dispatch IRQs */
+	spinlock_t lock;
+	struct list_head virtqueues;
+};
+
+struct virtio_mmio_vq_info {
+	/* the actual virtqueue */
+	struct virtqueue *vq;
+
+	/* the number of entries in the queue */
+	unsigned int num;
+
+	/* the index of the queue */
+	int queue_index;
+
+	/* the virtual address of the ring queue */
+	void *queue;
+
+	/* the list node for the virtqueues list */
+	struct list_head node;
+};
+
+
+
+/* Configuration interface */
+
+static u32 vm_get_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* TODO: Features > 32 bits */
+	writel(0, vm_dev->base + VIRTIO_MMIO_HOST_FEATURES_SEL);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_HOST_FEATURES);
+}
+
+static void vm_finalize_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	int i;
+
+	/* Give virtio_ring a chance to accept features. */
+	vring_transport_features(vdev);
+
+	for (i = 0; i < ARRAY_SIZE(vdev->features); i++) {
+		writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SET);
+		writel(vdev->features[i],
+				vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES);
+	}
+}
+
+static void vm_get(struct virtio_device *vdev, unsigned offset,
+		   void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static void vm_set(struct virtio_device *vdev, unsigned offset,
+		   const void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	const u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static u8 vm_get_status(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_STATUS) & 0xff;
+}
+
+static void vm_set_status(struct virtio_device *vdev, u8 status)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* We should never be setting status to 0. */
+	BUG_ON(status == 0);
+
+	writel(status, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+static void vm_reset(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* 0 status means a reset. */
+	writel(0, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+
+
+/* Transport interface */
+
+/* the notify function used when creating a virt queue */
+static void vm_notify(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+
+	/* We write the queue's selector into the notification register to
+	 * signal the other end */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+}
+
+/* Notify all virtqueues on an interrupt. */
+static irqreturn_t vm_interrupt(int irq, void *opaque)
+{
+	struct virtio_mmio_device *vm_dev = opaque;
+	struct virtio_mmio_vq_info *info;
+	struct virtio_driver *vdrv = container_of(vm_dev->vdev.dev.driver,
+			struct virtio_driver, driver);
+	unsigned long status;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+
+	/* Read and acknowledge interrupts */
+	status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS);
+	writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK);
+
+	if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)
+			&& vdrv && vdrv->config_changed) {
+		vdrv->config_changed(&vm_dev->vdev);
+		ret = IRQ_HANDLED;
+	}
+
+	if (likely(status & VIRTIO_MMIO_INT_VRING)) {
+		spin_lock_irqsave(&vm_dev->lock, flags);
+		list_for_each_entry(info, &vm_dev->virtqueues, node)
+			ret |= vring_interrupt(irq, info->vq);
+		spin_unlock_irqrestore(&vm_dev->lock, flags);
+	}
+
+	return ret;
+}
+
+
+
+static void vm_del_vq(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+	unsigned long flags, size;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_del(&info->node);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	vring_del_virtqueue(vq);
+
+	/* Select and deactivate the queue */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN));
+	free_pages_exact(info->queue, size);
+	kfree(info);
+}
+
+static void vm_del_vqs(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtqueue *vq, *n;
+
+	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+		vm_del_vq(vq);
+
+	free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev);
+}
+
+
+
+static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
+				  void (*callback)(struct virtqueue *vq),
+				  const char *name)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtio_mmio_vq_info *info;
+	struct virtqueue *vq;
+	unsigned long flags, size;
+	int err;
+
+	/* Select the queue we're interested in */
+	writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+
+	/* Queue shouldn't already be set up. */
+	if (readl(vm_dev->base + VIRTIO_MMIO_QUEUE_PFN)) {
+		err = -ENOENT;
+		goto error_available;
+	}
+
+	/* Allocate and fill out our active queue description */
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		err = -ENOMEM;
+		goto error_kmalloc;
+	}
+	info->queue_index = index;
+
+	/* Allocate pages for the queue - start with a queue as big as
+	 * possible (limited by maximum size allowed by device), drop down
+	 * to a minimal size, just big enough to fit descriptor table
+	 * and two rings (which makes it "alignment_size * 2")
+	 */
+	info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
+	while (1) {
+		size = PAGE_ALIGN(vring_size(info->num,
+				VIRTIO_MMIO_VRING_ALIGN));
+		/* Already smallest possible allocation? */
+		if (size <= VIRTIO_MMIO_VRING_ALIGN * 2) {
+			err = -ENOMEM;
+			goto error_alloc_pages;
+		}
+
+		info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
+		if (info->queue)
+			break;
+
+		info->num /= 2;
+	}
+
+	/* Activate the queue */
+	writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
+	writel(VIRTIO_MMIO_VRING_ALIGN,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
+	writel(virt_to_phys(info->queue) >> PAGE_SHIFT,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	/* Create the vring */
+	vq = vring_new_virtqueue(info->num, VIRTIO_MMIO_VRING_ALIGN,
+				 vdev, info->queue, vm_notify, callback, name);
+	if (!vq) {
+		err = -ENOMEM;
+		goto error_new_virtqueue;
+	}
+
+	vq->priv = info;
+	info->vq = vq;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_add(&info->node, &vm_dev->virtqueues);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	return vq;
+
+error_new_virtqueue:
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+	free_pages_exact(info->queue, size);
+error_alloc_pages:
+	kfree(info);
+error_kmalloc:
+error_available:
+	return ERR_PTR(err);
+}
+
+static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+		       struct virtqueue *vqs[],
+		       vq_callback_t *callbacks[],
+		       const char *names[])
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
+	int i, err;
+
+	err = request_irq(irq, vm_interrupt, IRQF_SHARED,
+			dev_name(&vdev->dev), vm_dev);
+	if (err)
+		return err;
+
+	for (i = 0; i < nvqs; ++i) {
+		vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]);
+		if (IS_ERR(vqs[i])) {
+			vm_del_vqs(vdev);
+			return PTR_ERR(vqs[i]);
+		}
+	}
+
+	return 0;
+}
+
+
+
+static struct virtio_config_ops virtio_mmio_config_ops = {
+	.get		= vm_get,
+	.set		= vm_set,
+	.get_status	= vm_get_status,
+	.set_status	= vm_set_status,
+	.reset		= vm_reset,
+	.find_vqs	= vm_find_vqs,
+	.del_vqs	= vm_del_vqs,
+	.get_features	= vm_get_features,
+	.finalize_features = vm_finalize_features,
+};
+
+
+
+/* Platform device */
+
+static int __devinit virtio_mmio_probe(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev;
+	struct resource *mem;
+	unsigned long magic;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start,
+			resource_size(mem), pdev->name))
+		return -EBUSY;
+
+	vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
+	if (!vm_dev)
+		return  -ENOMEM;
+
+	vm_dev->vdev.dev.parent = &pdev->dev;
+	vm_dev->vdev.config = &virtio_mmio_config_ops;
+	vm_dev->pdev = pdev;
+	INIT_LIST_HEAD(&vm_dev->virtqueues);
+	spin_lock_init(&vm_dev->lock);
+
+	vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (vm_dev->base == NULL)
+		return -EFAULT;
+
+	/* Check magic value */
+	magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
+	if (memcmp(&magic, "virt", 4) != 0) {
+		dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic);
+		return -ENODEV;
+	}
+
+	/* Check device version */
+	vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION);
+	if (vm_dev->version != 1) {
+		dev_err(&pdev->dev, "Version %ld not supported!\n",
+				vm_dev->version);
+		return -ENXIO;
+	}
+
+	vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
+	vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
+
+	writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+
+	platform_set_drvdata(pdev, vm_dev);
+
+	return register_virtio_device(&vm_dev->vdev);
+}
+
+static int __devexit virtio_mmio_remove(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev);
+
+	unregister_virtio_device(&vm_dev->vdev);
+
+	return 0;
+}
+
+
+
+/* Platform driver */
+
+static struct of_device_id virtio_mmio_match[] = {
+	{ .compatible = "virtio,mmio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, virtio_mmio_match);
+
+static struct platform_driver virtio_mmio_driver = {
+	.probe		= virtio_mmio_probe,
+	.remove		= __devexit_p(virtio_mmio_remove),
+	.driver		= {
+		.name	= "virtio-mmio",
+		.owner	= THIS_MODULE,
+		.of_match_table	= virtio_mmio_match,
+	},
+};
+
+static int __init virtio_mmio_init(void)
+{
+	return platform_driver_register(&virtio_mmio_driver);
+}
+
+static void __exit virtio_mmio_exit(void)
+{
+	platform_driver_unregister(&virtio_mmio_driver);
+}
+
+module_init(virtio_mmio_init);
+module_exit(virtio_mmio_exit);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Platform bus driver for memory mapped virtio devices");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/virtio_mmio.h b/include/linux/virtio_mmio.h
new file mode 100644
index 0000000..27c7ede
--- /dev/null
+++ b/include/linux/virtio_mmio.h
@@ -0,0 +1,111 @@
+/*
+ * Virtio platform device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_VIRTIO_MMIO_H
+#define _LINUX_VIRTIO_MMIO_H
+
+/*
+ * Control registers
+ */
+
+/* Magic value ("virt" string) - Read Only */
+#define VIRTIO_MMIO_MAGIC_VALUE		0x000
+
+/* Virtio device version - Read Only */
+#define VIRTIO_MMIO_VERSION		0x004
+
+/* Virtio device ID - Read Only */
+#define VIRTIO_MMIO_DEVICE_ID		0x008
+
+/* Virtio vendor ID - Read Only */
+#define VIRTIO_MMIO_VENDOR_ID		0x00c
+
+/* Bitmask of the features supported by the host
+ * (32 bits per set) - Read Only */
+#define VIRTIO_MMIO_HOST_FEATURES	0x010
+
+/* Host features set selector - Write Only */
+#define VIRTIO_MMIO_HOST_FEATURES_SEL	0x014
+
+/* Bitmask of features activated by the guest
+ * (32 bits per set) - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES	0x020
+
+/* Activated features set selector - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES_SET	0x024
+
+/* Guest's memory page size in bytes - Write Only */
+#define VIRTIO_MMIO_GUEST_PAGE_SIZE	0x028
+
+/* Queue selector - Write Only */
+#define VIRTIO_MMIO_QUEUE_SEL		0x030
+
+/* Maximum size of the currently selected queue - Read Only */
+#define VIRTIO_MMIO_QUEUE_NUM_MAX	0x034
+
+/* Queue size for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_NUM		0x038
+
+/* Used Ring alignment for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_ALIGN		0x03c
+
+/* Guest's PFN for the currently selected queue - Read Write */
+#define VIRTIO_MMIO_QUEUE_PFN		0x040
+
+/* Queue notifier - Write Only */
+#define VIRTIO_MMIO_QUEUE_NOTIFY	0x050
+
+/* Interrupt status - Read Only */
+#define VIRTIO_MMIO_INTERRUPT_STATUS	0x060
+
+/* Interrupt acknowledge - Write Only */
+#define VIRTIO_MMIO_INTERRUPT_ACK	0x064
+
+/* Device status register - Read Write */
+#define VIRTIO_MMIO_STATUS		0x070
+
+/* The config space is defined by each driver as
+ * the per-driver configuration space - Read Write */
+#define VIRTIO_MMIO_CONFIG		0x100
+
+
+
+/*
+ * Interrupt flags (re: interrupt status & acknowledge registers)
+ */
+
+#define VIRTIO_MMIO_INT_VRING		(1 << 0)
+#define VIRTIO_MMIO_INT_CONFIG		(1 << 1)
+
+#endif
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH v2 3/5] regulator: helper routine to extract regulator_init_data
From: Mark Brown @ 2011-10-24 13:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111024130429.GD1755@S2100-06.ap.freescale.net>

On Mon, Oct 24, 2011 at 09:04:31PM +0800, Shawn Guo wrote:

> If we can attach the device_node of 'regulators' node to dev->of_node
> when calling regulator_register(regulator_desc, dev, ...) from
> regulator driver, the regulator core will be able to find all nodes under
> 'regulators' using for_each_child_of_node(dev->of_node, child).

Please provide concrete examples of the bindings you're talking about,
the really important thing here is how sane the bindings look and I've
really got no idea what any of what you're talking about will look like
or if they make sense.

> hesitate to hack this into mfd_add_devices(), so I would like to add
> compatible string "fsl,mc13892-regulators" to node 'regulators' and
> find the node using of_find_compatible_node(dev->parent, NULL,
> "fsl,mc13892-regulators").

It's not immediately obvious to me that having a binding for the
regulators separately makes sense, it's not a usefully distinct device.

^ permalink raw reply

* Re: [PATCH v2 3/5] regulator: helper routine to extract regulator_init_data
From: Mark Brown @ 2011-10-24 13:06 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Grant Likely, Rajendra Nayak, patches, tony, devicetree-discuss,
	linux-kernel, linux-omap, lrg, linux-arm-kernel
In-Reply-To: <20111024130429.GD1755@S2100-06.ap.freescale.net>

On Mon, Oct 24, 2011 at 09:04:31PM +0800, Shawn Guo wrote:

> If we can attach the device_node of 'regulators' node to dev->of_node
> when calling regulator_register(regulator_desc, dev, ...) from
> regulator driver, the regulator core will be able to find all nodes under
> 'regulators' using for_each_child_of_node(dev->of_node, child).

Please provide concrete examples of the bindings you're talking about,
the really important thing here is how sane the bindings look and I've
really got no idea what any of what you're talking about will look like
or if they make sense.

> hesitate to hack this into mfd_add_devices(), so I would like to add
> compatible string "fsl,mc13892-regulators" to node 'regulators' and
> find the node using of_find_compatible_node(dev->parent, NULL,
> "fsl,mc13892-regulators").

It's not immediately obvious to me that having a binding for the
regulators separately makes sense, it's not a usefully distinct device.

^ permalink raw reply

* [PATCH] Shrink thread_info a bit
From: Baruch Siach @ 2011-10-24 13:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111024124818.GA17693@n2100.arm.linux.org.uk>

Hi Russell,

On Mon, Oct 24, 2011 at 01:48:18PM +0100, Russell King - ARM Linux wrote:
> Thread info comes in on Versatile Express at 752 bytes in size, which
> is quite large.  Of this, the crunch state is 184 bytes, which is only
> used on Cirrus Logic devices.
> 
> It is wasteful to have this in every kernel when Cirrus Logic CPUs
> are not that widely used.  So make this conditional.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  arch/arm/include/asm/thread_info.h |    2 ++
>  arch/arm/kernel/asm-offsets.c      |    2 ++
>  2 files changed, 4 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
> index 7b5cc8d..a030be7 100644
> --- a/arch/arm/include/asm/thread_info.h
> +++ b/arch/arm/include/asm/thread_info.h
> @@ -59,7 +59,9 @@ struct thread_info {
>  	__u32			syscall;	/* syscall number */
>  	__u8			used_cp[16];	/* thread used copro */
>  	unsigned long		tp_value;
> +#ifdef CONFIG_CRUNCH
>  	struct crunch_state	crunchstate;
> +#endif
>  	union fp_state		fpstate __attribute__((aligned(8)));
>  	union vfp_state		vfpstate;
>  #ifdef CONFIG_ARM_THUMBEE

Where is the arch/arm/kernel/asm-offsets.c hunk?

baruch

-- 
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -

^ permalink raw reply

* Re: [Qemu-devel] KVM call agenda for October 25
From: Andreas Färber @ 2011-10-24 13:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, kvm, Paolo Bonzini
In-Reply-To: <CAFEAcA_5-ZsJZX3fYDq8bLy8MRPuqqO5CCz=Q7pZurr_5O6ghg@mail.gmail.com>

Am 24.10.2011 14:02, schrieb Peter Maydell:
> On 24 October 2011 12:35, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> On 10/24/2011 01:04 PM, Juan Quintela wrote:
>>> Please send in any agenda items you are interested in covering.
>>
>> - What's left to merge for 1.0.

> I also think that it's somewhat unfortunate that we now will
> compile on ARM hosts so that we always abort on startup (due
> to the reliance on a working makecontext()) but I'm not really
> sure how to deal with that one.

FWIW we're also not working / not building on Darwin ppc+Intel, which is
related to a) softfloat integer types, b) GThread initialization, c)
unknown issues. Bisecting did not work well and I am lacking time and
ideas to investigate and fix this. For softfloat there are several
solutions around, in need of a decision.

Nice to merge would be the Cocoa sheet issue, once verified.

Andreas

^ permalink raw reply

* Re: [PATCH v3] virtio: Add platform bus driver for memory mapped virtio device
From: Pawel Moll @ 2011-10-24 13:06 UTC (permalink / raw)
  To: Rusty Russell
  Cc: linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	virtualization@lists.linux-foundation.org, Anthony Liguori,
	Michael S.Tsirkin
In-Reply-To: <87wrbv15lp.fsf@rustcorp.com.au>

On Mon, 2011-10-24 at 03:33 +0100, Rusty Russell wrote:
> No, that's it I think.  Please send a diff for the documentation, since
> I'm updating the LyX master and I've already applied your previous
> version.

Here it goes (below). Also do you think you would be able to merge the
driver (corresponding v4 patch follows) in the 3.2 merge window that
seems to have just opened? ;-)

Cheers!

Pawel

--- virtio-mmio.orig	2011-10-24 11:17:08.263907000 +0100
+++ virtio-mmio.tex	2011-10-24 13:58:29.752757000 +0100
@@ -59,9 +59,18 @@
 \item 0x050 | W | QueueNotify \\
 Queue notifier.\\
 Writing a queue index to this register notifies the Host that there are new buffers to process in the queue.
-\item 0x060 | W | InterruptACK \\
+\item 0x060 | R | InterruptStatus \\
+Interrupt status. \\
+Reading from this register returns a bit mask of interrupts asserted by the device. An interrupt is asserted if the corresponding bit is set, ie. equals one (1). \\
+\begin{itemize}
+\item Bit 0 | Used Ring update \\
+This interrupt is asserted when the Host has updated the Used Ring in at least one of the active virtual queues.
+\item Bit 1 | Configuration change \\
+This interrupt is asserted when configuration of the device has changed.
+\end{itemize}
+\item 0x064 | W | InterruptACK \\
 Interrupt acknowledge. \\
-Writing to this register notifies the Host that the Guest finished receiving used buffers from the device and therefore serviced an asserted interrupt. Values written to this register are currently not used, but for future extensions it must be set to one (0x1).
+Writing to this register notifies the Host that the Guest finished handling interrupts. Every bit of the value clears corresponding bit of the InterruptStatus register. \\
 \item 0x070 | RW | Status \\
 Device status. \\
 Reading from this register returns the current device status flags. \\
@@ -100,8 +109,7 @@
 The memory mapped virtio device behaves in the same way as described in p. 2.4 ``Device Operation'', with the following exceptions:
 \begin{enumerate}
 \item The device is notified about new buffers available in a queue by writing the queue index to register QueueNum instead of the virtio header in PCI I/O space (p. 2.4.1.4 ``Notifying The Device'').
-\item As the memory mapped virtio device is using single, dedicated interrupt signal, its handling is much simpler than in the PCI (MSI-X) case (p.  2.4.2 ``Receiving Used Buffer From The Device''). Therefore all the Guest interrupt handler should do after receiving used buffers is acknowledging the interrupt by writing a value to the InterruptACK register. Currently this value does not carry any meaning, but for future extensions it must be set to one (0x1).
-\item The dynamic configuration changes, as described in p. 2.4.3 ``Dealing With Configuration Changes'' are not permitted.
+\item The memory mapped virtio device is using single, dedicated interrupt signal. After receiving an interrupt, the driver must read the InterruptStatus register to check what caused the interrupt (see the register description). After the interrupt is handled, the driver must acknowledge it by writing a bit mask corresponding to the serviced interrupt to the InterruptACK register.
 \end{enumerate}
 
 \end{document}





^ permalink raw reply

* Re: KVM call agenda for October 25
From: Andreas Färber @ 2011-10-24 13:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, kvm, Paolo Bonzini
In-Reply-To: <CAFEAcA_5-ZsJZX3fYDq8bLy8MRPuqqO5CCz=Q7pZurr_5O6ghg@mail.gmail.com>

Am 24.10.2011 14:02, schrieb Peter Maydell:
> On 24 October 2011 12:35, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> On 10/24/2011 01:04 PM, Juan Quintela wrote:
>>> Please send in any agenda items you are interested in covering.
>>
>> - What's left to merge for 1.0.

> I also think that it's somewhat unfortunate that we now will
> compile on ARM hosts so that we always abort on startup (due
> to the reliance on a working makecontext()) but I'm not really
> sure how to deal with that one.

FWIW we're also not working / not building on Darwin ppc+Intel, which is
related to a) softfloat integer types, b) GThread initialization, c)
unknown issues. Bisecting did not work well and I am lacking time and
ideas to investigate and fix this. For softfloat there are several
solutions around, in need of a decision.

Nice to merge would be the Cocoa sheet issue, once verified.

Andreas

^ permalink raw reply

* [PATCH v3] virtio: Add platform bus driver for memory mapped virtio device
From: Pawel Moll @ 2011-10-24 13:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87wrbv15lp.fsf@rustcorp.com.au>

On Mon, 2011-10-24 at 03:33 +0100, Rusty Russell wrote:
> No, that's it I think.  Please send a diff for the documentation, since
> I'm updating the LyX master and I've already applied your previous
> version.

Here it goes (below). Also do you think you would be able to merge the
driver (corresponding v4 patch follows) in the 3.2 merge window that
seems to have just opened? ;-)

Cheers!

Pawel

--- virtio-mmio.orig	2011-10-24 11:17:08.263907000 +0100
+++ virtio-mmio.tex	2011-10-24 13:58:29.752757000 +0100
@@ -59,9 +59,18 @@
 \item 0x050 | W | QueueNotify \\
 Queue notifier.\\
 Writing a queue index to this register notifies the Host that there are new buffers to process in the queue.
-\item 0x060 | W | InterruptACK \\
+\item 0x060 | R | InterruptStatus \\
+Interrupt status. \\
+Reading from this register returns a bit mask of interrupts asserted by the device. An interrupt is asserted if the corresponding bit is set, ie. equals one (1). \\
+\begin{itemize}
+\item Bit 0 | Used Ring update \\
+This interrupt is asserted when the Host has updated the Used Ring in at least one of the active virtual queues.
+\item Bit 1 | Configuration change \\
+This interrupt is asserted when configuration of the device has changed.
+\end{itemize}
+\item 0x064 | W | InterruptACK \\
 Interrupt acknowledge. \\
-Writing to this register notifies the Host that the Guest finished receiving used buffers from the device and therefore serviced an asserted interrupt. Values written to this register are currently not used, but for future extensions it must be set to one (0x1).
+Writing to this register notifies the Host that the Guest finished handling interrupts. Every bit of the value clears corresponding bit of the InterruptStatus register. \\
 \item 0x070 | RW | Status \\
 Device status. \\
 Reading from this register returns the current device status flags. \\
@@ -100,8 +109,7 @@
 The memory mapped virtio device behaves in the same way as described in p. 2.4 ``Device Operation'', with the following exceptions:
 \begin{enumerate}
 \item The device is notified about new buffers available in a queue by writing the queue index to register QueueNum instead of the virtio header in PCI I/O space (p. 2.4.1.4 ``Notifying The Device'').
-\item As the memory mapped virtio device is using single, dedicated interrupt signal, its handling is much simpler than in the PCI (MSI-X) case (p.  2.4.2 ``Receiving Used Buffer From The Device''). Therefore all the Guest interrupt handler should do after receiving used buffers is acknowledging the interrupt by writing a value to the InterruptACK register. Currently this value does not carry any meaning, but for future extensions it must be set to one (0x1).
-\item The dynamic configuration changes, as described in p. 2.4.3 ``Dealing With Configuration Changes'' are not permitted.
+\item The memory mapped virtio device is using single, dedicated interrupt signal. After receiving an interrupt, the driver must read the InterruptStatus register to check what caused the interrupt (see the register description). After the interrupt is handled, the driver must acknowledge it by writing a bit mask corresponding to the serviced interrupt to the InterruptACK register.
 \end{enumerate}
 
 \end{document}

^ permalink raw reply

* Re: [PATCH v3] virtio: Add platform bus driver for memory mapped virtio device
From: Pawel Moll @ 2011-10-24 13:06 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Anthony Liguori, Michael S.Tsirkin, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	virtualization@lists.linux-foundation.org
In-Reply-To: <87wrbv15lp.fsf@rustcorp.com.au>

On Mon, 2011-10-24 at 03:33 +0100, Rusty Russell wrote:
> No, that's it I think.  Please send a diff for the documentation, since
> I'm updating the LyX master and I've already applied your previous
> version.

Here it goes (below). Also do you think you would be able to merge the
driver (corresponding v4 patch follows) in the 3.2 merge window that
seems to have just opened? ;-)

Cheers!

Pawel

--- virtio-mmio.orig	2011-10-24 11:17:08.263907000 +0100
+++ virtio-mmio.tex	2011-10-24 13:58:29.752757000 +0100
@@ -59,9 +59,18 @@
 \item 0x050 | W | QueueNotify \\
 Queue notifier.\\
 Writing a queue index to this register notifies the Host that there are new buffers to process in the queue.
-\item 0x060 | W | InterruptACK \\
+\item 0x060 | R | InterruptStatus \\
+Interrupt status. \\
+Reading from this register returns a bit mask of interrupts asserted by the device. An interrupt is asserted if the corresponding bit is set, ie. equals one (1). \\
+\begin{itemize}
+\item Bit 0 | Used Ring update \\
+This interrupt is asserted when the Host has updated the Used Ring in at least one of the active virtual queues.
+\item Bit 1 | Configuration change \\
+This interrupt is asserted when configuration of the device has changed.
+\end{itemize}
+\item 0x064 | W | InterruptACK \\
 Interrupt acknowledge. \\
-Writing to this register notifies the Host that the Guest finished receiving used buffers from the device and therefore serviced an asserted interrupt. Values written to this register are currently not used, but for future extensions it must be set to one (0x1).
+Writing to this register notifies the Host that the Guest finished handling interrupts. Every bit of the value clears corresponding bit of the InterruptStatus register. \\
 \item 0x070 | RW | Status \\
 Device status. \\
 Reading from this register returns the current device status flags. \\
@@ -100,8 +109,7 @@
 The memory mapped virtio device behaves in the same way as described in p. 2.4 ``Device Operation'', with the following exceptions:
 \begin{enumerate}
 \item The device is notified about new buffers available in a queue by writing the queue index to register QueueNum instead of the virtio header in PCI I/O space (p. 2.4.1.4 ``Notifying The Device'').
-\item As the memory mapped virtio device is using single, dedicated interrupt signal, its handling is much simpler than in the PCI (MSI-X) case (p.  2.4.2 ``Receiving Used Buffer From The Device''). Therefore all the Guest interrupt handler should do after receiving used buffers is acknowledging the interrupt by writing a value to the InterruptACK register. Currently this value does not carry any meaning, but for future extensions it must be set to one (0x1).
-\item The dynamic configuration changes, as described in p. 2.4.3 ``Dealing With Configuration Changes'' are not permitted.
+\item The memory mapped virtio device is using single, dedicated interrupt signal. After receiving an interrupt, the driver must read the InterruptStatus register to check what caused the interrupt (see the register description). After the interrupt is handled, the driver must acknowledge it by writing a bit mask corresponding to the serviced interrupt to the InterruptACK register.
 \end{enumerate}
 
 \end{document}

^ permalink raw reply

* [PATCH] iio:staging: Add documentation for IIO_EVENT_CODE
From: Lars-Peter Clausen @ 2011-10-24 13:05 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Michael Hennerich, linux-iio, device-drivers-devel, drivers,
	Lars-Peter Clausen

Document the different parameters of the IIO_EVENT_CODE macro and friends.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>

---
I'm adding this to get a clear definition of what each field is for, because
currently there are somewhat contradicting usages of this macro. So I'm not
quite sure if this is the correct documentation.

---
 drivers/staging/iio/events.h |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h
index 389c781..520a20e 100644
--- a/drivers/staging/iio/events.h
+++ b/drivers/staging/iio/events.h
@@ -40,6 +40,18 @@ enum iio_event_direction {
 	IIO_EV_DIR_FALLING,
 };
 
+/**
+ * IIO_EVENT_CODE() - create event identifier
+ * @chan_type:	Type of the channel. Should be one of enum iio_chan_type.
+ * @diff:	Whether the event is for an differential channel or not.
+ * @modifier:	Modifier for the channel. Should be one of enum iio_modifier.
+ * @direction:	Direction of the event. Should be one of enum iio_event_direction.
+ * @type:	Type of the event. Should be one enum iio_event_type.
+ * @chan:	Channel number for non-differential channels.
+ * @chan1:	First channel number for differential channels.
+ * @chan2:	Second channel number for differential channels.
+ */
+
 #define IIO_EVENT_CODE(chan_type, diff, modifier, direction,		\
 		       type, chan, chan1, chan2)			\
 	(((u64)type << 56) | ((u64)diff << 55) |			\
@@ -51,10 +63,27 @@ enum iio_event_direction {
 #define IIO_EV_BIT(type, direction)			\
 	(1 << (type*IIO_EV_DIR_MAX + direction))
 
+/**
+ * IIO_MOD_EVENT_CODE() - create event identifier for modified channels
+ * @channelclass: Type of the channel. Should be one of enum iio_chan_type.
+ * @number:	Channel number for non-differential channels.
+ * @modifier:	Modifier for the channel. Should be one of enum iio_modifier.
+ * @type:	Type of the event. Should be one enum iio_event_type.
+ * @direction:	Direction of the event. Should be one of enum iio_event_direction.
+ */
+
 #define IIO_MOD_EVENT_CODE(channelclass, number, modifier,		\
 			   type, direction)				\
 	IIO_EVENT_CODE(channelclass, 0, modifier, direction, type, number, 0, 0)
 
+/**
+ * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels
+ * @channelclass: Type of the channel. Should be one of enum iio_chan_type.
+ * @number:	Channel number for non-differential channels.
+ * @type:	Type of the event. Should be one enum iio_event_type.
+ * @direction:	Direction of the event. Should be one of enum iio_event_direction.
+ */
+
 #define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction)	\
 	IIO_EVENT_CODE(channelclass, 0, 0, direction, type, number, 0, 0)
 
-- 
1.7.7



^ permalink raw reply related

* [PATCH v2 3/5] regulator: helper routine to extract regulator_init_data
From: Shawn Guo @ 2011-10-24 13:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111024092411.GE8708@ponder.secretlab.ca>

On Mon, Oct 24, 2011 at 11:24:11AM +0200, Grant Likely wrote:
> On Fri, Oct 21, 2011 at 04:23:12PM +0800, Shawn Guo wrote:
> > On Thu, Oct 20, 2011 at 05:39:32PM +0530, Rajendra Nayak wrote:
> > > On Thursday 20 October 2011 11:44 AM, Shawn Guo wrote:
> > > >On Thu, Oct 20, 2011 at 10:48:58AM +0530, Rajendra Nayak wrote:
> > > >>>Let's look at mc13892-regulator driver.  There are 23 regulators defined
> > > >>>in array mc13892_regulators.  Needless to say, there is a dev behind
> > > >>>mc13892-regulator driver.  And when getting probed, this driver will
> > > >>>call regulator_register() to register those 23 regulators individually.
> > > >>>That said, for non-dt world, we have 1 + 23 'dev' with that 1 as the
> > > >>>parent of all other 23 'dev' (wrapped by regulator_dev).  But with the
> > > >>>current DT implementation, we will have at least 1 + 23 * 2 'dev'.
> > > >>>These extra 23 'dev' is totally new with DT.
> > > >>>
> > > >>
> > > >>but thats only because the mc13892-regulator driver is implemeted in
> > > >>such a way that all the regulators on the platform are bundled in as
> > > >>*one* device.
> > > >
> > > >I did not look into too many regulator drivers, but I expect this is
> > > >way that most regulator drivers are implemented in.  Having
> > > >mc13892-regulator being probed 23 times to register these 23 regulators
> > > >just makes less sense to me.
> > > >
> > > >>It would again depend on how you would pass these from
> > > >>the DT, if you indeed stick to the same way of bundling all regulators
> > > >>as one device from DT, the mc13892-regulator probe would just get called
> > > >>once and there would be one device associated, no?
> > > >>
> > > >Yes, I indeed would stick to the same way of bundling the registration
> > > >of all regulators with mc13892-regulator being probed once.  The problem
> > > >I have with the current regulator core DT implementation is that it
> > > >assumes the device_node of rdev->dev (dev wrapped in regulator_dev) is
> > > >being attached to rdev->dev.parent rather than itself.  Back to
> > > >mc13892-regulator example, that said, it requires the dev of
> > > >mc13892-regulator have the device_node of individual regulator attached
> > > >to.  IOW, the current implementation forces mc13892-regulator to be
> > > >probed 23 times to register those 23 regulators.  This is wrong to me.
> > > 
> > > I think I now understand to some extent the problem that you seem to be
> > > reporting. It is mainly with drivers which bundle all regulators and
> > > pass them as one device and would want to do so with DT too.
> > > 
> > > however I am still not clear on how what you seem to suggest would
> > > solve this problem. Note that not all drivers do it this way, and
> > > there are drivers where each regulator is considered as one device
> > > and I suspect they would remain that way with DT too. And hence we
> > > need to support both.
> > > 
> > > Do you have any RFC patch/code which could explain better what you are
> > > suggesting we do here?
> > > >
> > Here is what I changed based on your patches.  It only changes
> > drivers/regulator/core.c.
> > 
> > ---8<-------
> > diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> > index 9a5ebbe..8fe132d 100644
> > --- a/drivers/regulator/core.c
> > +++ b/drivers/regulator/core.c
> > @@ -1211,7 +1211,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
> >                 node = of_get_regulator(dev, id);
> >                 if (node)
> >                         list_for_each_entry(rdev, &regulator_list, list)
> > -                               if (node == rdev->dev.parent->of_node)
> > +                               if (node == rdev->dev.of_node)
> >                                         goto found;
> >         }
> >         list_for_each_entry(map, &regulator_map_list, list) {
> > @@ -2642,9 +2642,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >             regulator_desc->type != REGULATOR_CURRENT)
> >                 return ERR_PTR(-EINVAL);
> > 
> > -       if (!init_data)
> > -               return ERR_PTR(-EINVAL);
> > -
> >         /* Only one of each should be implemented */
> >         WARN_ON(regulator_desc->ops->get_voltage &&
> >                 regulator_desc->ops->get_voltage_sel);
> > @@ -2675,12 +2672,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >         INIT_LIST_HEAD(&rdev->list);
> >         BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
> > 
> > -       /* preform any regulator specific init */
> > -       if (init_data->regulator_init) {
> > -               ret = init_data->regulator_init(rdev->reg_data);
> > -               if (ret < 0)
> > -                       goto clean;
> > -       }
> > +       /* find device_node and attach it */
> > +       rdev->dev.of_node = of_find_node_by_name(NULL, regulator_desc->name);
> > 
> >         /* register with sysfs */
> >         rdev->dev.class = &regulator_class;
> > @@ -2693,6 +2686,20 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >                 goto clean;
> >         }
> > 
> > +       if (!init_data) {
> > +               /* try to get init_data from device tree */
> > +               init_data = of_get_regulator_init_data(&rdev->dev);
> > +               if (!init_data)
> > +                       return ERR_PTR(-EINVAL);
> > +       }
> > +
> > +       /* preform any regulator specific init */
> > +       if (init_data->regulator_init) {
> > +               ret = init_data->regulator_init(rdev->reg_data);
> > +               if (ret < 0)
> > +                       goto clean;
> > +       }
> > +
> >         dev_set_drvdata(&rdev->dev, rdev);
> > 
> >         /* set regulator constraints */
> > @@ -2719,7 +2726,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >                         node = of_get_regulator(dev, supply);
> >                         if (node)
> >                                 list_for_each_entry(r, &regulator_list, list)
> > -                                       if (node == r->dev.parent->of_node)
> > +                                       if (node == r->dev.of_node)
> >                                                 goto found;
> >                 }
> > 
> > ------->8---
> > 
> > And my dts file looks like something below.
> > 
> > 	ecspi at 70010000 { /* ECSPI1 */
> > 		fsl,spi-num-chipselects = <2>;
> > 		cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
> > 			   <&gpio3 25 0>; /* GPIO4_25 */
> > 		status = "okay";
> > 
> > 		pmic: mc13892 at 0 {
> > 			#address-cells = <1>;
> > 			#size-cells = <0>;
> > 			compatible = "fsl,mc13892";
> > 			spi-max-frequency = <6000000>;
> > 			reg = <0>;
> > 			mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */
> > 
> > 			regulators {
> > 				sw1reg: mc13892_sw1 {
> > 					regulator-min-uV = <600000>;
> > 					regulator-max-uV = <1375000>;
> > 					regulator-change-voltage;
> > 					regulator-boot-on;
> > 					regulator-always-on;
> > 				};
> > 
> > 				sw2reg: mc13892_sw2 {
> > 					regulator-min-uV = <900000>;
> > 					regulator-max-uV = <1850000>;
> > 					regulator-change-voltage;
> > 					regulator-boot-on;
> > 					regulator-always-on;
> > 				};
> > 
> > 				......
> > 			};
> 
> To follow up from my earlier comment, this .dts structure looks fine
> and reasonable to me, and it would also be fine for the mc13892 driver
> to use for_each_child_of_node() to find all the children of the
> regulators node.  Even finding the 'regulators' node by name from the
> mc13892 driver is perfectly fine provided for_each_child_of_node is
> used to find it.  All of this is okay because it is under the umbrella
> of the "fsl,mc13892" binding.
> 
For mc13892 regulator example, there are 3 levels 'struct dev'.

1. drivers/mfd/mc13xxx-core.c
   The "fsl,mc13892" binding is used in this mfd driver to get
   mc13xxx-core device probed.  And this mfd driver will in turn
   call mfd_add_devices() to add the second level device below.

2. drivers/regulator/mc13892-regulator.c
   As this device is created by mfd_add_devices() above, there is no
   device_node attached to its of_node, though we would hope that node
   'regulators' is attached there.  And the driver will call
   regulator_register() to have each regulator device created and
   registered in regulator core below.

3. drivers/regulator/core.c
   regulator_register() called above will create device (rdev->dev)
   for each regulator.

I am thinking about hiding the device_node discovering for each
regulator from the second level (regulator driver) and make it
internal to the third level (regulator core), as it seems to me
that regulator driver does not need to necessarily know about this.

If we can attach the device_node of 'regulators' node to dev->of_node
when calling regulator_register(regulator_desc, dev, ...) from
regulator driver, the regulator core will be able to find all nodes under
'regulators' using for_each_child_of_node(dev->of_node, child).

Then the question would be how we attach the device_node of 'regulators'
to dev->of_node where 'dev' is the second level device above.  I somehow
hesitate to hack this into mfd_add_devices(), so I would like to add
compatible string "fsl,mc13892-regulators" to node 'regulators' and
find the node using of_find_compatible_node(dev->parent, NULL,
"fsl,mc13892-regulators").

I'm not sure this is exactly same as what your comment suggests above.
So please let me know if it's appropriate.

-- 
Regards,
Shawn

^ permalink raw reply

* Re: [PATCH v2 3/5] regulator: helper routine to extract regulator_init_data
From: Shawn Guo @ 2011-10-24 13:04 UTC (permalink / raw)
  To: Grant Likely
  Cc: broonie, patches, tony, devicetree-discuss, Rajendra Nayak,
	linux-kernel, linux-omap, lrg, linux-arm-kernel
In-Reply-To: <20111024092411.GE8708@ponder.secretlab.ca>

On Mon, Oct 24, 2011 at 11:24:11AM +0200, Grant Likely wrote:
> On Fri, Oct 21, 2011 at 04:23:12PM +0800, Shawn Guo wrote:
> > On Thu, Oct 20, 2011 at 05:39:32PM +0530, Rajendra Nayak wrote:
> > > On Thursday 20 October 2011 11:44 AM, Shawn Guo wrote:
> > > >On Thu, Oct 20, 2011 at 10:48:58AM +0530, Rajendra Nayak wrote:
> > > >>>Let's look at mc13892-regulator driver.  There are 23 regulators defined
> > > >>>in array mc13892_regulators.  Needless to say, there is a dev behind
> > > >>>mc13892-regulator driver.  And when getting probed, this driver will
> > > >>>call regulator_register() to register those 23 regulators individually.
> > > >>>That said, for non-dt world, we have 1 + 23 'dev' with that 1 as the
> > > >>>parent of all other 23 'dev' (wrapped by regulator_dev).  But with the
> > > >>>current DT implementation, we will have at least 1 + 23 * 2 'dev'.
> > > >>>These extra 23 'dev' is totally new with DT.
> > > >>>
> > > >>
> > > >>but thats only because the mc13892-regulator driver is implemeted in
> > > >>such a way that all the regulators on the platform are bundled in as
> > > >>*one* device.
> > > >
> > > >I did not look into too many regulator drivers, but I expect this is
> > > >way that most regulator drivers are implemented in.  Having
> > > >mc13892-regulator being probed 23 times to register these 23 regulators
> > > >just makes less sense to me.
> > > >
> > > >>It would again depend on how you would pass these from
> > > >>the DT, if you indeed stick to the same way of bundling all regulators
> > > >>as one device from DT, the mc13892-regulator probe would just get called
> > > >>once and there would be one device associated, no?
> > > >>
> > > >Yes, I indeed would stick to the same way of bundling the registration
> > > >of all regulators with mc13892-regulator being probed once.  The problem
> > > >I have with the current regulator core DT implementation is that it
> > > >assumes the device_node of rdev->dev (dev wrapped in regulator_dev) is
> > > >being attached to rdev->dev.parent rather than itself.  Back to
> > > >mc13892-regulator example, that said, it requires the dev of
> > > >mc13892-regulator have the device_node of individual regulator attached
> > > >to.  IOW, the current implementation forces mc13892-regulator to be
> > > >probed 23 times to register those 23 regulators.  This is wrong to me.
> > > 
> > > I think I now understand to some extent the problem that you seem to be
> > > reporting. It is mainly with drivers which bundle all regulators and
> > > pass them as one device and would want to do so with DT too.
> > > 
> > > however I am still not clear on how what you seem to suggest would
> > > solve this problem. Note that not all drivers do it this way, and
> > > there are drivers where each regulator is considered as one device
> > > and I suspect they would remain that way with DT too. And hence we
> > > need to support both.
> > > 
> > > Do you have any RFC patch/code which could explain better what you are
> > > suggesting we do here?
> > > >
> > Here is what I changed based on your patches.  It only changes
> > drivers/regulator/core.c.
> > 
> > ---8<-------
> > diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> > index 9a5ebbe..8fe132d 100644
> > --- a/drivers/regulator/core.c
> > +++ b/drivers/regulator/core.c
> > @@ -1211,7 +1211,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
> >                 node = of_get_regulator(dev, id);
> >                 if (node)
> >                         list_for_each_entry(rdev, &regulator_list, list)
> > -                               if (node == rdev->dev.parent->of_node)
> > +                               if (node == rdev->dev.of_node)
> >                                         goto found;
> >         }
> >         list_for_each_entry(map, &regulator_map_list, list) {
> > @@ -2642,9 +2642,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >             regulator_desc->type != REGULATOR_CURRENT)
> >                 return ERR_PTR(-EINVAL);
> > 
> > -       if (!init_data)
> > -               return ERR_PTR(-EINVAL);
> > -
> >         /* Only one of each should be implemented */
> >         WARN_ON(regulator_desc->ops->get_voltage &&
> >                 regulator_desc->ops->get_voltage_sel);
> > @@ -2675,12 +2672,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >         INIT_LIST_HEAD(&rdev->list);
> >         BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
> > 
> > -       /* preform any regulator specific init */
> > -       if (init_data->regulator_init) {
> > -               ret = init_data->regulator_init(rdev->reg_data);
> > -               if (ret < 0)
> > -                       goto clean;
> > -       }
> > +       /* find device_node and attach it */
> > +       rdev->dev.of_node = of_find_node_by_name(NULL, regulator_desc->name);
> > 
> >         /* register with sysfs */
> >         rdev->dev.class = &regulator_class;
> > @@ -2693,6 +2686,20 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >                 goto clean;
> >         }
> > 
> > +       if (!init_data) {
> > +               /* try to get init_data from device tree */
> > +               init_data = of_get_regulator_init_data(&rdev->dev);
> > +               if (!init_data)
> > +                       return ERR_PTR(-EINVAL);
> > +       }
> > +
> > +       /* preform any regulator specific init */
> > +       if (init_data->regulator_init) {
> > +               ret = init_data->regulator_init(rdev->reg_data);
> > +               if (ret < 0)
> > +                       goto clean;
> > +       }
> > +
> >         dev_set_drvdata(&rdev->dev, rdev);
> > 
> >         /* set regulator constraints */
> > @@ -2719,7 +2726,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
> >                         node = of_get_regulator(dev, supply);
> >                         if (node)
> >                                 list_for_each_entry(r, &regulator_list, list)
> > -                                       if (node == r->dev.parent->of_node)
> > +                                       if (node == r->dev.of_node)
> >                                                 goto found;
> >                 }
> > 
> > ------->8---
> > 
> > And my dts file looks like something below.
> > 
> > 	ecspi@70010000 { /* ECSPI1 */
> > 		fsl,spi-num-chipselects = <2>;
> > 		cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
> > 			   <&gpio3 25 0>; /* GPIO4_25 */
> > 		status = "okay";
> > 
> > 		pmic: mc13892@0 {
> > 			#address-cells = <1>;
> > 			#size-cells = <0>;
> > 			compatible = "fsl,mc13892";
> > 			spi-max-frequency = <6000000>;
> > 			reg = <0>;
> > 			mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */
> > 
> > 			regulators {
> > 				sw1reg: mc13892_sw1 {
> > 					regulator-min-uV = <600000>;
> > 					regulator-max-uV = <1375000>;
> > 					regulator-change-voltage;
> > 					regulator-boot-on;
> > 					regulator-always-on;
> > 				};
> > 
> > 				sw2reg: mc13892_sw2 {
> > 					regulator-min-uV = <900000>;
> > 					regulator-max-uV = <1850000>;
> > 					regulator-change-voltage;
> > 					regulator-boot-on;
> > 					regulator-always-on;
> > 				};
> > 
> > 				......
> > 			};
> 
> To follow up from my earlier comment, this .dts structure looks fine
> and reasonable to me, and it would also be fine for the mc13892 driver
> to use for_each_child_of_node() to find all the children of the
> regulators node.  Even finding the 'regulators' node by name from the
> mc13892 driver is perfectly fine provided for_each_child_of_node is
> used to find it.  All of this is okay because it is under the umbrella
> of the "fsl,mc13892" binding.
> 
For mc13892 regulator example, there are 3 levels 'struct dev'.

1. drivers/mfd/mc13xxx-core.c
   The "fsl,mc13892" binding is used in this mfd driver to get
   mc13xxx-core device probed.  And this mfd driver will in turn
   call mfd_add_devices() to add the second level device below.

2. drivers/regulator/mc13892-regulator.c
   As this device is created by mfd_add_devices() above, there is no
   device_node attached to its of_node, though we would hope that node
   'regulators' is attached there.  And the driver will call
   regulator_register() to have each regulator device created and
   registered in regulator core below.

3. drivers/regulator/core.c
   regulator_register() called above will create device (rdev->dev)
   for each regulator.

I am thinking about hiding the device_node discovering for each
regulator from the second level (regulator driver) and make it
internal to the third level (regulator core), as it seems to me
that regulator driver does not need to necessarily know about this.

If we can attach the device_node of 'regulators' node to dev->of_node
when calling regulator_register(regulator_desc, dev, ...) from
regulator driver, the regulator core will be able to find all nodes under
'regulators' using for_each_child_of_node(dev->of_node, child).

Then the question would be how we attach the device_node of 'regulators'
to dev->of_node where 'dev' is the second level device above.  I somehow
hesitate to hack this into mfd_add_devices(), so I would like to add
compatible string "fsl,mc13892-regulators" to node 'regulators' and
find the node using of_find_compatible_node(dev->parent, NULL,
"fsl,mc13892-regulators").

I'm not sure this is exactly same as what your comment suggests above.
So please let me know if it's appropriate.

-- 
Regards,
Shawn

^ permalink raw reply

* M-ONLINE ....
From: M-ONLINE @ 2011-10-24 12:57 UTC (permalink / raw)



KINDLY PROVIDE YOUR NAME-  ADDRESS-  SEX-  AGE-  MOBILE-  FOR YOUR ONE-MILLION POUNDS WHICH
YOU HAVE WON.  

^ permalink raw reply

* Re: [PATCH 0/2] ARM: Samsung: Add basic device tree support for Exynos4 boards
From: Kukjin Kim @ 2011-10-24 13:02 UTC (permalink / raw)
  To: Thomas Abraham
  Cc: devicetree-discuss, linux-samsung-soc, grant.likely, rob.herring,
	arnd, kgene.kim, linux-arm-kernel, patches
In-Reply-To: <1318342396-26178-1-git-send-email-thomas.abraham@linaro.org>

On 10/11/11 16:13, Thomas Abraham wrote:
> This patchset adds a new basic device tree enabled machine/board file which is
> based on the Samsung's Exynos4 family of SoC's. Also included in this patchset is the
> dts file for Exynos4210 SoC, Samsung's SMDKV310 board and Insignal's Origen board.
>
> The Exynos4210 dts file includes support for IRQ, GPIO, WDT, RTC, UART, SDHCI, Keypad,
> DMA and I2C controllers. As device tree coverage for Exynos4210 increases, additional
> device nodes to represent the controllers should be added.
>
> The device tree enabled machine file enables boot on two boards based on the
> Exynos4210 SoC. This provides a starting point to add additional device tree support
> on these boards, migrate other existing Exynos4 based boards to use device tree
> and enable device tree based boot on new upcoming boards.
>
> This patchset has been tested on the following tree:
>    https://github.com/kgene/linux-samsung.git   branch: for-next
>
> Thomas Abraham (2):
>    ARM: Samsung: Add Exynos4 device tree enabled board file
>    ARM: dts: Add intial dts file for Exynos4210 SoC, SMDKV310 and Origen board
>
>   .../devicetree/bindings/arm/insignal-boards.txt    |    8 +
>   .../devicetree/bindings/arm/samsung-boards.txt     |    8 +
>   arch/arm/boot/dts/exynos4210-origen.dts            |  137 +++++++
>   arch/arm/boot/dts/exynos4210-smdkv310.dts          |  182 +++++++++
>   arch/arm/boot/dts/exynos4210.dtsi                  |  403 ++++++++++++++++++++
>   arch/arm/mach-exynos4/Kconfig                      |   14 +
>   arch/arm/mach-exynos4/Makefile                     |    2 +
>   arch/arm/mach-exynos4/mach-exynos4-dt.c            |   85 ++++
>   8 files changed, 839 insertions(+), 0 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/arm/insignal-boards.txt
>   create mode 100644 Documentation/devicetree/bindings/arm/samsung-boards.txt
>   create mode 100644 arch/arm/boot/dts/exynos4210-origen.dts
>   create mode 100644 arch/arm/boot/dts/exynos4210-smdkv310.dts
>   create mode 100644 arch/arm/boot/dts/exynos4210.dtsi
>   create mode 100644 arch/arm/mach-exynos4/mach-exynos4-dt.c

Applied.
Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply

* [PATCH 0/2] ARM: Samsung: Add basic device tree support for Exynos4 boards
From: Kukjin Kim @ 2011-10-24 13:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318342396-26178-1-git-send-email-thomas.abraham@linaro.org>

On 10/11/11 16:13, Thomas Abraham wrote:
> This patchset adds a new basic device tree enabled machine/board file which is
> based on the Samsung's Exynos4 family of SoC's. Also included in this patchset is the
> dts file for Exynos4210 SoC, Samsung's SMDKV310 board and Insignal's Origen board.
>
> The Exynos4210 dts file includes support for IRQ, GPIO, WDT, RTC, UART, SDHCI, Keypad,
> DMA and I2C controllers. As device tree coverage for Exynos4210 increases, additional
> device nodes to represent the controllers should be added.
>
> The device tree enabled machine file enables boot on two boards based on the
> Exynos4210 SoC. This provides a starting point to add additional device tree support
> on these boards, migrate other existing Exynos4 based boards to use device tree
> and enable device tree based boot on new upcoming boards.
>
> This patchset has been tested on the following tree:
>    https://github.com/kgene/linux-samsung.git   branch: for-next
>
> Thomas Abraham (2):
>    ARM: Samsung: Add Exynos4 device tree enabled board file
>    ARM: dts: Add intial dts file for Exynos4210 SoC, SMDKV310 and Origen board
>
>   .../devicetree/bindings/arm/insignal-boards.txt    |    8 +
>   .../devicetree/bindings/arm/samsung-boards.txt     |    8 +
>   arch/arm/boot/dts/exynos4210-origen.dts            |  137 +++++++
>   arch/arm/boot/dts/exynos4210-smdkv310.dts          |  182 +++++++++
>   arch/arm/boot/dts/exynos4210.dtsi                  |  403 ++++++++++++++++++++
>   arch/arm/mach-exynos4/Kconfig                      |   14 +
>   arch/arm/mach-exynos4/Makefile                     |    2 +
>   arch/arm/mach-exynos4/mach-exynos4-dt.c            |   85 ++++
>   8 files changed, 839 insertions(+), 0 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/arm/insignal-boards.txt
>   create mode 100644 Documentation/devicetree/bindings/arm/samsung-boards.txt
>   create mode 100644 arch/arm/boot/dts/exynos4210-origen.dts
>   create mode 100644 arch/arm/boot/dts/exynos4210-smdkv310.dts
>   create mode 100644 arch/arm/boot/dts/exynos4210.dtsi
>   create mode 100644 arch/arm/mach-exynos4/mach-exynos4-dt.c

Applied.
Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply

* [PATCH v5 0/2] Add device tree support for Samsung's keypad controller driver
From: Kukjin Kim @ 2011-10-24 13:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <057501cc880e$af0a28a0$0d1e79e0$%kim@samsung.com>

On 10/11/11 14:09, Kukjin Kim wrote:
> Thomas Abraham wrote:
>>
>> Changes since v4:
>> - Tested with linux 3.1-rc9. No changes in code.
>>
>> Changes since v3:
>> - Addressed comments from Grant Likely.
>>    - Set num_rows and num_cols to zero in samsung_keypad_parse_dt function.
>>    - Fixed the wierd looking if-else block in samsung_keypad_probe
> function.
>>
>> Changes since v2:
>> - Addressed comments from Grant Likely.
>>    - Renamed 'keypad,key-code' property name to 'linux,code'.
>>    - Fixed incorrect data types for all instances of of_property+read_u32.
>>    - linux,input-type binding was not added as suggested since the driver
>>      supports only EV_KEY event type.
>>
>> Changes since v1:
>> - Addressed comments from Dmitry Torokhov.
>>    - Type of controller is cached in driver's private data and the function
>>      that determines the type of the controller for each keypad scan is
>>      removed.
>>    - pdata allocated during probe is explicitly freed after probe completes
>>      without any error. In case of exit from probe due a error, no explicit
>>      deallocation of pdata memory is performed and it is left to devres to
>>      handle that.
>>    - The generic code to translate KEY(x,y,code) is retained in the driver
>>      itself. I am unsure of a right common place for it.
>>    - Driver continues with the probe even if one or more gpio configuration
>>      fails.
>>    - Patch 1 that adds a new config option is still retained in this
> patchset.
>>
>>
>> This patchset adds device tree support for samsung's keypad controller
> driver.
>> First patch adds a new config option to be used by device tree enabled
> platforms
>> for selecting the samsung's keypad controller driver. The second patch
> adds
>> device
>> tree support for the keypad driver.
>>
>>
>> Thomas Abraham (2):
>>    input: samsung-keypad: Add HAVE_SAMSUNG_KEYPAD config option
>>    input: samsung-keypad: Add device tree support
>>
>>   .../devicetree/bindings/input/samsung-keypad.txt   |   88 ++++++++++
>>   drivers/input/keyboard/Kconfig                     |    9 +-
>>   drivers/input/keyboard/samsung-keypad.c            |  174
>> ++++++++++++++++++--
>>   3 files changed, 258 insertions(+), 13 deletions(-)
>>   create mode 100644 Documentation/devicetree/bindings/input/samsung-
>> keypad.txt
>
> Looks ok to me,
> Acked-by: Kukjin Kim<kgene.kim@samsung.com>
>
> Hi Dmitry,
> If you're ok on this, please adding this in your tree for upcoming merge
> window.
>
Dmitry,

Any problem on this?

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply

* Re: [PATCH v5 0/2] Add device tree support for Samsung's keypad controller driver
From: Kukjin Kim @ 2011-10-24 13:00 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: 'Thomas Abraham', devicetree-discuss, dmitry.torokhov,
	grant.likely, linux-input, linux-samsung-soc, linux-arm-kernel,
	jy0922.shim, dh09.lee, patches
In-Reply-To: <057501cc880e$af0a28a0$0d1e79e0$%kim@samsung.com>

On 10/11/11 14:09, Kukjin Kim wrote:
> Thomas Abraham wrote:
>>
>> Changes since v4:
>> - Tested with linux 3.1-rc9. No changes in code.
>>
>> Changes since v3:
>> - Addressed comments from Grant Likely.
>>    - Set num_rows and num_cols to zero in samsung_keypad_parse_dt function.
>>    - Fixed the wierd looking if-else block in samsung_keypad_probe
> function.
>>
>> Changes since v2:
>> - Addressed comments from Grant Likely.
>>    - Renamed 'keypad,key-code' property name to 'linux,code'.
>>    - Fixed incorrect data types for all instances of of_property+read_u32.
>>    - linux,input-type binding was not added as suggested since the driver
>>      supports only EV_KEY event type.
>>
>> Changes since v1:
>> - Addressed comments from Dmitry Torokhov.
>>    - Type of controller is cached in driver's private data and the function
>>      that determines the type of the controller for each keypad scan is
>>      removed.
>>    - pdata allocated during probe is explicitly freed after probe completes
>>      without any error. In case of exit from probe due a error, no explicit
>>      deallocation of pdata memory is performed and it is left to devres to
>>      handle that.
>>    - The generic code to translate KEY(x,y,code) is retained in the driver
>>      itself. I am unsure of a right common place for it.
>>    - Driver continues with the probe even if one or more gpio configuration
>>      fails.
>>    - Patch 1 that adds a new config option is still retained in this
> patchset.
>>
>>
>> This patchset adds device tree support for samsung's keypad controller
> driver.
>> First patch adds a new config option to be used by device tree enabled
> platforms
>> for selecting the samsung's keypad controller driver. The second patch
> adds
>> device
>> tree support for the keypad driver.
>>
>>
>> Thomas Abraham (2):
>>    input: samsung-keypad: Add HAVE_SAMSUNG_KEYPAD config option
>>    input: samsung-keypad: Add device tree support
>>
>>   .../devicetree/bindings/input/samsung-keypad.txt   |   88 ++++++++++
>>   drivers/input/keyboard/Kconfig                     |    9 +-
>>   drivers/input/keyboard/samsung-keypad.c            |  174
>> ++++++++++++++++++--
>>   3 files changed, 258 insertions(+), 13 deletions(-)
>>   create mode 100644 Documentation/devicetree/bindings/input/samsung-
>> keypad.txt
>
> Looks ok to me,
> Acked-by: Kukjin Kim<kgene.kim@samsung.com>
>
> Hi Dmitry,
> If you're ok on this, please adding this in your tree for upcoming merge
> window.
>
Dmitry,

Any problem on this?

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply

* [Bug 42160] [NV4e] Mouse pointer disappears randomly after resuming from GNOME screensaver
From: bugzilla-daemon-CC+yJ3UmIYqDUpFQwHEjaQ @ 2011-10-24 12:59 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <bug-42160-8800-V0hAGp6uBxMKqLRl/0Ahz6D7qz1kEfGD2LY78lusg7I@public.gmane.org/>

https://bugs.freedesktop.org/show_bug.cgi?id=42160

--- Comment #2 from Matias Kreder <delete-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy@public.gmane.org> 2011-10-24 05:59:41 PDT ---
Created attachment 52688
  --> https://bugs.freedesktop.org/attachment.cgi?id=52688
Xorg log

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

^ permalink raw reply

* [Bug 42160] [NV4e] Mouse pointer disappears randomly after resuming from GNOME screensaver
From: bugzilla-daemon-CC+yJ3UmIYqDUpFQwHEjaQ @ 2011-10-24 12:58 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <bug-42160-8800-V0hAGp6uBxMKqLRl/0Ahz6D7qz1kEfGD2LY78lusg7I@public.gmane.org/>

https://bugs.freedesktop.org/show_bug.cgi?id=42160

--- Comment #1 from Matias Kreder <delete-rxtnV0ftBwyoClj4AeEUq9i2O/JbrIOy@public.gmane.org> 2011-10-24 05:58:43 PDT ---
Created attachment 52687
  --> https://bugs.freedesktop.org/attachment.cgi?id=52687
dmesg output with drb.debug

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.