aboutsummaryrefslogtreecommitdiff
path: root/arch/ia64/sn/pci/tioca_provider.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/sn/pci/tioca_provider.c')
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c107
1 files changed, 56 insertions, 51 deletions
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 27aa1842dac..a70b11fd57d 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -9,6 +9,9 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/bitmap.h>
+#include <linux/slab.h>
+#include <linux/export.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/addrs.h>
#include <asm/sn/io.h>
@@ -16,7 +19,7 @@
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/tioca_provider.h>
-uint32_t tioca_gart_found;
+u32 tioca_gart_found;
EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */
LIST_HEAD(tioca_list);
@@ -34,8 +37,8 @@ static int tioca_gart_init(struct tioca_kernel *);
static int
tioca_gart_init(struct tioca_kernel *tioca_kern)
{
- uint64_t ap_reg;
- uint64_t offset;
+ u64 ap_reg;
+ u64 offset;
struct page *tmp;
struct tioca_common *tioca_common;
struct tioca __iomem *ca_base;
@@ -88,7 +91,7 @@ tioca_gart_init(struct tioca_kernel *tioca_kern)
break;
default:
printk(KERN_ERR "%s: Invalid CA_APERATURE_SIZE "
- "0x%lx\n", __FUNCTION__, (ulong) CA_APERATURE_SIZE);
+ "0x%lx\n", __func__, (ulong) CA_APERATURE_SIZE);
return -1;
}
@@ -123,8 +126,8 @@ tioca_gart_init(struct tioca_kernel *tioca_kern)
if (!tmp) {
printk(KERN_ERR "%s: Could not allocate "
- "%lu bytes (order %d) for GART\n",
- __FUNCTION__,
+ "%llu bytes (order %d) for GART\n",
+ __func__,
tioca_kern->ca_gart_size,
get_order(tioca_kern->ca_gart_size));
return -ENOMEM;
@@ -214,7 +217,7 @@ void
tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
{
int cap_ptr;
- uint32_t reg;
+ u32 reg;
struct tioca __iomem *tioca_base;
struct pci_dev *pdev;
struct tioca_common *common;
@@ -223,7 +226,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
/*
* Scan all vga controllers on this bus making sure they all
- * suport FW. If not, return.
+ * support FW. If not, return.
*/
list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
@@ -276,7 +279,7 @@ EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */
* We will always use 0x1
* 55:55 - Swap bytes Currently unused
*/
-static uint64_t
+static u64
tioca_dma_d64(unsigned long paddr)
{
dma_addr_t bus_addr;
@@ -318,15 +321,15 @@ tioca_dma_d64(unsigned long paddr)
* and so a given CA can only directly target nodes in the range
* xxx - xxx+255.
*/
-static uint64_t
-tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
+static u64
+tioca_dma_d48(struct pci_dev *pdev, u64 paddr)
{
struct tioca_common *tioca_common;
struct tioca __iomem *ca_base;
- uint64_t ct_addr;
+ u64 ct_addr;
dma_addr_t bus_addr;
- uint32_t node_upper;
- uint64_t agp_dma_extn;
+ u32 node_upper;
+ u64 agp_dma_extn;
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
@@ -341,15 +344,15 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
if (node_upper > 64) {
printk(KERN_ERR "%s: coretalk addr 0x%p node id out "
- "of range\n", __FUNCTION__, (void *)ct_addr);
+ "of range\n", __func__, (void *)ct_addr);
return 0;
}
agp_dma_extn = __sn_readq_relaxed(&ca_base->ca_agp_dma_addr_extn);
if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
printk(KERN_ERR "%s: coretalk upper node (%u) "
- "mismatch with ca_agp_dma_addr_extn (%lu)\n",
- __FUNCTION__,
+ "mismatch with ca_agp_dma_addr_extn (%llu)\n",
+ __func__,
node_upper, (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT));
return 0;
}
@@ -364,20 +367,20 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
* @req_size: len (bytes) to map
*
* Map @paddr into CA address space using the GART mechanism. The mapped
- * dma_addr_t is guarenteed to be contiguous in CA bus space.
+ * dma_addr_t is guaranteed to be contiguous in CA bus space.
*/
static dma_addr_t
-tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
+tioca_dma_mapped(struct pci_dev *pdev, unsigned long paddr, size_t req_size)
{
- int i, ps, ps_shift, entry, entries, mapsize, last_entry;
- uint64_t xio_addr, end_xio_addr;
+ int ps, ps_shift, entry, entries, mapsize;
+ u64 xio_addr, end_xio_addr;
struct tioca_common *tioca_common;
struct tioca_kernel *tioca_kern;
dma_addr_t bus_addr = 0;
struct tioca_dmamap *ca_dmamap;
void *map;
unsigned long flags;
- struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);;
+ struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
@@ -410,21 +413,13 @@ tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
map = tioca_kern->ca_pcigart_pagemap;
mapsize = tioca_kern->ca_pcigart_entries;
- entry = find_first_zero_bit(map, mapsize);
- while (entry < mapsize) {
- last_entry = find_next_bit(map, mapsize, entry);
-
- if (last_entry - entry >= entries)
- break;
-
- entry = find_next_zero_bit(map, mapsize, last_entry);
- }
-
- if (entry > mapsize)
+ entry = bitmap_find_next_zero_area(map, mapsize, 0, entries, 0);
+ if (entry >= mapsize) {
+ kfree(ca_dmamap);
goto map_return;
+ }
- for (i = 0; i < entries; i++)
- set_bit(entry + i, map);
+ bitmap_set(map, entry, entries);
bus_addr = tioca_kern->ca_pciap_base + (entry * ps);
@@ -514,13 +509,19 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
* The mapping mode used is based on the devices dma_mask. As a last resort
* use the GART mapped mode.
*/
-static uint64_t
-tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
+static u64
+tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
{
- uint64_t mapaddr;
+ u64 mapaddr;
/*
- * If card is 64 or 48 bit addresable, use a direct mapping. 32
+ * Not supported for now ...
+ */
+ if (dma_flags & SN_DMA_MSI)
+ return 0;
+
+ /*
+ * If card is 64 or 48 bit addressable, use a direct mapping. 32
* bit direct is so restrictive w.r.t. where the memory resides that
* we don't use it even though CA has some support.
*/
@@ -544,18 +545,17 @@ tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
* tioca_error_intr_handler - SGI TIO CA error interrupt handler
* @irq: unused
* @arg: pointer to tioca_common struct for the given CA
- * @pt: unused
*
* Handle a CA error interrupt. Simply a wrapper around a SAL call which
* defers processing to the SGI prom.
*/
static irqreturn_t
-tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
+tioca_error_intr_handler(int irq, void *arg)
{
struct tioca_common *soft = arg;
struct ia64_sal_retval ret_stuff;
- uint64_t segment;
- uint64_t busnum;
+ u64 segment;
+ u64 busnum;
ret_stuff.status = 0;
ret_stuff.v0 = 0;
@@ -589,10 +589,10 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
/* sanity check prom rev */
- if (sn_sal_rev() < 0x0406) {
+ if (is_shub1() && sn_sal_rev() < 0x0406) {
printk
(KERN_ERR "%s: SGI prom rev 4.06 or greater required "
- "for tioca support\n", __FUNCTION__);
+ "for tioca support\n", __func__);
return NULL;
}
@@ -600,12 +600,14 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
* Allocate kernel bus soft and copy from prom.
*/
- tioca_common = kzalloc(sizeof(struct tioca_common), GFP_KERNEL);
+ tioca_common = kmemdup(prom_bussoft, sizeof(struct tioca_common),
+ GFP_KERNEL);
if (!tioca_common)
return NULL;
- memcpy(tioca_common, prom_bussoft, sizeof(struct tioca_common));
- tioca_common->ca_common.bs_base |= __IA64_UNCACHED_OFFSET;
+ tioca_common->ca_common.bs_base = (unsigned long)
+ ioremap(REGION_OFFSET(tioca_common->ca_common.bs_base),
+ sizeof(struct tioca_common));
/* init kernel-private area */
@@ -620,7 +622,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
INIT_LIST_HEAD(&tioca_kern->ca_dmamaps);
tioca_kern->ca_closest_node =
nasid_to_cnodeid(tioca_common->ca_closest_nasid);
- tioca_common->ca_kernel_private = (uint64_t) tioca_kern;
+ tioca_common->ca_kernel_private = (u64) tioca_kern;
bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
tioca_common->ca_common.bs_persist_busnum);
@@ -640,13 +642,16 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
if (request_irq(SGI_TIOCA_ERROR,
tioca_error_intr_handler,
- SA_SHIRQ, "TIOCA error", (void *)tioca_common))
+ IRQF_SHARED, "TIOCA error", (void *)tioca_common))
printk(KERN_WARNING
"%s: Unable to get irq %d. "
"Error interrupts won't be routed for TIOCA bus %d\n",
- __FUNCTION__, SGI_TIOCA_ERROR,
+ __func__, SGI_TIOCA_ERROR,
(int)tioca_common->ca_common.bs_persist_busnum);
+ irq_set_handler(SGI_TIOCA_ERROR, handle_level_irq);
+ sn_set_err_irq_affinity(SGI_TIOCA_ERROR);
+
/* Setup locality information */
controller->node = tioca_kern->ca_closest_node;
return tioca_common;