--- v5
+++ v10
@@ -1,105 +1,86 @@
-The iommu_free_table helper release memory it is using (the TCE table and
-@it_map) and release the iommu_table struct as well. We might not want
-the very last step as we store iommu_table in parent structures.
+This replaces direct accesses to TCE table with a helper which
+returns an TCE entry address. This does not make difference now but will
+when multi-level TCE tables get introduces.
+
+No change in behavior is expected.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
+Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
- arch/powerpc/include/asm/iommu.h | 1 +
- arch/powerpc/kernel/iommu.c | 57 ++++++++++++++++++++++++----------------
- 2 files changed, 35 insertions(+), 23 deletions(-)
+Changes:
+v9:
+* new patch in the series to separate this mechanical change from
+functional changes; this is not right before
+"powerpc/powernv: Implement multilevel TCE tables" but here in order
+to let the next patch - "powerpc/iommu/powernv: Release replaced TCE" -
+use pnv_tce() and avoid changing the same code twice
+---
+ arch/powerpc/platforms/powernv/pci.c | 34 +++++++++++++++++++++-------------
+ 1 file changed, 21 insertions(+), 13 deletions(-)
-diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
-index 6af22a4..fd118ea 100644
---- a/arch/powerpc/include/asm/iommu.h
-+++ b/arch/powerpc/include/asm/iommu.h
-@@ -125,6 +125,7 @@ static inline void *get_iommu_table_base(struct device *dev)
+diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
+index ed7de7b..cc82f05 100644
+--- a/arch/powerpc/platforms/powernv/pci.c
++++ b/arch/powerpc/platforms/powernv/pci.c
+@@ -572,38 +572,46 @@ struct pci_ops pnv_pci_ops = {
+ .write = pnv_pci_write_config,
+ };
- extern struct iommu_table *iommu_table_alloc(int node);
- /* Frees table for an individual device node */
-+extern void iommu_reset_table(struct iommu_table *tbl, const char *node_name);
- extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);
++static __be64 *pnv_tce(struct iommu_table *tbl, long idx)
++{
++ __be64 *tmp = ((__be64 *)tbl->it_base);
++
++ return tmp + idx;
++}
++
+ int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
+ unsigned long uaddr, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+ {
+ u64 proto_tce = iommu_direction_to_tce_perm(direction);
+- __be64 *tcep;
+- u64 rpn;
++ u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
++ long i;
- /* Initializes an iommu_table based in values set in the passed-in
-diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
-index f0f60ec..1440c6a 100644
---- a/arch/powerpc/kernel/iommu.c
-+++ b/arch/powerpc/kernel/iommu.c
-@@ -721,24 +721,46 @@ struct iommu_table *iommu_table_alloc(int node)
- return &table_group->tables[0];
+- tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
+- rpn = __pa(uaddr) >> tbl->it_page_shift;
+-
+- while (npages--)
+- *(tcep++) = cpu_to_be64(proto_tce |
+- (rpn++ << tbl->it_page_shift));
++ for (i = 0; i < npages; i++) {
++ unsigned long newtce = proto_tce |
++ ((rpn + i) << tbl->it_page_shift);
++ unsigned long idx = index - tbl->it_offset + i;
+
++ *(pnv_tce(tbl, idx)) = cpu_to_be64(newtce);
++ }
+
+ return 0;
}
-+void iommu_reset_table(struct iommu_table *tbl, const char *node_name)
-+{
-+ if (!tbl)
-+ return;
-+
-+ if (tbl->it_map) {
-+ unsigned long bitmap_sz;
-+ unsigned int order;
-+
-+ /*
-+ * In case we have reserved the first bit, we should not emit
-+ * the warning below.
-+ */
-+ if (tbl->it_offset == 0)
-+ clear_bit(0, tbl->it_map);
-+
-+ /* verify that table contains no entries */
-+ if (!bitmap_empty(tbl->it_map, tbl->it_size))
-+ pr_warn("%s: Unexpected TCEs for %s\n", __func__,
-+ node_name);
-+
-+ /* calculate bitmap size in bytes */
-+ bitmap_sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long);
-+
-+ /* free bitmap */
-+ order = get_order(bitmap_sz);
-+ free_pages((unsigned long) tbl->it_map, order);
+ void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
+ {
+- __be64 *tcep;
++ long i;
+
+- tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
++ for (i = 0; i < npages; i++) {
++ unsigned long idx = index - tbl->it_offset + i;
+
+- while (npages--)
+- *(tcep++) = cpu_to_be64(0);
++ *(pnv_tce(tbl, idx)) = cpu_to_be64(0);
+ }
-+
-+ memset(tbl, 0, sizeof(*tbl));
-+}
-+
- void iommu_free_table(struct iommu_table *tbl, const char *node_name)
+ }
+
+ unsigned long pnv_tce_get(struct iommu_table *tbl, long index)
{
-- unsigned long bitmap_sz;
-- unsigned int order;
- struct iommu_table_group *table_group = tbl->it_group;
+- return ((u64 *)tbl->it_base)[index - tbl->it_offset];
++ return *(pnv_tce(tbl, index - tbl->it_offset));
+ }
-- if (!tbl || !tbl->it_map) {
-- printk(KERN_ERR "%s: expected TCE map for %s\n", __func__,
-- node_name);
-+ if (!tbl)
- return;
-- }
-
-- /*
-- * In case we have reserved the first bit, we should not emit
-- * the warning below.
-- */
-- if (tbl->it_offset == 0)
-- clear_bit(0, tbl->it_map);
-+ iommu_reset_table(tbl, node_name);
-
- #ifdef CONFIG_IOMMU_API
- if (table_group->group) {
-@@ -747,17 +769,6 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
- }
- #endif
-
-- /* verify that table contains no entries */
-- if (!bitmap_empty(tbl->it_map, tbl->it_size))
-- pr_warn("%s: Unexpected TCEs for %s\n", __func__, node_name);
--
-- /* calculate bitmap size in bytes */
-- bitmap_sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long);
--
-- /* free bitmap */
-- order = get_order(bitmap_sz);
-- free_pages((unsigned long) tbl->it_map, order);
--
- /* free table */
- kfree(table_group);
- }
+ struct iommu_table *pnv_pci_table_alloc(int nid)
--
-2.0.0
+2.4.0.rc3.8.gfb3e7d5