Commit f0a08fcb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull arch/tile updates from Chris Metcalf:
 "These changes provide support for PCIe root complex and USB host mode
  for tilegx's on-chip I/Os.

  In addition, this pull provides the required underpinning for the
  on-chip networking support that was pulled into 3.5.  The changes have
  all been through LKML (with several rounds for PCIe RC) and on
  linux-next."

* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  tile: updates to pci root complex from community feedback
  bounce: allow use of bounce pool via config option
  usb: add host support for the tilegx architecture
  arch/tile: provide kernel support for the tilegx USB shim
  tile pci: enable IOMMU to support DMA for legacy devices
  arch/tile: enable ZONE_DMA for tilegx
  tilegx pci: support I/O to arbitrarily-cached pages
  tile: remove unused header
  arch/tile: tilegx PCI root complex support
  arch/tile: provide kernel support for the tilegx TRIO shim
  arch/tile: break out the "csum a long" function to <asm/checksum.h>
  arch/tile: provide kernel support for the tilegx mPIPE shim
  arch/tile: common DMA code for the GXIO IORPC subsystem
  arch/tile: support MMIO-based readb/writeb etc.
  arch/tile: introduce GXIO IORPC framework for tilegx
parents 474183b1 f6d2ce00
Loading
Loading
Loading
Loading
+42 −0
Original line number Original line Diff line number Diff line
@@ -3,6 +3,8 @@


config TILE
config TILE
	def_bool y
	def_bool y
	select HAVE_DMA_ATTRS
	select HAVE_DMA_API_DEBUG
	select HAVE_KVM if !TILEGX
	select HAVE_KVM if !TILEGX
	select GENERIC_FIND_FIRST_BIT
	select GENERIC_FIND_FIRST_BIT
	select USE_GENERIC_SMP_HELPERS
	select USE_GENERIC_SMP_HELPERS
@@ -79,6 +81,9 @@ config ARCH_DMA_ADDR_T_64BIT
config NEED_DMA_MAP_STATE
config NEED_DMA_MAP_STATE
	def_bool y
	def_bool y


config ARCH_HAS_DMA_SET_COHERENT_MASK
	bool

config LOCKDEP_SUPPORT
config LOCKDEP_SUPPORT
	def_bool y
	def_bool y


@@ -212,6 +217,22 @@ config HIGHMEM


	  If unsure, say "true".
	  If unsure, say "true".


config ZONE_DMA
	def_bool y

config IOMMU_HELPER
	bool

config NEED_SG_DMA_LENGTH
	bool

config SWIOTLB
	bool
	default TILEGX
	select IOMMU_HELPER
	select NEED_SG_DMA_LENGTH
	select ARCH_HAS_DMA_SET_COHERENT_MASK

# We do not currently support disabling NUMA.
# We do not currently support disabling NUMA.
config NUMA
config NUMA
	bool # "NUMA Memory Allocation and Scheduler Support"
	bool # "NUMA Memory Allocation and Scheduler Support"
@@ -345,6 +366,8 @@ config KERNEL_PL
	  kernel will be built to run at.  Generally you should use
	  kernel will be built to run at.  Generally you should use
	  the default value here.
	  the default value here.


source "arch/tile/gxio/Kconfig"

endmenu  # Tilera-specific configuration
endmenu  # Tilera-specific configuration


menu "Bus options"
menu "Bus options"
@@ -354,6 +377,9 @@ config PCI
	default y
	default y
	select PCI_DOMAINS
	select PCI_DOMAINS
	select GENERIC_PCI_IOMAP
	select GENERIC_PCI_IOMAP
	select TILE_GXIO_TRIO if TILEGX
	select ARCH_SUPPORTS_MSI if TILEGX
	select PCI_MSI if TILEGX
	---help---
	---help---
	  Enable PCI root complex support, so PCIe endpoint devices can
	  Enable PCI root complex support, so PCIe endpoint devices can
	  be attached to the Tile chip.  Many, but not all, PCI devices
	  be attached to the Tile chip.  Many, but not all, PCI devices
@@ -370,6 +396,22 @@ config NO_IOPORT


source "drivers/pci/Kconfig"
source "drivers/pci/Kconfig"


config TILE_USB
	tristate "Tilera USB host adapter support"
	default y
	depends on USB
	depends on TILEGX
	select TILE_GXIO_USB_HOST
	---help---
	  Provides USB host adapter support for the built-in EHCI and OHCI
	  interfaces on TILE-Gx chips.

# USB OHCI needs the bounce pool since tilegx will often have more
# than 4GB of memory, but we don't currently use the IOTLB to present
# a 32-bit address to OHCI.  So we need to use a bounce pool instead.
config NEED_BOUNCE_POOL
	def_bool USB_OHCI_HCD

config HOTPLUG
config HOTPLUG
	bool "Support for hot-pluggable devices"
	bool "Support for hot-pluggable devices"
	---help---
	---help---
+2 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,8 @@ libs-y += $(LIBGCC_PATH)
# See arch/tile/Kbuild for content of core part of the kernel
# See arch/tile/Kbuild for content of core part of the kernel
core-y		+= arch/tile/
core-y		+= arch/tile/


core-$(CONFIG_TILE_GXIO) += arch/tile/gxio/

ifdef TILERA_ROOT
ifdef TILERA_ROOT
INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
endif
endif

arch/tile/gxio/Kconfig

0 → 100644
+28 −0
Original line number Original line Diff line number Diff line
# Support direct access to TILE-Gx hardware from user space, via the
# gxio library, or from kernel space, via kernel IORPC support.
config TILE_GXIO
	bool
	depends on TILEGX

# Support direct access to the common I/O DMA facility within the
# TILE-Gx mPIPE and Trio hardware from kernel space.
config TILE_GXIO_DMA
	bool
	select TILE_GXIO

# Support direct access to the TILE-Gx mPIPE hardware from kernel space.
config TILE_GXIO_MPIPE
	bool
	select TILE_GXIO
	select TILE_GXIO_DMA

# Support direct access to the TILE-Gx TRIO hardware from kernel space.
config TILE_GXIO_TRIO
	bool
	select TILE_GXIO
	select TILE_GXIO_DMA

# Support direct access to the TILE-Gx USB hardware from kernel space.
config TILE_GXIO_USB_HOST
	bool
	select TILE_GXIO
+9 −0
Original line number Original line Diff line number Diff line
#
# Makefile for the Tile-Gx device access support.
#

obj-$(CONFIG_TILE_GXIO) += iorpc_globals.o kiorpc.o
obj-$(CONFIG_TILE_GXIO_DMA) += dma_queue.o
obj-$(CONFIG_TILE_GXIO_MPIPE) += mpipe.o iorpc_mpipe.o iorpc_mpipe_info.o
obj-$(CONFIG_TILE_GXIO_TRIO) += trio.o iorpc_trio.o
obj-$(CONFIG_TILE_GXIO_USB_HOST) += usb_host.o iorpc_usb_host.o
+176 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2012 Tilera Corporation. All Rights Reserved.
 *
 *   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, version 2.
 *
 *   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, GOOD TITLE or
 *   NON INFRINGEMENT.  See the GNU General Public License for
 *   more details.
 */

#include <linux/io.h>
#include <linux/atomic.h>
#include <linux/module.h>
#include <gxio/dma_queue.h>

/* Wait for a memory read to complete. */
#define wait_for_value(val)                             \
  __asm__ __volatile__("move %0, %0" :: "r"(val))

/* The index is in the low 16. */
#define DMA_QUEUE_INDEX_MASK ((1 << 16) - 1)

/*
 * The hardware descriptor-ring type.
 * This matches the types used by mpipe (MPIPE_EDMA_POST_REGION_VAL_t)
 * and trio (TRIO_PUSH_DMA_REGION_VAL_t or TRIO_PULL_DMA_REGION_VAL_t).
 * See those types for more documentation on the individual fields.
 */
typedef union {
	struct {
#ifndef __BIG_ENDIAN__
		uint64_t ring_idx:16;
		uint64_t count:16;
		uint64_t gen:1;
		uint64_t __reserved:31;
#else
		uint64_t __reserved:31;
		uint64_t gen:1;
		uint64_t count:16;
		uint64_t ring_idx:16;
#endif
	};
	uint64_t word;
} __gxio_ring_t;

