Commit 5ce6386b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (24 commits)
  [POWERPC] Convert the cell IOMMU fixed mapping to 16M IOMMU pages
  [POWERPC] Allow for different IOMMU page sizes in cell IOMMU code
  [POWERPC] Cell IOMMU: n_pte_pages is in 4K page units, not IOMMU_PAGE_SIZE
  [POWERPC] Split setup of IOMMU stab and ptab, allocate dynamic/fixed ptabs separately
  [POWERPC] Move allocation of cell IOMMU pad page
  [POWERPC] Remove unused pte_offset variable
  [POWERPC] Use it_offset not pte_offset in cell IOMMU code
  [POWERPC] Clearup cell IOMMU fixed mapping terminology
  [POWERPC] enable hardware watchpoints on cell blades
  [POWERPC] move celleb DABRX definitions
  [POWERPC] OProfile: enable callgraph support for Cell
  [POWERPC] spufs: fix use time accounting on SPE-overcommit
  [POWERPC] spufs: serialize SLB invalidation against SLB loading
  [POWERPC] spufs: invalidate SLB translation before adding a new entry
  [POWERPC] spufs: synchronize IRQ when disabling
  [POWERPC] spufs: fix order of sputrace thread IDs
  [POWERPC] Xilinx: hwicap cleanup
  [POWERPC] 4xx: Use correct board info structure in cuboot wrappers
  [POWERPC] spufs: fix invalid scheduling of forgotten contexts
  [POWERPC] 44x: add missing define TARGET_4xx and TARGET_440GX to cuboot-taishan
  ...
