mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-18 00:24:58 +08:00
powerpc/pseries: Fix endian issues in pseries iommu code
Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
3e7cec6b17
commit
df015604cf
@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static void tce_invalidate_pSeries_sw(struct iommu_table *tbl,
|
static void tce_invalidate_pSeries_sw(struct iommu_table *tbl,
|
||||||
u64 *startp, u64 *endp)
|
__be64 *startp, __be64 *endp)
|
||||||
{
|
{
|
||||||
u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
|
u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
|
||||||
unsigned long start, end, inc;
|
unsigned long start, end, inc;
|
||||||
@ -86,7 +86,7 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
|
|||||||
struct dma_attrs *attrs)
|
struct dma_attrs *attrs)
|
||||||
{
|
{
|
||||||
u64 proto_tce;
|
u64 proto_tce;
|
||||||
u64 *tcep, *tces;
|
__be64 *tcep, *tces;
|
||||||
u64 rpn;
|
u64 rpn;
|
||||||
|
|
||||||
proto_tce = TCE_PCI_READ; // Read allowed
|
proto_tce = TCE_PCI_READ; // Read allowed
|
||||||
@ -94,12 +94,12 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
|
|||||||
if (direction != DMA_TO_DEVICE)
|
if (direction != DMA_TO_DEVICE)
|
||||||
proto_tce |= TCE_PCI_WRITE;
|
proto_tce |= TCE_PCI_WRITE;
|
||||||
|
|
||||||
tces = tcep = ((u64 *)tbl->it_base) + index;
|
tces = tcep = ((__be64 *)tbl->it_base) + index;
|
||||||
|
|
||||||
while (npages--) {
|
while (npages--) {
|
||||||
/* can't move this out since we might cross MEMBLOCK boundary */
|
/* can't move this out since we might cross MEMBLOCK boundary */
|
||||||
rpn = __pa(uaddr) >> TCE_SHIFT;
|
rpn = __pa(uaddr) >> TCE_SHIFT;
|
||||||
*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
|
*tcep = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
|
||||||
|
|
||||||
uaddr += TCE_PAGE_SIZE;
|
uaddr += TCE_PAGE_SIZE;
|
||||||
tcep++;
|
tcep++;
|
||||||
@ -113,9 +113,9 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
|
|||||||
|
|
||||||
static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
|
static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
|
||||||
{
|
{
|
||||||
u64 *tcep, *tces;
|
__be64 *tcep, *tces;
|
||||||
|
|
||||||
tces = tcep = ((u64 *)tbl->it_base) + index;
|
tces = tcep = ((__be64 *)tbl->it_base) + index;
|
||||||
|
|
||||||
while (npages--)
|
while (npages--)
|
||||||
*(tcep++) = 0;
|
*(tcep++) = 0;
|
||||||
@ -126,11 +126,11 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
|
|||||||
|
|
||||||
static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
|
static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
|
||||||
{
|
{
|
||||||
u64 *tcep;
|
__be64 *tcep;
|
||||||
|
|
||||||
tcep = ((u64 *)tbl->it_base) + index;
|
tcep = ((__be64 *)tbl->it_base) + index;
|
||||||
|
|
||||||
return *tcep;
|
return be64_to_cpu(*tcep);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tce_free_pSeriesLP(struct iommu_table*, long, long);
|
static void tce_free_pSeriesLP(struct iommu_table*, long, long);
|
||||||
@ -177,7 +177,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_PER_CPU(u64 *, tce_page);
|
static DEFINE_PER_CPU(__be64 *, tce_page);
|
||||||
|
|
||||||
static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
|
static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
|
||||||
long npages, unsigned long uaddr,
|
long npages, unsigned long uaddr,
|
||||||
@ -186,7 +186,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
|
|||||||
{
|
{
|
||||||
u64 rc = 0;
|
u64 rc = 0;
|
||||||
u64 proto_tce;
|
u64 proto_tce;
|
||||||
u64 *tcep;
|
__be64 *tcep;
|
||||||
u64 rpn;
|
u64 rpn;
|
||||||
long l, limit;
|
long l, limit;
|
||||||
long tcenum_start = tcenum, npages_start = npages;
|
long tcenum_start = tcenum, npages_start = npages;
|
||||||
@ -206,7 +206,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
|
|||||||
* from iommu_alloc{,_sg}()
|
* from iommu_alloc{,_sg}()
|
||||||
*/
|
*/
|
||||||
if (!tcep) {
|
if (!tcep) {
|
||||||
tcep = (u64 *)__get_free_page(GFP_ATOMIC);
|
tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
|
||||||
/* If allocation fails, fall back to the loop implementation */
|
/* If allocation fails, fall back to the loop implementation */
|
||||||
if (!tcep) {
|
if (!tcep) {
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
@ -230,7 +230,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
|
|||||||
limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
|
limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
|
||||||
|
|
||||||
for (l = 0; l < limit; l++) {
|
for (l = 0; l < limit; l++) {
|
||||||
tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
|
tcep[l] = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
|
||||||
rpn++;
|
rpn++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,16 +329,16 @@ struct direct_window {
|
|||||||
|
|
||||||
/* Dynamic DMA Window support */
|
/* Dynamic DMA Window support */
|
||||||
struct ddw_query_response {
|
struct ddw_query_response {
|
||||||
u32 windows_available;
|
__be32 windows_available;
|
||||||
u32 largest_available_block;
|
__be32 largest_available_block;
|
||||||
u32 page_size;
|
__be32 page_size;
|
||||||
u32 migration_capable;
|
__be32 migration_capable;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ddw_create_response {
|
struct ddw_create_response {
|
||||||
u32 liobn;
|
__be32 liobn;
|
||||||
u32 addr_hi;
|
__be32 addr_hi;
|
||||||
u32 addr_lo;
|
__be32 addr_lo;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LIST_HEAD(direct_window_list);
|
static LIST_HEAD(direct_window_list);
|
||||||
@ -392,7 +392,8 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
|
|||||||
unsigned long num_pfn, const void *arg)
|
unsigned long num_pfn, const void *arg)
|
||||||
{
|
{
|
||||||
const struct dynamic_dma_window_prop *maprange = arg;
|
const struct dynamic_dma_window_prop *maprange = arg;
|
||||||
u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce, liobn;
|
u64 tce_size, num_tce, dma_offset, next, proto_tce, liobn;
|
||||||
|
__be64 *tcep;
|
||||||
u32 tce_shift;
|
u32 tce_shift;
|
||||||
u64 rc = 0;
|
u64 rc = 0;
|
||||||
long l, limit;
|
long l, limit;
|
||||||
@ -401,7 +402,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
|
|||||||
tcep = __get_cpu_var(tce_page);
|
tcep = __get_cpu_var(tce_page);
|
||||||
|
|
||||||
if (!tcep) {
|
if (!tcep) {
|
||||||
tcep = (u64 *)__get_free_page(GFP_ATOMIC);
|
tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
|
||||||
if (!tcep) {
|
if (!tcep) {
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -435,7 +436,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
|
|||||||
dma_offset = next + be64_to_cpu(maprange->dma_base);
|
dma_offset = next + be64_to_cpu(maprange->dma_base);
|
||||||
|
|
||||||
for (l = 0; l < limit; l++) {
|
for (l = 0; l < limit; l++) {
|
||||||
tcep[l] = proto_tce | next;
|
tcep[l] = cpu_to_be64(proto_tce | next);
|
||||||
next += tce_size;
|
next += tce_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,7 +781,7 @@ static u64 find_existing_ddw(struct device_node *pdn)
|
|||||||
list_for_each_entry(window, &direct_window_list, list) {
|
list_for_each_entry(window, &direct_window_list, list) {
|
||||||
if (window->device == pdn) {
|
if (window->device == pdn) {
|
||||||
direct64 = window->prop;
|
direct64 = window->prop;
|
||||||
dma_addr = direct64->dma_base;
|
dma_addr = be64_to_cpu(direct64->dma_base);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1045,11 +1046,11 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
|||||||
dev_dbg(&dev->dev, "no free dynamic windows");
|
dev_dbg(&dev->dev, "no free dynamic windows");
|
||||||
goto out_restore_window;
|
goto out_restore_window;
|
||||||
}
|
}
|
||||||
if (query.page_size & 4) {
|
if (be32_to_cpu(query.page_size) & 4) {
|
||||||
page_shift = 24; /* 16MB */
|
page_shift = 24; /* 16MB */
|
||||||
} else if (query.page_size & 2) {
|
} else if (be32_to_cpu(query.page_size) & 2) {
|
||||||
page_shift = 16; /* 64kB */
|
page_shift = 16; /* 64kB */
|
||||||
} else if (query.page_size & 1) {
|
} else if (be32_to_cpu(query.page_size) & 1) {
|
||||||
page_shift = 12; /* 4kB */
|
page_shift = 12; /* 4kB */
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(&dev->dev, "no supported direct page size in mask %x",
|
dev_dbg(&dev->dev, "no supported direct page size in mask %x",
|
||||||
@ -1059,7 +1060,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
|||||||
/* verify the window * number of ptes will map the partition */
|
/* verify the window * number of ptes will map the partition */
|
||||||
/* check largest block * page size > max memory hotplug addr */
|
/* check largest block * page size > max memory hotplug addr */
|
||||||
max_addr = memory_hotplug_max();
|
max_addr = memory_hotplug_max();
|
||||||
if (query.largest_available_block < (max_addr >> page_shift)) {
|
if (be32_to_cpu(query.largest_available_block) < (max_addr >> page_shift)) {
|
||||||
dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
|
dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
|
||||||
"%llu-sized pages\n", max_addr, query.largest_available_block,
|
"%llu-sized pages\n", max_addr, query.largest_available_block,
|
||||||
1ULL << page_shift);
|
1ULL << page_shift);
|
||||||
@ -1085,7 +1086,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out_free_prop;
|
goto out_free_prop;
|
||||||
|
|
||||||
ddwprop->liobn = cpu_to_be32(create.liobn);
|
ddwprop->liobn = create.liobn;
|
||||||
ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2));
|
ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2));
|
||||||
ddwprop->tce_shift = cpu_to_be32(page_shift);
|
ddwprop->tce_shift = cpu_to_be32(page_shift);
|
||||||
ddwprop->window_shift = cpu_to_be32(len);
|
ddwprop->window_shift = cpu_to_be32(len);
|
||||||
|
Loading…
Reference in New Issue
Block a user