void __gxio_dma_queue_init(__gxio_dma_queue_t *dma_queue,
			   void *post_region_addr, unsigned int num_entries)
{
	/*
	 * Limit 65536 entry rings to 65535 credits because we only have a
	 * 16 bit completion counter.
	 */
	int64_t credits = (num_entries < 65536) ? num_entries : 65535;

	memset(dma_queue, 0, sizeof(*dma_queue));

	dma_queue->post_region_addr = post_region_addr;
	dma_queue->hw_complete_count = 0;
	dma_queue->credits_and_next_index = credits << DMA_QUEUE_CREDIT_SHIFT;
}

EXPORT_SYMBOL_GPL(__gxio_dma_queue_init);

void __gxio_dma_queue_update_credits(__gxio_dma_queue_t *dma_queue)
{
	__gxio_ring_t val;
	uint64_t count;
	uint64_t delta;
	uint64_t new_count;

	/*
	 * Read the 64-bit completion count without touching the cache, so
	 * we later avoid having to evict any sharers of this cache line
	 * when we update it below.
	 */
	uint64_t orig_hw_complete_count =
		cmpxchg(&dma_queue->hw_complete_count,
			-1, -1);

	/* Make sure the load completes before we access the hardware. */
	wait_for_value(orig_hw_complete_count);

	/* Read the 16-bit count of how many packets it has completed. */
	val.word = __gxio_mmio_read(dma_queue->post_region_addr);
	count = val.count;

	/*
	 * Calculate the number of completions since we last updated the
	 * 64-bit counter.  It's safe to ignore the high bits because the
	 * maximum credit value is 65535.
	 */
	delta = (count - orig_hw_complete_count) & 0xffff;
	if (delta == 0)
		return;

	/*
	 * Try to write back the count, advanced by delta.  If we race with
	 * another thread, this might fail, in which case we return
	 * immediately on the assumption that some credits are (or at least
	 * were) available.
	 */
	new_count = orig_hw_complete_count + delta;
	if (cmpxchg(&dma_queue->hw_complete_count,
		    orig_hw_complete_count,
		    new_count) != orig_hw_complete_count)
		return;

	/*
	 * We succeeded in advancing the completion count; add back the
	 * corresponding number of egress credits.
	 */
	__insn_fetchadd(&dma_queue->credits_and_next_index,
			(delta << DMA_QUEUE_CREDIT_SHIFT));
}

EXPORT_SYMBOL_GPL(__gxio_dma_queue_update_credits);

/*
 * A separate 'blocked' method for put() so that backtraces and
 * profiles will clearly indicate that we're wasting time spinning on
 * egress availability rather than actually posting commands.
 */
int64_t __gxio_dma_queue_wait_for_credits(__gxio_dma_queue_t *dma_queue,
					  int64_t modifier)
{
	int backoff = 16;
	int64_t old;

	do {
		int i;
		/* Back off to avoid spamming memory networks. */
		for (i = backoff; i > 0; i--)
			__insn_mfspr(SPR_PASS);

		/* Check credits again. */
		__gxio_dma_queue_update_credits(dma_queue);
		old = __insn_fetchaddgez(&dma_queue->credits_and_next_index,
					 modifier);

		/* Calculate bounded exponential backoff for next iteration. */
		if (backoff < 256)
			backoff *= 2;
	} while (old + modifier < 0);

	return old;
}

EXPORT_SYMBOL_GPL(__gxio_dma_queue_wait_for_credits);

int64_t __gxio_dma_queue_reserve_aux(__gxio_dma_queue_t *dma_queue,
				     unsigned int num, int wait)
{
	return __gxio_dma_queue_reserve(dma_queue, num, wait != 0, true);
}

EXPORT_SYMBOL_GPL(__gxio_dma_queue_reserve_aux);

int __gxio_dma_queue_is_complete(__gxio_dma_queue_t *dma_queue,
				 int64_t completion_slot, int update)
{
	if (update) {
		if (ACCESS_ONCE(dma_queue->hw_complete_count) >
		    completion_slot)
			return 1;

		__gxio_dma_queue_update_credits(dma_queue);
	}

	return ACCESS_ONCE(dma_queue->hw_complete_count) > completion_slot;
}

EXPORT_SYMBOL_GPL(__gxio_dma_queue_is_complete);
Loading