parents a64e715f 3cecdda3
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "44x.h" #include "44x.h"
#include "cuboot.h" #include "cuboot.h"
#define TARGET_4xx
#define TARGET_44x #define TARGET_44x
#include "ppcboot.h" #include "ppcboot.h"
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "44x.h" #include "44x.h"
#include "cuboot.h" #include "cuboot.h"
#define TARGET_4xx
#define TARGET_44x #define TARGET_44x
#include "ppcboot.h" #include "ppcboot.h"
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "44x.h" #include "44x.h"
#include "cuboot.h" #include "cuboot.h"
#define TARGET_4xx
#define TARGET_44x #define TARGET_44x
#include "ppcboot.h" #include "ppcboot.h"
......
...@@ -21,7 +21,9 @@ ...@@ -21,7 +21,9 @@
#include "dcr.h" #include "dcr.h"
#include "4xx.h" #include "4xx.h"
#define TARGET_4xx
#define TARGET_44x #define TARGET_44x
#define TARGET_440GX
#include "ppcboot.h" #include "ppcboot.h"
static bd_t bd; static bd_t bd;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "4xx.h" #include "4xx.h"
#include "cuboot.h" #include "cuboot.h"
#define TARGET_4xx
#define TARGET_44x #define TARGET_44x
#include "ppcboot.h" #include "ppcboot.h"
......
...@@ -235,7 +235,7 @@ PCIE0: pciex@0a0000000 { ...@@ -235,7 +235,7 @@ PCIE0: pciex@0a0000000 {
#interrupt-cells = <1>; #interrupt-cells = <1>;
#size-cells = <2>; #size-cells = <2>;
#address-cells = <3>; #address-cells = <3>;
compatible = "ibm,plb-pciex-405exr", "ibm,plb-pciex"; compatible = "ibm,plb-pciex-405ex", "ibm,plb-pciex";
primary; primary;
port = <0>; /* port number */ port = <0>; /* port number */
reg = <a0000000 20000000 /* Config space access */ reg = <a0000000 20000000 /* Config space access */
......
...@@ -38,8 +38,8 @@ cpu@0 { ...@@ -38,8 +38,8 @@ cpu@0 {
timebase-frequency = <0>; /* Filled in by zImage */ timebase-frequency = <0>; /* Filled in by zImage */
i-cache-line-size = <20>; i-cache-line-size = <20>;
d-cache-line-size = <20>; d-cache-line-size = <20>;
i-cache-size = <20000>; i-cache-size = <8000>;
d-cache-size = <20000>; d-cache-size = <8000>;
dcr-controller; dcr-controller;
dcr-access-method = "native"; dcr-access-method = "native";
}; };
...@@ -136,11 +136,11 @@ MAL0: mcmal { ...@@ -136,11 +136,11 @@ MAL0: mcmal {
}; };
POB0: opb { POB0: opb {
compatible = "ibm,opb-440spe", "ibm,opb-440gp", "ibm,opb"; compatible = "ibm,opb-440spe", "ibm,opb-440gp", "ibm,opb";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
ranges = <00000000 4 e0000000 20000000>; ranges = <00000000 4 e0000000 20000000>;
clock-frequency = <0>; /* Filled in by zImage */ clock-frequency = <0>; /* Filled in by zImage */
EBC0: ebc { EBC0: ebc {
compatible = "ibm,ebc-440spe", "ibm,ebc-440gp", "ibm,ebc"; compatible = "ibm,ebc-440spe", "ibm,ebc-440gp", "ibm,ebc";
...@@ -153,38 +153,38 @@ EBC0: ebc { ...@@ -153,38 +153,38 @@ EBC0: ebc {
}; };
UART0: serial@10000200 { UART0: serial@10000200 {
device_type = "serial"; device_type = "serial";
compatible = "ns16550"; compatible = "ns16550";
reg = <10000200 8>; reg = <10000200 8>;
virtual-reg = <a0000200>; virtual-reg = <a0000200>;
clock-frequency = <0>; /* Filled in by zImage */ clock-frequency = <0>; /* Filled in by zImage */
current-speed = <1c200>; current-speed = <1c200>;
interrupt-parent = <&UIC0>; interrupt-parent = <&UIC0>;
interrupts = <0 4>; interrupts = <0 4>;
}; };
UART1: serial@10000300 { UART1: serial@10000300 {
device_type = "serial"; device_type = "serial";
compatible = "ns16550"; compatible = "ns16550";
reg = <10000300 8>; reg = <10000300 8>;
virtual-reg = <a0000300>; virtual-reg = <a0000300>;
clock-frequency = <0>; clock-frequency = <0>;
current-speed = <0>; current-speed = <0>;
interrupt-parent = <&UIC0>; interrupt-parent = <&UIC0>;
interrupts = <1 4>; interrupts = <1 4>;
}; };
UART2: serial@10000600 { UART2: serial@10000600 {
device_type = "serial"; device_type = "serial";
compatible = "ns16550"; compatible = "ns16550";
reg = <10000600 8>; reg = <10000600 8>;
virtual-reg = <a0000600>; virtual-reg = <a0000600>;
clock-frequency = <0>; clock-frequency = <0>;
current-speed = <0>; current-speed = <0>;
interrupt-parent = <&UIC1>; interrupt-parent = <&UIC1>;
interrupts = <5 4>; interrupts = <5 4>;
}; };
IIC0: i2c@10000400 { IIC0: i2c@10000400 {
compatible = "ibm,iic-440spe", "ibm,iic-440gp", "ibm,iic"; compatible = "ibm,iic-440spe", "ibm,iic-440gp", "ibm,iic";
......
...@@ -1151,7 +1151,7 @@ static void cell_handle_interrupt(struct pt_regs *regs, ...@@ -1151,7 +1151,7 @@ static void cell_handle_interrupt(struct pt_regs *regs,
for (i = 0; i < num_counters; ++i) { for (i = 0; i < num_counters; ++i) {
if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(i)) if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(i))
&& ctr[i].enabled) { && ctr[i].enabled) {
oprofile_add_pc(pc, is_kernel, i); oprofile_add_ext_sample(pc, regs, i, is_kernel);
cbe_write_ctr(cpu, i, reset_value[i]); cbe_write_ctr(cpu, i, reset_value[i]);
} }
} }
......
...@@ -199,6 +199,7 @@ int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv) ...@@ -199,6 +199,7 @@ int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv)
return 0; return 0;
} }
EXPORT_SYMBOL(mpc52xx_set_psc_clkdiv);
/** /**
* mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer
......
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
/* IOMMU sizing */ /* IOMMU sizing */
#define IO_SEGMENT_SHIFT 28 #define IO_SEGMENT_SHIFT 28
#define IO_PAGENO_BITS (IO_SEGMENT_SHIFT - IOMMU_PAGE_SHIFT) #define IO_PAGENO_BITS(shift) (IO_SEGMENT_SHIFT - (shift))
/* The high bit needs to be set on every DMA address */ /* The high bit needs to be set on every DMA address */
#define SPIDER_DMA_OFFSET 0x80000000ul #define SPIDER_DMA_OFFSET 0x80000000ul
...@@ -123,7 +123,6 @@ struct iommu_window { ...@@ -123,7 +123,6 @@ struct iommu_window {
struct cbe_iommu *iommu; struct cbe_iommu *iommu;
unsigned long offset; unsigned long offset;
unsigned long size; unsigned long size;
unsigned long pte_offset;
unsigned int ioid; unsigned int ioid;
struct iommu_table table; struct iommu_table table;
}; };
...@@ -200,7 +199,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages, ...@@ -200,7 +199,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
(window->ioid & IOPTE_IOID_Mask); (window->ioid & IOPTE_IOID_Mask);
#endif #endif
io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset); io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
for (i = 0; i < npages; i++, uaddr += IOMMU_PAGE_SIZE) for (i = 0; i < npages; i++, uaddr += IOMMU_PAGE_SIZE)
io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask); io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask);
...@@ -232,7 +231,7 @@ static void tce_free_cell(struct iommu_table *tbl, long index, long npages) ...@@ -232,7 +231,7 @@ static void tce_free_cell(struct iommu_table *tbl, long index, long npages)
| (window->ioid & IOPTE_IOID_Mask); | (window->ioid & IOPTE_IOID_Mask);
#endif #endif
io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset); io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
for (i = 0; i < npages; i++) for (i = 0; i < npages; i++)
io_pte[i] = pte; io_pte[i] = pte;
...@@ -307,76 +306,84 @@ static int cell_iommu_find_ioc(int nid, unsigned long *base) ...@@ -307,76 +306,84 @@ static int cell_iommu_find_ioc(int nid, unsigned long *base)
return -ENODEV; return -ENODEV;
} }
static void cell_iommu_setup_page_tables(struct cbe_iommu *iommu, static void cell_iommu_setup_stab(struct cbe_iommu *iommu,
unsigned long dbase, unsigned long dsize, unsigned long dbase, unsigned long dsize,
unsigned long fbase, unsigned long fsize) unsigned long fbase, unsigned long fsize)
{ {
struct page *page; struct page *page;
int i; unsigned long segments, stab_size;
unsigned long reg, segments, pages_per_segment, ptab_size, stab_size,
n_pte_pages, base;
base = dbase;
if (fsize != 0)
base = min(fbase, dbase);
segments = max(dbase + dsize, fbase + fsize) >> IO_SEGMENT_SHIFT; segments = max(dbase + dsize, fbase + fsize) >> IO_SEGMENT_SHIFT;
pages_per_segment = 1ull << IO_PAGENO_BITS;
pr_debug("%s: iommu[%d]: segments: %lu, pages per segment: %lu\n", pr_debug("%s: iommu[%d]: segments: %lu\n",
__FUNCTION__, iommu->nid, segments, pages_per_segment); __FUNCTION__, iommu->nid, segments);
/* set up the segment table */ /* set up the segment table */
stab_size = segments * sizeof(unsigned long); stab_size = segments * sizeof(unsigned long);
page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(stab_size)); page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(stab_size));
BUG_ON(!page); BUG_ON(!page);
iommu->stab = page_address(page); iommu->stab = page_address(page);
clear_page(iommu->stab); memset(iommu->stab, 0, stab_size);
}
static unsigned long *cell_iommu_alloc_ptab(struct cbe_iommu *iommu,
unsigned long base, unsigned long size, unsigned long gap_base,
unsigned long gap_size, unsigned long page_shift)
{
struct page *page;
int i;
unsigned long reg, segments, pages_per_segment, ptab_size,
n_pte_pages, start_seg, *ptab;
start_seg = base >> IO_SEGMENT_SHIFT;
segments = size >> IO_SEGMENT_SHIFT;
pages_per_segment = 1ull << IO_PAGENO_BITS(page_shift);
/* PTEs for each segment must start on a 4K bounday */
pages_per_segment = max(pages_per_segment,
(1 << 12) / sizeof(unsigned long));
/* ... and the page tables. Since these are contiguous, we can treat
* the page tables as one array of ptes, like pSeries does.
*/
ptab_size = segments * pages_per_segment * sizeof(unsigned long); ptab_size = segments * pages_per_segment * sizeof(unsigned long);
pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __FUNCTION__, pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __FUNCTION__,
iommu->nid, ptab_size, get_order(ptab_size)); iommu->nid, ptab_size, get_order(ptab_size));
page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(ptab_size)); page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(ptab_size));
BUG_ON(!page); BUG_ON(!page);
iommu->ptab = page_address(page); ptab = page_address(page);
memset(iommu->ptab, 0, ptab_size); memset(ptab, 0, ptab_size);
/* allocate a bogus page for the end of each mapping */ /* number of 4K pages needed for a page table */
page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0); n_pte_pages = (pages_per_segment * sizeof(unsigned long)) >> 12;
BUG_ON(!page);
iommu->pad_page = page_address(page);
clear_page(iommu->pad_page);
/* number of pages needed for a page table */
n_pte_pages = (pages_per_segment *
sizeof(unsigned long)) >> IOMMU_PAGE_SHIFT;
pr_debug("%s: iommu[%d]: stab at %p, ptab at %p, n_pte_pages: %lu\n", pr_debug("%s: iommu[%d]: stab at %p, ptab at %p, n_pte_pages: %lu\n",
__FUNCTION__, iommu->nid, iommu->stab, iommu->ptab, __FUNCTION__, iommu->nid, iommu->stab, ptab,
n_pte_pages); n_pte_pages);
/* initialise the STEs */ /* initialise the STEs */
reg = IOSTE_V | ((n_pte_pages - 1) << 5); reg = IOSTE_V | ((n_pte_pages - 1) << 5);
if (IOMMU_PAGE_SIZE == 0x1000) switch (page_shift) {
reg |= IOSTE_PS_4K; case 12: reg |= IOSTE_PS_4K; break;
else if (IOMMU_PAGE_SIZE == 0x10000) case 16: reg |= IOSTE_PS_64K; break;
reg |= IOSTE_PS_64K; case 20: reg |= IOSTE_PS_1M; break;
else { case 24: reg |= IOSTE_PS_16M; break;
extern void __unknown_page_size_error(void); default: BUG();
__unknown_page_size_error();
} }
gap_base = gap_base >> IO_SEGMENT_SHIFT;
gap_size = gap_size >> IO_SEGMENT_SHIFT;
pr_debug("Setting up IOMMU stab:\n"); pr_debug("Setting up IOMMU stab:\n");
for (i = base >> IO_SEGMENT_SHIFT; i < segments; i++) { for (i = start_seg; i < (start_seg + segments); i++) {
iommu->stab[i] = reg | if (i >= gap_base && i < (gap_base + gap_size)) {
(__pa(iommu->ptab) + n_pte_pages * IOMMU_PAGE_SIZE * i); pr_debug("\toverlap at %d, skipping\n", i);
continue;
}
iommu->stab[i] = reg | (__pa(ptab) + (n_pte_pages << 12) *
(i - start_seg));
pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]); pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]);
} }
return ptab;
} }
static void cell_iommu_enable_hardware(struct cbe_iommu *iommu) static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
...@@ -423,7 +430,9 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu) ...@@ -423,7 +430,9 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, static void cell_iommu_setup_hardware(struct cbe_iommu *iommu,
unsigned long base, unsigned long size) unsigned long base, unsigned long size)
{ {
cell_iommu_setup_page_tables(iommu, base, size, 0, 0); cell_iommu_setup_stab(iommu, base, size, 0, 0);
iommu->ptab = cell_iommu_alloc_ptab(iommu, base, size, 0, 0,
IOMMU_PAGE_SHIFT);
cell_iommu_enable_hardware(iommu); cell_iommu_enable_hardware(iommu);
} }
...@@ -464,6 +473,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, ...@@ -464,6 +473,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
unsigned long pte_offset) unsigned long pte_offset)
{ {
struct iommu_window *window; struct iommu_window *window;
struct page *page;
u32 ioid; u32 ioid;
ioid = cell_iommu_get_ioid(np); ioid = cell_iommu_get_ioid(np);
...@@ -475,13 +485,11 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, ...@@ -475,13 +485,11 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
window->size = size; window->size = size;
window->ioid = ioid; window->ioid = ioid;
window->iommu = iommu; window->iommu = iommu;
window->pte_offset = pte_offset;
window->table.it_blocksize = 16; window->table.it_blocksize = 16;
window->table.it_base = (unsigned long)iommu->ptab; window->table.it_base = (unsigned long)iommu->ptab;
window->table.it_index = iommu->nid; window->table.it_index = iommu->nid;
window->table.it_offset = (offset >> IOMMU_PAGE_SHIFT) + window->table.it_offset = (offset >> IOMMU_PAGE_SHIFT) + pte_offset;
window->pte_offset;
window->table.it_size = size >> IOMMU_PAGE_SHIFT; window->table.it_size = size >> IOMMU_PAGE_SHIFT;
iommu_init_table(&window->table, iommu->nid); iommu_init_table(&window->table, iommu->nid);
...@@ -504,6 +512,11 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, ...@@ -504,6 +512,11 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
* This code also assumes that we have a window that starts at 0, * This code also assumes that we have a window that starts at 0,
* which is the case on all spider based blades. * which is the case on all spider based blades.
*/ */
page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0);
BUG_ON(!page);
iommu->pad_page = page_address(page);
clear_page(iommu->pad_page);
__set_bit(0, window->table.it_map); __set_bit(0, window->table.it_map);
tce_build_cell(&window->table, window->table.it_offset, 1, tce_build_cell(&window->table, window->table.it_offset, 1,
(unsigned long)iommu->pad_page, DMA_TO_DEVICE); (unsigned long)iommu->pad_page, DMA_TO_DEVICE);
...@@ -549,7 +562,7 @@ static void cell_dma_dev_setup_iommu(struct device *dev) ...@@ -549,7 +562,7 @@ static void cell_dma_dev_setup_iommu(struct device *dev)
archdata->dma_data = &window->table; archdata->dma_data = &window->table;
} }
static void cell_dma_dev_setup_static(struct device *dev); static void cell_dma_dev_setup_fixed(struct device *dev);
static void cell_dma_dev_setup(struct device *dev) static void cell_dma_dev_setup(struct device *dev)
{ {
...@@ -557,7 +570,7 @@ static void cell_dma_dev_setup(struct device *dev) ...@@ -557,7 +570,7 @@ static void cell_dma_dev_setup(struct device *dev)
/* Order is important here, these are not mutually exclusive */ /* Order is important here, these are not mutually exclusive */
if (get_dma_ops(dev) == &dma_iommu_fixed_ops) if (get_dma_ops(dev) == &dma_iommu_fixed_ops)
cell_dma_dev_setup_static(dev); cell_dma_dev_setup_fixed(dev);
else if (get_pci_dma_ops() == &dma_iommu_ops) else if (get_pci_dma_ops() == &dma_iommu_ops)
cell_dma_dev_setup_iommu(dev); cell_dma_dev_setup_iommu(dev);
else if (get_pci_dma_ops() == &dma_direct_ops) else if (get_pci_dma_ops() == &dma_direct_ops)
...@@ -858,7 +871,7 @@ static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask) ...@@ -858,7 +871,7 @@ static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask)
return 0; return 0;
} }
static void cell_dma_dev_setup_static(struct device *dev) static void cell_dma_dev_setup_fixed(struct device *dev)
{ {
struct dev_archdata *archdata = &dev->archdata; struct dev_archdata *archdata = &dev->archdata;
u64 addr; u64 addr;
...@@ -869,35 +882,45 @@ static void cell_dma_dev_setup_static(struct device *dev) ...@@ -869,35 +882,45 @@ static void cell_dma_dev_setup_static(struct device *dev)
dev_dbg(dev, "iommu: fixed addr = %lx\n", addr); dev_dbg(dev, "iommu: fixed addr = %lx\n", addr);
} }
static void insert_16M_pte(unsigned long addr, unsigned long *ptab,
unsigned long base_pte)
{
unsigned long segment, offset;
segment = addr >> IO_SEGMENT_SHIFT;
offset = (addr >> 24) - (segment << IO_PAGENO_BITS(24));
ptab = ptab + (segment * (1 << 12) / sizeof(unsigned long));
pr_debug("iommu: addr %lx ptab %p segment %lx offset %lx\n",
addr, ptab, segment, offset);
ptab[offset] = base_pte | (__pa(addr) & IOPTE_RPN_Mask);
}
static void cell_iommu_setup_fixed_ptab(struct cbe_iommu *iommu, static void cell_iommu_setup_fixed_ptab(struct cbe_iommu *iommu,
struct device_node *np, unsigned long dbase, unsigned long dsize, struct device_node *np, unsigned long dbase, unsigned long dsize,
unsigned long fbase, unsigned long fsize) unsigned long fbase, unsigned long fsize)
{ {
unsigned long base_pte, uaddr, *io_pte; unsigned long base_pte, uaddr, ioaddr, *ptab;
int i;
dma_iommu_fixed_base = fbase; ptab = cell_iommu_alloc_ptab(iommu, fbase, fsize, dbase, dsize, 24);
/* convert from bytes into page table indices */ dma_iommu_fixed_base = fbase;
dbase = dbase >> IOMMU_PAGE_SHIFT;
dsize = dsize >> IOMMU_PAGE_SHIFT;
fbase = fbase >> IOMMU_PAGE_SHIFT;
fsize = fsize >> IOMMU_PAGE_SHIFT;
pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase); pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
io_pte = iommu->ptab;
base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW
| (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask); | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
uaddr = 0; for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) {
for (i = fbase; i < fbase + fsize; i++, uaddr += IOMMU_PAGE_SIZE) {
/* Don't touch the dynamic region */ /* Don't touch the dynamic region */
if (i >= dbase && i < (dbase + dsize)) { ioaddr = uaddr + fbase;
pr_debug("iommu: static/dynamic overlap, skipping\n"); if (ioaddr >= dbase && ioaddr < (dbase + dsize)) {
pr_debug("iommu: fixed/dynamic overlap, skipping\n");
continue; continue;
} }
io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask);
insert_16M_pte(uaddr, ptab, base_pte);
} }
mb(); mb();
...@@ -995,7 +1018,9 @@ static int __init cell_iommu_fixed_mapping_init(void) ...@@ -995,7 +1018,9 @@ static int __init cell_iommu_fixed_mapping_init(void)
"fixed window 0x%lx-0x%lx\n", iommu->nid, dbase, "fixed window 0x%lx-0x%lx\n", iommu->nid, dbase,
dbase + dsize, fbase, fbase + fsize); dbase + dsize, fbase, fbase + fsize);
cell_iommu_setup_page_tables(iommu, dbase, dsize, fbase, fsize); cell_iommu_setup_stab(iommu, dbase, dsize, fbase, fsize);
iommu->ptab = cell_iommu_alloc_ptab(iommu, dbase, dsize, 0, 0,
IOMMU_PAGE_SHIFT);
cell_iommu_setup_fixed_ptab(iommu, np, dbase, dsize, cell_iommu_setup_fixed_ptab(iommu, np, dbase, dsize,
fbase, fsize); fbase, fsize);
cell_iommu_enable_hardware(iommu); cell_iommu_enable_hardware(iommu);
......
...@@ -149,6 +149,11 @@ static void __init cell_init_irq(void) ...@@ -149,6 +149,11 @@ static void __init cell_init_irq(void)
mpic_init_IRQ(); mpic_init_IRQ();
} }
static void __init cell_set_dabrx(void)
{
mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
}
static void __init cell_setup_arch(void) static void __init cell_setup_arch(void)
{ {
#ifdef CONFIG_SPU_BASE #ifdef CONFIG_SPU_BASE
...@@ -158,6 +163,8 @@ static void __init cell_setup_arch(void) ...@@ -158,6 +163,8 @@ static void __init cell_setup_arch(void)
cbe_regs_init(); cbe_regs_init();
cell_set_dabrx();
#ifdef CONFIG_CBE_RAS #ifdef CONFIG_CBE_RAS
cbe_ras_init(); cbe_ras_init();
#endif #endif
......
...@@ -81,9 +81,12 @@ struct spu_slb { ...@@ -81,9 +81,12 @@ struct spu_slb {
void spu_invalidate_slbs(struct spu *spu) void spu_invalidate_slbs(struct spu *spu)
{ {
struct spu_priv2 __iomem *priv2 = spu->priv2; struct spu_priv2 __iomem *priv2 = spu->priv2;
unsigned long flags;
spin_lock_irqsave(&spu->register_lock, flags);
if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK) if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK)
out_be64(&priv2->slb_invalidate_all_W, 0UL); out_be64(&priv2->slb_invalidate_all_W, 0UL);
spin_unlock_irqrestore(&spu->register_lock, flags);
} }
EXPORT_SYMBOL_GPL(spu_invalidate_slbs); EXPORT_SYMBOL_GPL(spu_invalidate_slbs);
...@@ -148,7 +151,11 @@ static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb) ...@@ -148,7 +151,11 @@ static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
__func__, slbe, slb->vsid, slb->esid); __func__, slbe, slb->vsid, slb->esid);
out_be64(&priv2->slb_index_W, slbe); out_be64(&priv2->slb_index_W, slbe);
/* set invalid before writing vsid */
out_be64(&priv2->slb_esid_RW, 0);
/* now it's safe to write the vsid */
out_be64(&priv2->slb_vsid_RW, slb->vsid); out_be64(&priv2->slb_vsid_RW, slb->vsid);
/* setting the new esid makes the entry valid again */
out_be64(&priv2->slb_esid_RW, slb->esid); out_be64(&priv2->slb_esid_RW, slb->esid);
} }
...@@ -290,9 +297,11 @@ void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, ...@@ -290,9 +297,11 @@ void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
nr_slbs++; nr_slbs++;
} }
spin_lock_irq(&spu->register_lock);
/* Add the set of SLBs */ /* Add the set of SLBs */
for (i = 0; i < nr_slbs; i++) for (i = 0; i < nr_slbs; i++)
spu_load_slb(spu, i, &slbs[i]); spu_load_slb(spu, i, &slbs[i]);
spin_unlock_irq(&spu->register_lock);
} }
EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs); EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
...@@ -337,13 +346,14 @@ spu_irq_class_1(int irq, void *data) ...@@ -337,13 +346,14 @@ spu_irq_class_1(int irq, void *data)
if (stat & CLASS1_STORAGE_FAULT_INTR) if (stat & CLASS1_STORAGE_FAULT_INTR)
spu_mfc_dsisr_set(spu, 0ul); spu_mfc_dsisr_set(spu, 0ul);
spu_int_stat_clear(spu, 1, stat); spu_int_stat_clear(spu, 1, stat);
spin_unlock(&spu->register_lock);
pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
dar, dsisr);
if (stat & CLASS1_SEGMENT_FAULT_INTR) if (stat & CLASS1_SEGMENT_FAULT_INTR)
__spu_trap_data_seg(spu, dar); __spu_trap_data_seg(spu, dar);
spin_unlock(&spu->register_lock);
pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
dar, dsisr);
if (stat & CLASS1_STORAGE_FAULT_INTR) if (stat & CLASS1_STORAGE_FAULT_INTR)
__spu_trap_data_map(spu, dar, dsisr); __spu_trap_data_map(spu, dar, dsisr);
......
...@@ -109,13 +109,12 @@ void spu_forget(struct spu_context *ctx) ...@@ -109,13 +109,12 @@ void spu_forget(struct spu_context *ctx)
/* /*
* This is basically an open-coded spu_acquire_saved, except that * This is basically an open-coded spu_acquire_saved, except that
* we don't acquire the state mutex interruptible. * we don't acquire the state mutex interruptible, and we don't
* want this context to be rescheduled on release.
*/ */
mutex_lock(&ctx->state_mutex); mutex_lock(&ctx->state_mutex);
if (ctx->state != SPU_STATE_SAVED) { if (ctx->state != SPU_STATE_SAVED)
set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
spu_deactivate(ctx); spu_deactivate(ctx);
}
mm = ctx->owner; mm = ctx->owner;
ctx->owner = NULL; ctx->owner = NULL;
......
...@@ -366,6 +366,13 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, ...@@ -366,6 +366,13 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
if (offset >= ps_size) if (offset >= ps_size)
return NOPFN_SIGBUS; return NOPFN_SIGBUS;
/*
* Because we release the mmap_sem, the context may be destroyed while
* we're in spu_wait. Grab an extra reference so it isn't destroyed
* in the meantime.
*/
get_spu_context(ctx);
/* /*
* We have to wait for context to be loaded before we have * We have to wait for context to be loaded before we have
* pages to hand out to the user, but we don't want to wait * pages to hand out to the user, but we don't want to wait
...@@ -375,7 +382,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, ...@@ -375,7 +382,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
* hanged. * hanged.
*/ */
if (spu_acquire(ctx)) if (spu_acquire(ctx))
return NOPFN_REFAULT; goto refault;
if (ctx->state == SPU_STATE_SAVED) { if (ctx->state == SPU_STATE_SAVED) {
up_read(&current->mm->mmap_sem); up_read(&current->mm->mmap_sem);
...@@ -391,6 +398,9 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, ...@@ -391,6 +398,9 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
if (!ret) if (!ret)
spu_release(ctx); spu_release(ctx);
refault:
put_spu_context(ctx);
return NOPFN_REFAULT; return NOPFN_REFAULT;
} }
......
...@@ -246,7 +246,7 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) ...@@ -246,7 +246,7 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
spu_switch_notify(spu, ctx); spu_switch_notify(spu, ctx);
ctx->state = SPU_STATE_RUNNABLE; ctx->state = SPU_STATE_RUNNABLE;
spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED); spuctx_switch_state(ctx, SPU_UTIL_USER);
} }
/* /*
......
...@@ -58,12 +58,12 @@ static int sputrace_sprint(char *tbuf, int n) ...@@ -58,12 +58,12 @@ static int sputrace_sprint(char *tbuf, int n)
ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start)); ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start));
return snprintf(tbuf, n, return snprintf(tbuf, n,
"[%lu.%09lu] %d: %s (thread = %d, spu = %d)\n", "[%lu.%09lu] %d: %s (ctxthread = %d, spu = %d)\n",
(unsigned long) tv.tv_sec, (unsigned long) tv.tv_sec,
(unsigned long) tv.tv_nsec, (unsigned long) tv.tv_nsec,
t->owner_tid,
t->name,
t->curr_tid, t->curr_tid,
t->name,
t->owner_tid,
t->number); t->number);
} }
...@@ -188,6 +188,7 @@ struct spu_probe spu_probes[] = { ...@@ -188,6 +188,7 @@ struct spu_probe spu_probes[] = {
{ "spufs_ps_nopfn__insert", "%p %p", spu_context_event }, { "spufs_ps_nopfn__insert", "%p %p", spu_context_event },
{ "spu_acquire_saved__enter", "%p", spu_context_nospu_event }, { "spu_acquire_saved__enter", "%p", spu_context_nospu_event },
{ "destroy_spu_context__enter", "%p", spu_context_nospu_event }, { "destroy_spu_context__enter", "%p", spu_context_nospu_event },
{ "spufs_stop_callback__enter", "%p %p", spu_context_event },
}; };
static int __init sputrace_init(void) static int __init sputrace_init(void)
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/hardirq.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -117,6 +118,8 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu) ...@@ -117,6 +118,8 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu)
* Write INT_MASK_class1 with value of 0. * Write INT_MASK_class1 with value of 0.
* Save INT_Mask_class2 in CSA. * Save INT_Mask_class2 in CSA.
* Write INT_MASK_class2 with value of 0. * Write INT_MASK_class2 with value of 0.
* Synchronize all three interrupts to be sure
* we no longer execute a handler on another CPU.
*/ */
spin_lock_irq(&spu->register_lock); spin_lock_irq(&spu->register_lock);
if (csa) { if (csa) {
...@@ -129,6 +132,9 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu) ...@@ -129,6 +132,9 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu)
spu_int_mask_set(spu, 2, 0ul); spu_int_mask_set(spu, 2, 0ul);
eieio(); eieio();
spin_unlock_irq(&spu->register_lock); spin_unlock_irq(&spu->register_lock);
synchronize_irq(spu->irqs[0]);
synchronize_irq(spu->irqs[1]);
synchronize_irq(spu->irqs[2]);
} }
static inline void set_watchdog_timer(struct spu_state *csa, struct spu *spu) static inline void set_watchdog_timer(struct spu_state *csa, struct spu *spu)
......
...@@ -21,9 +21,6 @@ ...@@ -21,9 +21,6 @@
#ifndef _CELLEB_BEAT_H #ifndef _CELLEB_BEAT_H
#define _CELLEB_BEAT_H #define _CELLEB_BEAT_H
#define DABRX_KERNEL (1UL<<1)
#define DABRX_USER (1UL<<0)
int64_t beat_get_term_char(uint64_t,uint64_t*,uint64_t*,uint64_t*); int64_t beat_get_term_char(uint64_t,uint64_t*,uint64_t*,uint64_t*);
int64_t beat_put_term_char(uint64_t,uint64_t,uint64_t,uint64_t); int64_t beat_put_term_char(uint64_t,uint64_t,uint64_t,uint64_t);
int64_t beat_repository_encode(int, const char *, uint64_t[4]); int64_t beat_repository_encode(int, const char *, uint64_t[4]);
......
...@@ -73,8 +73,8 @@ ...@@ -73,8 +73,8 @@
#define XHI_BUFFER_START 0 #define XHI_BUFFER_START 0
/** /**
* buffer_icap_get_status: Get the contents of the status register. * buffer_icap_get_status - Get the contents of the status register.
* @parameter base_address: is the base address of the device * @base_address: is the base address of the device
* *
* The status register contains the ICAP status and the done bit. * The status register contains the ICAP status and the done bit.
* *
...@@ -94,9 +94,9 @@ static inline u32 buffer_icap_get_status(void __iomem *base_address) ...@@ -94,9 +94,9 @@ static inline u32 buffer_icap_get_status(void __iomem *base_address)
} }
/** /**
* buffer_icap_get_bram: Reads data from the storage buffer bram. * buffer_icap_get_bram - Reads data from the storage buffer bram.
* @parameter base_address: contains the base address of the component. * @base_address: contains the base address of the component.
* @parameter offset: The word offset from which the data should be read. * @offset: The word offset from which the data should be read.
* *
* A bram is used as a configuration memory cache. One frame of data can * A bram is used as a configuration memory cache. One frame of data can
* be stored in this "storage buffer". * be stored in this "storage buffer".
...@@ -108,8 +108,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address, ...@@ -108,8 +108,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address,
} }
/** /**
* buffer_icap_busy: Return true if the icap device is busy * buffer_icap_busy - Return true if the icap device is busy
* @parameter base_address: is the base address of the device * @base_address: is the base address of the device
* *
* The queries the low order bit of the status register, which * The queries the low order bit of the status register, which
* indicates whether the current configuration or readback operation * indicates whether the current configuration or readback operation
...@@ -121,8 +121,8 @@ static inline bool buffer_icap_busy(void __iomem *base_address) ...@@ -121,8 +121,8 @@ static inline bool buffer_icap_busy(void __iomem *base_address)
} }
/** /**
* buffer_icap_busy: Return true if the icap device is not busy * buffer_icap_busy - Return true if the icap device is not busy
* @parameter base_address: is the base address of the device * @base_address: is the base address of the device
* *
* The queries the low order bit of the status register, which * The queries the low order bit of the status register, which
* indicates whether the current configuration or readback operation * indicates whether the current configuration or readback operation
...@@ -134,9 +134,9 @@ static inline bool buffer_icap_done(void __iomem *base_address) ...@@ -134,9 +134,9 @@ static inline bool buffer_icap_done(void __iomem *base_address)
} }
/** /**
* buffer_icap_set_size: Set the size register. * buffer_icap_set_size - Set the size register.
* @parameter base_address: is the base address of the device * @base_address: is the base address of the device
* @parameter data: The size in bytes. * @data: The size in bytes.
* *
* The size register holds the number of 8 bit bytes to transfer between * The size register holds the number of 8 bit bytes to transfer between
* bram and the icap (or icap to bram). * bram and the icap (or icap to bram).
...@@ -148,9 +148,9 @@ static inline void buffer_icap_set_size(void __iomem *base_address, ...@@ -148,9 +148,9 @@ static inline void buffer_icap_set_size(void __iomem *base_address,
} }
/** /**
* buffer_icap_mSetoffsetReg: Set the bram offset register. * buffer_icap_set_offset - Set the bram offset register.
* @parameter base_address: contains the base address of the device. * @base_address: contains the base address of the device.
* @parameter data: is the value to be written to the data register. * @data: is the value to be written to the data register.
* *
* The bram offset register holds the starting bram address to transfer * The bram offset register holds the starting bram address to transfer
* data from during configuration or write data to during readback. * data from during configuration or write data to during readback.
...@@ -162,9 +162,9 @@ static inline void buffer_icap_set_offset(void __iomem *base_address, ...@@ -162,9 +162,9 @@ static inline void buffer_icap_set_offset(void __iomem *base_address,
} }
/** /**
* buffer_icap_set_rnc: Set the RNC (Readback not Configure) register. * buffer_icap_set_rnc - Set the RNC (Readback not Configure) register.
* @parameter base_address: contains the base address of the device. * @base_address: contains the base address of the device.
* @parameter data: is the value to be written to the data register. * @data: is the value to be written to the data register.
* *
* The RNC register determines the direction of the data transfer. It * The RNC register determines the direction of the data transfer. It
* controls whether a configuration or readback take place. Writing to * controls whether a configuration or readback take place. Writing to
...@@ -178,10 +178,10 @@ static inline void buffer_icap_set_rnc(void __iomem *base_address, ...@@ -178,10 +178,10 @@ static inline void buffer_icap_set_rnc(void __iomem *base_address,
} }
/** /**
* buffer_icap_set_bram: Write data to the storage buffer bram. * buffer_icap_set_bram - Write data to the storage buffer bram.
* @parameter base_address: contains the base address of the component. * @base_address: contains the base address of the component.
* @parameter offset: The word offset at which the data should be written. * @offset: The word offset at which the data should be written.
* @parameter data: The value to be written to the bram offset. * @data: The value to be written to the bram offset.
* *
* A bram is used as a configuration memory cache. One frame of data can * A bram is used as a configuration memory cache. One frame of data can
* be stored in this "storage buffer". * be stored in this "storage buffer".
...@@ -193,10 +193,10 @@ static inline void buffer_icap_set_bram(void __iomem *base_address, ...@@ -193,10 +193,10 @@ static inline void buffer_icap_set_bram(void __iomem *base_address,
} }
/** /**
* buffer_icap_device_read: Transfer bytes from ICAP to the storage buffer. * buffer_icap_device_read - Transfer bytes from ICAP to the storage buffer.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter offset: The storage buffer start address. * @offset: The storage buffer start address.
* @parameter count: The number of words (32 bit) to read from the * @count: The number of words (32 bit) to read from the
* device (ICAP). * device (ICAP).
**/ **/
static int buffer_icap_device_read(struct hwicap_drvdata *drvdata, static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,
...@@ -227,10 +227,10 @@ static int buffer_icap_device_read(struct hwicap_drvdata *drvdata, ...@@ -227,10 +227,10 @@ static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,
}; };
/** /**
* buffer_icap_device_write: Transfer bytes from ICAP to the storage buffer. * buffer_icap_device_write - Transfer bytes from ICAP to the storage buffer.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter offset: The storage buffer start address. * @offset: The storage buffer start address.
* @parameter count: The number of words (32 bit) to read from the * @count: The number of words (32 bit) to read from the
* device (ICAP). * device (ICAP).
**/ **/
static int buffer_icap_device_write(struct hwicap_drvdata *drvdata, static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,
...@@ -261,8 +261,8 @@ static int buffer_icap_device_write(struct hwicap_drvdata *drvdata, ...@@ -261,8 +261,8 @@ static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,
}; };
/** /**
* buffer_icap_reset: Reset the logic of the icap device. * buffer_icap_reset - Reset the logic of the icap device.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* *
* Writing to the status register resets the ICAP logic in an internal * Writing to the status register resets the ICAP logic in an internal
* version of the core. For the version of the core published in EDK, * version of the core. For the version of the core published in EDK,
...@@ -274,10 +274,10 @@ void buffer_icap_reset(struct hwicap_drvdata *drvdata) ...@@ -274,10 +274,10 @@ void buffer_icap_reset(struct hwicap_drvdata *drvdata)
} }
/** /**
* buffer_icap_set_configuration: Load a partial bitstream from system memory. * buffer_icap_set_configuration - Load a partial bitstream from system memory.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter data: Kernel address of the partial bitstream. * @data: Kernel address of the partial bitstream.
* @parameter size: the size of the partial bitstream in 32 bit words. * @size: the size of the partial bitstream in 32 bit words.
**/ **/
int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
u32 size) u32 size)
...@@ -333,10 +333,10 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, ...@@ -333,10 +333,10 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
}; };
/** /**
* buffer_icap_get_configuration: Read configuration data from the device. * buffer_icap_get_configuration - Read configuration data from the device.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter data: Address of the data representing the partial bitstream * @data: Address of the data representing the partial bitstream
* @parameter size: the size of the partial bitstream in 32 bit words. * @size: the size of the partial bitstream in 32 bit words.
**/ **/
int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data, int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
u32 size) u32 size)
......
...@@ -94,9 +94,9 @@ ...@@ -94,9 +94,9 @@
/** /**
* fifo_icap_fifo_write: Write data to the write FIFO. * fifo_icap_fifo_write - Write data to the write FIFO.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter data: the 32-bit value to be written to the FIFO. * @data: the 32-bit value to be written to the FIFO.
* *
* This function will silently fail if the fifo is full. * This function will silently fail if the fifo is full.
**/ **/
...@@ -108,8 +108,8 @@ static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata, ...@@ -108,8 +108,8 @@ static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata,
} }
/** /**
* fifo_icap_fifo_read: Read data from the Read FIFO. * fifo_icap_fifo_read - Read data from the Read FIFO.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* *
* This function will silently fail if the fifo is empty. * This function will silently fail if the fifo is empty.
**/ **/
...@@ -121,9 +121,9 @@ static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata) ...@@ -121,9 +121,9 @@ static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata)
} }
/** /**
* fifo_icap_set_read_size: Set the the size register. * fifo_icap_set_read_size - Set the the size register.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter data: the size of the following read transaction, in words. * @data: the size of the following read transaction, in words.
**/ **/
static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata, static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata,
u32 data) u32 data)
...@@ -132,8 +132,8 @@ static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata, ...@@ -132,8 +132,8 @@ static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata,
} }
/** /**
* fifo_icap_start_config: Initiate a configuration (write) to the device. * fifo_icap_start_config - Initiate a configuration (write) to the device.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
**/ **/
static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata) static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata)
{ {
...@@ -142,8 +142,8 @@ static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata) ...@@ -142,8 +142,8 @@ static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata)
} }
/** /**
* fifo_icap_start_readback: Initiate a readback from the device. * fifo_icap_start_readback - Initiate a readback from the device.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
**/ **/
static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata) static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
{ {
...@@ -152,8 +152,8 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata) ...@@ -152,8 +152,8 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
} }
/** /**
* fifo_icap_busy: Return true if the ICAP is still processing a transaction. * fifo_icap_busy - Return true if the ICAP is still processing a transaction.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
**/ **/
static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
{ {
...@@ -163,8 +163,8 @@ static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) ...@@ -163,8 +163,8 @@ static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
} }
/** /**
* fifo_icap_write_fifo_vacancy: Query the write fifo available space. * fifo_icap_write_fifo_vacancy - Query the write fifo available space.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* *
* Return the number of words that can be safely pushed into the write fifo. * Return the number of words that can be safely pushed into the write fifo.
**/ **/
...@@ -175,8 +175,8 @@ static inline u32 fifo_icap_write_fifo_vacancy( ...@@ -175,8 +175,8 @@ static inline u32 fifo_icap_write_fifo_vacancy(
} }
/** /**
* fifo_icap_read_fifo_occupancy: Query the read fifo available data. * fifo_icap_read_fifo_occupancy - Query the read fifo available data.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* *
* Return the number of words that can be safely read from the read fifo. * Return the number of words that can be safely read from the read fifo.
**/ **/
...@@ -187,11 +187,11 @@ static inline u32 fifo_icap_read_fifo_occupancy( ...@@ -187,11 +187,11 @@ static inline u32 fifo_icap_read_fifo_occupancy(
} }
/** /**
* fifo_icap_set_configuration: Send configuration data to the ICAP. * fifo_icap_set_configuration - Send configuration data to the ICAP.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter frame_buffer: a pointer to the data to be written to the * @frame_buffer: a pointer to the data to be written to the
* ICAP device. * ICAP device.
* @parameter num_words: the number of words (32 bit) to write to the ICAP * @num_words: the number of words (32 bit) to write to the ICAP
* device. * device.
* This function writes the given user data to the Write FIFO in * This function writes the given user data to the Write FIFO in
...@@ -266,10 +266,10 @@ int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata, ...@@ -266,10 +266,10 @@ int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,
} }
/** /**
* fifo_icap_get_configuration: Read configuration data from the device. * fifo_icap_get_configuration - Read configuration data from the device.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* @parameter data: Address of the data representing the partial bitstream * @data: Address of the data representing the partial bitstream
* @parameter size: the size of the partial bitstream in 32 bit words. * @size: the size of the partial bitstream in 32 bit words.
* *
* This function reads the specified number of words from the ICAP device in * This function reads the specified number of words from the ICAP device in
* the polled mode. * the polled mode.
...@@ -335,8 +335,8 @@ int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata, ...@@ -335,8 +335,8 @@ int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,
} }
/** /**
* buffer_icap_reset: Reset the logic of the icap device. * buffer_icap_reset - Reset the logic of the icap device.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* *
* This function forces the software reset of the complete HWICAP device. * This function forces the software reset of the complete HWICAP device.
* All the registers will return to the default value and the FIFO is also * All the registers will return to the default value and the FIFO is also
...@@ -360,8 +360,8 @@ void fifo_icap_reset(struct hwicap_drvdata *drvdata) ...@@ -360,8 +360,8 @@ void fifo_icap_reset(struct hwicap_drvdata *drvdata)
} }
/** /**
* fifo_icap_flush_fifo: This function flushes the FIFOs in the device. * fifo_icap_flush_fifo - This function flushes the FIFOs in the device.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
*/ */
void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata) void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata)
{ {
......
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <asm/semaphore.h> #include <linux/mutex.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/fs.h> #include <linux/fs.h>
...@@ -119,6 +119,7 @@ module_param(xhwicap_minor, int, S_IRUGO); ...@@ -119,6 +119,7 @@ module_param(xhwicap_minor, int, S_IRUGO);
/* An array, which is set to true when the device is registered. */ /* An array, which is set to true when the device is registered. */
static bool probed_devices[HWICAP_DEVICES]; static bool probed_devices[HWICAP_DEVICES];
static struct mutex icap_sem;
static struct class *icap_class; static struct class *icap_class;
...@@ -199,14 +200,14 @@ static const struct config_registers v5_config_registers = { ...@@ -199,14 +200,14 @@ static const struct config_registers v5_config_registers = {
}; };
/** /**
* hwicap_command_desync: Send a DESYNC command to the ICAP port. * hwicap_command_desync - Send a DESYNC command to the ICAP port.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* *
* This command desynchronizes the ICAP After this command, a * This command desynchronizes the ICAP After this command, a
* bitstream containing a NULL packet, followed by a SYNCH packet is * bitstream containing a NULL packet, followed by a SYNCH packet is
* required before the ICAP will recognize commands. * required before the ICAP will recognize commands.
*/ */
int hwicap_command_desync(struct hwicap_drvdata *drvdata) static int hwicap_command_desync(struct hwicap_drvdata *drvdata)
{ {
u32 buffer[4]; u32 buffer[4];
u32 index = 0; u32 index = 0;
...@@ -228,51 +229,18 @@ int hwicap_command_desync(struct hwicap_drvdata *drvdata) ...@@ -228,51 +229,18 @@ int hwicap_command_desync(struct hwicap_drvdata *drvdata)
} }
/** /**
* hwicap_command_capture: Send a CAPTURE command to the ICAP port. * hwicap_get_configuration_register - Query a configuration register.
* @parameter drvdata: a pointer to the drvdata. * @drvdata: a pointer to the drvdata.
* * @reg: a constant which represents the configuration
* This command captures all of the flip flop states so they will be
* available during readback. One can use this command instead of
* enabling the CAPTURE block in the design.
*/
int hwicap_command_capture(struct hwicap_drvdata *drvdata)
{
u32 buffer[7];
u32 index = 0;
/*
* Create the data to be written to the ICAP.
*/
buffer[index++] = XHI_DUMMY_PACKET;
buffer[index++] = XHI_SYNC_PACKET;
buffer[index++] = XHI_NOOP_PACKET;
buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;
buffer[index++] = XHI_CMD_GCAPTURE;
buffer[index++] = XHI_DUMMY_PACKET;
buffer[index++] = XHI_DUMMY_PACKET;
/*
* Write the data to the FIFO and intiate the transfer of data
* present in the FIFO to the ICAP device.
*/
return drvdata->config->set_configuration(drvdata,
&buffer[0], index);
}
/**
* hwicap_get_configuration_register: Query a configuration register.
* @parameter drvdata: a pointer to the drvdata.
* @parameter reg: a constant which represents the configuration
* register value to be returned. * register value to be returned.
* Examples: XHI_IDCODE, XHI_FLR. * Examples: XHI_IDCODE, XHI_FLR.
* @parameter RegData: returns the value of the register. * @reg_data: returns the value of the register.
* *
* Sends a query packet to the ICAP and then receives the response. * Sends a query packet to the ICAP and then receives the response.
* The icap is left in Synched state. * The icap is left in Synched state.
*/ */
int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
u32 reg, u32 *RegData) u32 reg, u32 *reg_data)
{ {
int status; int status;
u32 buffer[6]; u32 buffer[6];
...@@ -300,14 +268,14 @@ int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, ...@@ -300,14 +268,14 @@ int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
/* /*
* Read the configuration register * Read the configuration register
*/ */
status = drvdata->config->get_configuration(drvdata, RegData, 1); status = drvdata->config->get_configuration(drvdata, reg_data, 1);
if (status) if (status)
return status; return status;
return 0; return 0;
} }
int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata) static int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata)
{ {
int status; int status;
u32 idcode; u32 idcode;
...@@ -344,7 +312,7 @@ int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata) ...@@ -344,7 +312,7 @@ int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata)
} }
static ssize_t static ssize_t
hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) hwicap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{ {
struct hwicap_drvdata *drvdata = file->private_data; struct hwicap_drvdata *drvdata = file->private_data;
ssize_t bytes_to_read = 0; ssize_t bytes_to_read = 0;
...@@ -353,8 +321,9 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -353,8 +321,9 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos)
u32 bytes_remaining; u32 bytes_remaining;
int status; int status;
if (down_interruptible(&drvdata->sem)) status = mutex_lock_interruptible(&drvdata->sem);
return -ERESTARTSYS; if (status)
return status;
if (drvdata->read_buffer_in_use) { if (drvdata->read_buffer_in_use) {
/* If there are leftover bytes in the buffer, just */ /* If there are leftover bytes in the buffer, just */
...@@ -370,8 +339,9 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -370,8 +339,9 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos)
goto error; goto error;
} }
drvdata->read_buffer_in_use -= bytes_to_read; drvdata->read_buffer_in_use -= bytes_to_read;
memcpy(drvdata->read_buffer + bytes_to_read, memmove(drvdata->read_buffer,
drvdata->read_buffer, 4 - bytes_to_read); drvdata->read_buffer + bytes_to_read,
4 - bytes_to_read);
} else { } else {
/* Get new data from the ICAP, and return was was requested. */ /* Get new data from the ICAP, and return was was requested. */
kbuf = (u32 *) get_zeroed_page(GFP_KERNEL); kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);
...@@ -414,18 +384,20 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -414,18 +384,20 @@ hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos)
status = -EFAULT; status = -EFAULT;
goto error; goto error;
} }
memcpy(kbuf, drvdata->read_buffer, bytes_remaining); memcpy(drvdata->read_buffer,
kbuf,
bytes_remaining);
drvdata->read_buffer_in_use = bytes_remaining; drvdata->read_buffer_in_use = bytes_remaining;
free_page((unsigned long)kbuf); free_page((unsigned long)kbuf);
} }
status = bytes_to_read; status = bytes_to_read;
error: error:
up(&drvdata->sem); mutex_unlock(&drvdata->sem);
return status; return status;
} }
static ssize_t static ssize_t
hwicap_write(struct file *file, const char *buf, hwicap_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct hwicap_drvdata *drvdata = file->private_data; struct hwicap_drvdata *drvdata = file->private_data;
...@@ -435,8 +407,9 @@ hwicap_write(struct file *file, const char *buf, ...@@ -435,8 +407,9 @@ hwicap_write(struct file *file, const char *buf,
ssize_t len; ssize_t len;
ssize_t status; ssize_t status;
if (down_interruptible(&drvdata->sem)) status = mutex_lock_interruptible(&drvdata->sem);
return -ERESTARTSYS; if (status)
return status;
left += drvdata->write_buffer_in_use; left += drvdata->write_buffer_in_use;
...@@ -465,7 +438,7 @@ hwicap_write(struct file *file, const char *buf, ...@@ -465,7 +438,7 @@ hwicap_write(struct file *file, const char *buf,
memcpy(kbuf, drvdata->write_buffer, memcpy(kbuf, drvdata->write_buffer,
drvdata->write_buffer_in_use); drvdata->write_buffer_in_use);
if (copy_from_user( if (copy_from_user(
(((char *)kbuf) + (drvdata->write_buffer_in_use)), (((char *)kbuf) + drvdata->write_buffer_in_use),
buf + written, buf + written,
len - (drvdata->write_buffer_in_use))) { len - (drvdata->write_buffer_in_use))) {
free_page((unsigned long)kbuf); free_page((unsigned long)kbuf);
...@@ -508,7 +481,7 @@ hwicap_write(struct file *file, const char *buf, ...@@ -508,7 +481,7 @@ hwicap_write(struct file *file, const char *buf,
free_page((unsigned long)kbuf); free_page((unsigned long)kbuf);
status = written; status = written;
error: error:
up(&drvdata->sem); mutex_unlock(&drvdata->sem);
return status; return status;
} }
...@@ -519,8 +492,9 @@ static int hwicap_open(struct inode *inode, struct file *file) ...@@ -519,8 +492,9 @@ static int hwicap_open(struct inode *inode, struct file *file)
drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev); drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
if (down_interruptible(&drvdata->sem)) status = mutex_lock_interruptible(&drvdata->sem);
return -ERESTARTSYS; if (status)
return status;
if (drvdata->is_open) { if (drvdata->is_open) {
status = -EBUSY; status = -EBUSY;
...@@ -539,7 +513,7 @@ static int hwicap_open(struct inode *inode, struct file *file) ...@@ -539,7 +513,7 @@ static int hwicap_open(struct inode *inode, struct file *file)
drvdata->is_open = 1; drvdata->is_open = 1;
error: error:
up(&drvdata->sem); mutex_unlock(&drvdata->sem);
return status; return status;
} }
...@@ -549,8 +523,7 @@ static int hwicap_release(struct inode *inode, struct file *file) ...@@ -549,8 +523,7 @@ static int hwicap_release(struct inode *inode, struct file *file)
int i; int i;
int status = 0; int status = 0;
if (down_interruptible(&drvdata->sem)) mutex_lock(&drvdata->sem);
return -ERESTARTSYS;
if (drvdata->write_buffer_in_use) { if (drvdata->write_buffer_in_use) {
/* Flush write buffer. */ /* Flush write buffer. */
...@@ -569,7 +542,7 @@ static int hwicap_release(struct inode *inode, struct file *file) ...@@ -569,7 +542,7 @@ static int hwicap_release(struct inode *inode, struct file *file)
error: error:
drvdata->is_open = 0; drvdata->is_open = 0;
up(&drvdata->sem); mutex_unlock(&drvdata->sem);
return status; return status;
} }
...@@ -592,31 +565,36 @@ static int __devinit hwicap_setup(struct device *dev, int id, ...@@ -592,31 +565,36 @@ static int __devinit hwicap_setup(struct device *dev, int id,
dev_info(dev, "Xilinx icap port driver\n"); dev_info(dev, "Xilinx icap port driver\n");
mutex_lock(&icap_sem);
if (id < 0) { if (id < 0) {
for (id = 0; id < HWICAP_DEVICES; id++) for (id = 0; id < HWICAP_DEVICES; id++)
if (!probed_devices[id]) if (!probed_devices[id])
break; break;
} }
if (id < 0 || id >= HWICAP_DEVICES) { if (id < 0 || id >= HWICAP_DEVICES) {
mutex_unlock(&icap_sem);
dev_err(dev, "%s%i too large\n", DRIVER_NAME, id); dev_err(dev, "%s%i too large\n", DRIVER_NAME, id);
return -EINVAL; return -EINVAL;
} }
if (probed_devices[id]) { if (probed_devices[id]) {
mutex_unlock(&icap_sem);
dev_err(dev, "cannot assign to %s%i; it is already in use\n", dev_err(dev, "cannot assign to %s%i; it is already in use\n",
DRIVER_NAME, id); DRIVER_NAME, id);
return -EBUSY; return -EBUSY;
} }
probed_devices[id] = 1; probed_devices[id] = 1;
mutex_unlock(&icap_sem);
devt = MKDEV(xhwicap_major, xhwicap_minor + id); devt = MKDEV(xhwicap_major, xhwicap_minor + id);
drvdata = kmalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL); drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
if (!drvdata) { if (!drvdata) {
dev_err(dev, "Couldn't allocate device private record\n"); dev_err(dev, "Couldn't allocate device private record\n");
return -ENOMEM; retval = -ENOMEM;
goto failed0;
} }
memset((void *)drvdata, 0, sizeof(struct hwicap_drvdata));
dev_set_drvdata(dev, (void *)drvdata); dev_set_drvdata(dev, (void *)drvdata);
if (!regs_res) { if (!regs_res) {
...@@ -648,7 +626,7 @@ static int __devinit hwicap_setup(struct device *dev, int id, ...@@ -648,7 +626,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
drvdata->config = config; drvdata->config = config;
drvdata->config_regs = config_regs; drvdata->config_regs = config_regs;
init_MUTEX(&drvdata->sem); mutex_init(&drvdata->sem);
drvdata->is_open = 0; drvdata->is_open = 0;
dev_info(dev, "ioremap %lx to %p with size %x\n", dev_info(dev, "ioremap %lx to %p with size %x\n",
...@@ -663,7 +641,7 @@ static int __devinit hwicap_setup(struct device *dev, int id, ...@@ -663,7 +641,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
goto failed3; goto failed3;
} }
/* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */ /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */
class_device_create(icap_class, NULL, devt, NULL, DRIVER_NAME); device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id);
return 0; /* success */ return 0; /* success */
failed3: failed3:
...@@ -675,6 +653,11 @@ static int __devinit hwicap_setup(struct device *dev, int id, ...@@ -675,6 +653,11 @@ static int __devinit hwicap_setup(struct device *dev, int id,
failed1: failed1:
kfree(drvdata); kfree(drvdata);
failed0:
mutex_lock(&icap_sem);
probed_devices[id] = 0;
mutex_unlock(&icap_sem);
return retval; return retval;
} }
...@@ -699,14 +682,16 @@ static int __devexit hwicap_remove(struct device *dev) ...@@ -699,14 +682,16 @@ static int __devexit hwicap_remove(struct device *dev)
if (!drvdata) if (!drvdata)
return 0; return 0;
class_device_destroy(icap_class, drvdata->devt); device_destroy(icap_class, drvdata->devt);
cdev_del(&drvdata->cdev); cdev_del(&drvdata->cdev);
iounmap(drvdata->base_address); iounmap(drvdata->base_address);
release_mem_region(drvdata->mem_start, drvdata->mem_size); release_mem_region(drvdata->mem_start, drvdata->mem_size);
kfree(drvdata); kfree(drvdata);
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;
mutex_lock(&icap_sem);
probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;
mutex_unlock(&icap_sem);
return 0; /* success */ return 0; /* success */
} }
...@@ -821,28 +806,29 @@ static struct of_platform_driver hwicap_of_driver = { ...@@ -821,28 +806,29 @@ static struct of_platform_driver hwicap_of_driver = {
}; };
/* Registration helpers to keep the number of #ifdefs to a minimum */ /* Registration helpers to keep the number of #ifdefs to a minimum */
static inline int __devinit hwicap_of_register(void) static inline int __init hwicap_of_register(void)
{ {
pr_debug("hwicap: calling of_register_platform_driver()\n"); pr_debug("hwicap: calling of_register_platform_driver()\n");
return of_register_platform_driver(&hwicap_of_driver); return of_register_platform_driver(&hwicap_of_driver);
} }
static inline void __devexit hwicap_of_unregister(void) static inline void __exit hwicap_of_unregister(void)
{ {
of_unregister_platform_driver(&hwicap_of_driver); of_unregister_platform_driver(&hwicap_of_driver);
} }
#else /* CONFIG_OF */ #else /* CONFIG_OF */
/* CONFIG_OF not enabled; do nothing helpers */ /* CONFIG_OF not enabled; do nothing helpers */
static inline int __devinit hwicap_of_register(void) { return 0; } static inline int __init hwicap_of_register(void) { return 0; }
static inline void __devexit hwicap_of_unregister(void) { } static inline void __exit hwicap_of_unregister(void) { }
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
static int __devinit hwicap_module_init(void) static int __init hwicap_module_init(void)
{ {
dev_t devt; dev_t devt;
int retval; int retval;
icap_class = class_create(THIS_MODULE, "xilinx_config"); icap_class = class_create(THIS_MODULE, "xilinx_config");
mutex_init(&icap_sem);
if (xhwicap_major) { if (xhwicap_major) {
devt = MKDEV(xhwicap_major, xhwicap_minor); devt = MKDEV(xhwicap_major, xhwicap_minor);
...@@ -883,7 +869,7 @@ static int __devinit hwicap_module_init(void) ...@@ -883,7 +869,7 @@ static int __devinit hwicap_module_init(void)
return retval; return retval;
} }
static void __devexit hwicap_module_cleanup(void) static void __exit hwicap_module_cleanup(void)
{ {
dev_t devt = MKDEV(xhwicap_major, xhwicap_minor); dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);
......
...@@ -48,9 +48,9 @@ struct hwicap_drvdata { ...@@ -48,9 +48,9 @@ struct hwicap_drvdata {
u8 write_buffer[4]; u8 write_buffer[4];
u32 read_buffer_in_use; /* Always in [0,3] */ u32 read_buffer_in_use; /* Always in [0,3] */
u8 read_buffer[4]; u8 read_buffer[4];
u32 mem_start; /* phys. address of the control registers */ resource_size_t mem_start;/* phys. address of the control registers */
u32 mem_end; /* phys. address of the control registers */ resource_size_t mem_end; /* phys. address of the control registers */
u32 mem_size; resource_size_t mem_size;
void __iomem *base_address;/* virt. address of the control registers */ void __iomem *base_address;/* virt. address of the control registers */
struct device *dev; struct device *dev;
...@@ -61,7 +61,7 @@ struct hwicap_drvdata { ...@@ -61,7 +61,7 @@ struct hwicap_drvdata {
const struct config_registers *config_regs; const struct config_registers *config_regs;
void *private_data; void *private_data;
bool is_open; bool is_open;
struct semaphore sem; struct mutex sem;
}; };
struct hwicap_driver_config { struct hwicap_driver_config {
...@@ -164,29 +164,29 @@ struct config_registers { ...@@ -164,29 +164,29 @@ struct config_registers {
#define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL #define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL
/** /**
* hwicap_type_1_read: Generates a Type 1 read packet header. * hwicap_type_1_read - Generates a Type 1 read packet header.
* @parameter: Register is the address of the register to be read back. * @reg: is the address of the register to be read back.
* *
* Generates a Type 1 read packet header, which is used to indirectly * Generates a Type 1 read packet header, which is used to indirectly
* read registers in the configuration logic. This packet must then * read registers in the configuration logic. This packet must then
* be sent through the icap device, and a return packet received with * be sent through the icap device, and a return packet received with
* the information. * the information.
**/ **/
static inline u32 hwicap_type_1_read(u32 Register) static inline u32 hwicap_type_1_read(u32 reg)
{ {
return (XHI_TYPE_1 << XHI_TYPE_SHIFT) | return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |
(Register << XHI_REGISTER_SHIFT) | (reg << XHI_REGISTER_SHIFT) |
(XHI_OP_READ << XHI_OP_SHIFT); (XHI_OP_READ << XHI_OP_SHIFT);
} }
/** /**
* hwicap_type_1_write: Generates a Type 1 write packet header * hwicap_type_1_write - Generates a Type 1 write packet header
* @parameter: Register is the address of the register to be read back. * @reg: is the address of the register to be read back.
**/ **/
static inline u32 hwicap_type_1_write(u32 Register) static inline u32 hwicap_type_1_write(u32 reg)
{ {
return (XHI_TYPE_1 << XHI_TYPE_SHIFT) | return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |
(Register << XHI_REGISTER_SHIFT) | (reg << XHI_REGISTER_SHIFT) |
(XHI_OP_WRITE << XHI_OP_SHIFT); (XHI_OP_WRITE << XHI_OP_SHIFT);
} }
......
...@@ -153,6 +153,9 @@ ...@@ -153,6 +153,9 @@
#define CTRL_RUNLATCH 0x1 #define CTRL_RUNLATCH 0x1
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ #define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
#define DABR_TRANSLATION (1UL << 2) #define DABR_TRANSLATION (1UL << 2)
#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */
#define DABRX_USER (1UL << 0)
#define DABRX_KERNEL (1UL << 1)
#define SPRN_DAR 0x013 /* Data Address Register */ #define SPRN_DAR 0x013 /* Data Address Register */
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ #define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
#define DSISR_NOHPTE 0x40000000 /* no translation found */ #define DSISR_NOHPTE 0x40000000 /* no translation found */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment