19c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/*
29c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * This file is subject to the terms and conditions of the GNU General Public
39c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * License.  See the file "COPYING" in the main directory of this archive
49c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * for more details.
59c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
69c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Copyright (C) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved.
79c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
89c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
99c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <linux/types.h>
109c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <linux/interrupt.h>
119c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <linux/pci.h>
1281f6527bd322ef1f3a58c2c438b9ded3bd8f606aAkinobu Mita#include <linux/bitmap.h>
135a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
14bd3ff1943509e641a34f2d8dd1d41ed12a4476c1Paul Gortmaker#include <linux/export.h>
159c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <asm/sn/sn_sal.h>
169c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <asm/sn/addrs.h>
171fa92957282e4595727c1a21bf6687ea5a2d612fTony Luck#include <asm/sn/io.h>
189c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <asm/sn/pcidev.h>
199c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <asm/sn/pcibus_provider_defs.h>
209c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule#include <asm/sn/tioca_provider.h>
219c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2253493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargavau32 tioca_gart_found;
239c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark MauleEXPORT_SYMBOL(tioca_gart_found);	/* used by agp-sgi */
249c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
259c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark MauleLIST_HEAD(tioca_list);
269c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark MauleEXPORT_SYMBOL(tioca_list);	/* used by agp-sgi */
279c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
289c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maulestatic int tioca_gart_init(struct tioca_kernel *);
299c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
309c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
319c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_gart_init - Initialize SGI TIOCA GART
329c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @tioca_common: ptr to common prom/kernel struct identifying the
339c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
349c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * If the indicated tioca has devices present, initialize its associated
359c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * GART MMR's and kernel memory.
369c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
379c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maulestatic int
389c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Mauletioca_gart_init(struct tioca_kernel *tioca_kern)
399c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
4053493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 ap_reg;
4153493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 offset;
429c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct page *tmp;
439c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_common *tioca_common;
44b3e5b5b2277f9c047082dcb309f665fe8b5706c1Al Viro	struct tioca __iomem *ca_base;
459c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
469c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_common = tioca_kern->ca_common;
47b3e5b5b2277f9c047082dcb309f665fe8b5706c1Al Viro	ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
489c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
499c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (list_empty(tioca_kern->ca_devices))
509c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return 0;
519c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
529c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ap_reg = 0;
539c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
549c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
559c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Validate aperature size
569c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
579c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
589c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	switch (CA_APERATURE_SIZE >> 20) {
599c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 4:
609c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x3ff << CA_GART_AP_SIZE_SHFT);	/* 4MB */
619c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
629c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 8:
639c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x3fe << CA_GART_AP_SIZE_SHFT);	/* 8MB */
649c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
659c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 16:
669c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x3fc << CA_GART_AP_SIZE_SHFT);	/* 16MB */
679c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
689c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 32:
699c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x3f8 << CA_GART_AP_SIZE_SHFT);	/* 32 MB */
709c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
719c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 64:
729c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x3f0 << CA_GART_AP_SIZE_SHFT);	/* 64 MB */
739c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
749c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 128:
759c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x3e0 << CA_GART_AP_SIZE_SHFT);	/* 128 MB */
769c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
779c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 256:
789c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x3c0 << CA_GART_AP_SIZE_SHFT);	/* 256 MB */
799c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
809c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 512:
819c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x380 << CA_GART_AP_SIZE_SHFT);	/* 512 MB */
829c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
839c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 1024:
849c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x300 << CA_GART_AP_SIZE_SHFT);	/* 1GB */
859c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
869c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 2048:
879c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x200 << CA_GART_AP_SIZE_SHFT);	/* 2GB */
889c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
899c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	case 4096:
909c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= (0x000 << CA_GART_AP_SIZE_SHFT);	/* 4 GB */
919c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
929c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	default:
939c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		printk(KERN_ERR "%s:  Invalid CA_APERATURE_SIZE "
94d4ed80841ad4a1d59decccfbe2d010558568c5fbHarvey Harrison		       "0x%lx\n", __func__, (ulong) CA_APERATURE_SIZE);
959c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return -1;
969c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
979c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
989c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
999c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Set up other aperature parameters
1009c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
1019c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1029c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (PAGE_SIZE >= 16384) {
1039c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		tioca_kern->ca_ap_pagesize = 16384;
1049c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		ap_reg |= CA_GART_PAGE_SIZE;
1059c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	} else {
1069c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		tioca_kern->ca_ap_pagesize = 4096;
1079c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
1089c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1099c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_ap_size = CA_APERATURE_SIZE;
1109c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_ap_bus_base = CA_APERATURE_BASE;
1119c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gart_entries =
1129c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    tioca_kern->ca_ap_size / tioca_kern->ca_ap_pagesize;
1139c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1149c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ap_reg |= (CA_GART_AP_ENB_AGP | CA_GART_AP_ENB_PCI);
1159c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ap_reg |= tioca_kern->ca_ap_bus_base;
1169c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1179c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
1189c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Allocate and set up the GART
1199c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
1209c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1219c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gart_size = tioca_kern->ca_gart_entries * sizeof(u64);
1229c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tmp =
1239c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    alloc_pages_node(tioca_kern->ca_closest_node,
1249c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			     GFP_KERNEL | __GFP_ZERO,
1259c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			     get_order(tioca_kern->ca_gart_size));
1269c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1279c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (!tmp) {
1289c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		printk(KERN_ERR "%s:  Could not allocate "
129e088a4ad7fa53c3dc3c29f930025f41ccf01953eMatthew Wilcox		       "%llu bytes (order %d) for GART\n",
130d4ed80841ad4a1d59decccfbe2d010558568c5fbHarvey Harrison		       __func__,
1319c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		       tioca_kern->ca_gart_size,
1329c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		       get_order(tioca_kern->ca_gart_size));
1339c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return -ENOMEM;
1349c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
1359c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1369c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gart = page_address(tmp);
1379c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gart_coretalk_addr =
1389c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    PHYS_TO_TIODMA(virt_to_phys(tioca_kern->ca_gart));
1399c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1409c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
1419c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Compute PCI/AGP convenience fields
1429c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
1439c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1449c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	offset = CA_PCI32_MAPPED_BASE - CA_APERATURE_BASE;
1459c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_pciap_base = CA_PCI32_MAPPED_BASE;
1469c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_pciap_size = CA_PCI32_MAPPED_SIZE;
1479c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_pcigart_start = offset / tioca_kern->ca_ap_pagesize;
1489c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_pcigart_base =
1499c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    tioca_kern->ca_gart_coretalk_addr + offset;
1509c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_pcigart =
1519c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    &tioca_kern->ca_gart[tioca_kern->ca_pcigart_start];
1529c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_pcigart_entries =
1539c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize;
1549c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_pcigart_pagemap =
155f96cb1f0580324b95b7219466312a376a59a796fPekka Enberg	    kzalloc(tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
1569c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (!tioca_kern->ca_pcigart_pagemap) {
1579c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		free_pages((unsigned long)tioca_kern->ca_gart,
1589c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			   get_order(tioca_kern->ca_gart_size));
1599c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return -1;
1609c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
1619c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1629c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	offset = CA_AGP_MAPPED_BASE - CA_APERATURE_BASE;
1639c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gfxap_base = CA_AGP_MAPPED_BASE;
1649c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gfxap_size = CA_AGP_MAPPED_SIZE;
1659c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gfxgart_start = offset / tioca_kern->ca_ap_pagesize;
1669c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gfxgart_base =
1679c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    tioca_kern->ca_gart_coretalk_addr + offset;
1689c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gfxgart =
1699c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    &tioca_kern->ca_gart[tioca_kern->ca_gfxgart_start];
1709c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gfxgart_entries =
1719c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    tioca_kern->ca_gfxap_size / tioca_kern->ca_ap_pagesize;
1729c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1739c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
1749c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * various control settings:
1759c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 *      use agp op-combining
1769c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 *      use GET semantics to fetch memory
1779c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 *      participate in coherency domain
1784628d7cada7a19166ba8fe57f5ef0f0009694e1eMark Maule	 * 	DISABLE GART PREFETCHING due to hw bug tracked in SGI PV930029
1799c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
1809c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1815fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	__sn_setq_relaxed(&ca_base->ca_control1,
1825fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule			CA_AGPDMA_OP_ENB_COMBDELAY);	/* PV895469 ? */
1835fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	__sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
1845fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	__sn_setq_relaxed(&ca_base->ca_control2,
1855fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule			(0x2ull << CA_GART_MEM_PARAM_SHFT));
1869c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_gart_iscoherent = 1;
1875fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	__sn_clrq_relaxed(&ca_base->ca_control2,
1885fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	    		(CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB));
1899c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1909c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
1919c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Unmask GART fetch error interrupts.  Clear residual errors first.
1929c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
1939c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1945fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	writeq(CA_GART_FETCH_ERR, &ca_base->ca_int_status_alias);
1955fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	writeq(CA_GART_FETCH_ERR, &ca_base->ca_mult_error_alias);
1965fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	__sn_clrq_relaxed(&ca_base->ca_int_mask, CA_GART_FETCH_ERR);
1979c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
1989c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
1999c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Program the aperature and gart registers in TIOCA
2009c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
2019c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2025fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	writeq(ap_reg, &ca_base->ca_gart_aperature);
2035fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	writeq(tioca_kern->ca_gart_coretalk_addr|1, &ca_base->ca_gart_ptr_table);
2049c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2059c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return 0;
2069c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
2079c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2089c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
2099c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_fastwrite_enable - enable AGP FW for a tioca and its functions
2109c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @tioca_kernel: structure representing the CA
2119c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
2129c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Given a CA, scan all attached functions making sure they all support
2139c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * FastWrite.  If so, enable FastWrite for all functions and the CA itself.
2149c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
2159c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2169c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maulevoid
2179c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Mauletioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
2189c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
2199c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	int cap_ptr;
22053493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u32 reg;
221b3e5b5b2277f9c047082dcb309f665fe8b5706c1Al Viro	struct tioca __iomem *tioca_base;
2229c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct pci_dev *pdev;
2239c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_common *common;
2249c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2259c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	common = tioca_kern->ca_common;
2269c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2279c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
2289c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Scan all vga controllers on this bus making sure they all
22972fdbdce3d52282f8ea95f512e871791256754e6Simon Arlott	 * support FW.  If not, return.
2309c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
2319c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2329c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
2339c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
2349c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			continue;
2359c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2369c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
2379c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		if (!cap_ptr)
2389c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			return;	/* no AGP CAP means no FW */
2399c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2409c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		pci_read_config_dword(pdev, cap_ptr + PCI_AGP_STATUS, &reg);
2419c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		if (!(reg & PCI_AGP_STATUS_FW))
2429c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			return;	/* function doesn't support FW */
2439c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
2449c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2459c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
2469c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Set fw for all vga fn's
2479c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
2489c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2499c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
2509c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
2519c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			continue;
2529c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2539c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
2549c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		pci_read_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, &reg);
2559c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		reg |= PCI_AGP_COMMAND_FW;
2569c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		pci_write_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, reg);
2579c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
2589c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2599c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
2609c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Set ca's fw to match
2619c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
2629c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
263b3e5b5b2277f9c047082dcb309f665fe8b5706c1Al Viro	tioca_base = (struct tioca __iomem*)common->ca_common.bs_base;
2645fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	__sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE);
2659c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
2669c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2679c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark MauleEXPORT_SYMBOL(tioca_fastwrite_enable);	/* used by agp-sgi */
2689c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2699c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
2709c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_dma_d64 - create a DMA mapping using 64-bit direct mode
2719c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @paddr: system physical address
2729c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
2739c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Map @paddr into 64-bit CA bus space.  No device context is necessary.
2749c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Bits 53:0 come from the coretalk address.  We just need to mask in the
2759c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * following optional bits of the 64-bit pci address:
2769c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
2779c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * 63:60 - Coretalk Packet Type -  0x1 for Mem Get/Put (coherent)
2789c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *                                 0x2 for PIO (non-coherent)
2799c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *                                 We will always use 0x1
2809c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * 55:55 - Swap bytes		   Currently unused
2819c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
28253493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargavastatic u64
2839c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Mauletioca_dma_d64(unsigned long paddr)
2849c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
2859c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	dma_addr_t bus_addr;
2869c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2879c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	bus_addr = PHYS_TO_TIODMA(paddr);
2889c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2899c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	BUG_ON(!bus_addr);
2909c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	BUG_ON(bus_addr >> 54);
2919c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2929c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/* Set upper nibble to Cache Coherent Memory op */
2939c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	bus_addr |= (1UL << 60);
2949c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2959c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return bus_addr;
2969c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
2979c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
2989c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
2999c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_dma_d48 - create a DMA mapping using 48-bit direct mode
3009c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @pdev: linux pci_dev representing the function
3019c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @paddr: system physical address
3029c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
3039c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Map @paddr into 64-bit bus space of the CA associated with @pcidev_info.
3049c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
3059c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * The CA agp 48 bit direct address falls out as follows:
3069c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
3079c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * When direct mapping AGP addresses, the 48 bit AGP address is
3089c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * constructed as follows:
3099c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
3109c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * [47:40] - Low 8 bits of the page Node ID extracted from coretalk
3119c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *              address [47:40].  The upper 8 node bits are fixed
3129c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *              and come from the xxx register bits [5:0]
3139c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * [39:38] - Chiplet ID extracted from coretalk address [39:38]
3149c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * [37:00] - node offset extracted from coretalk address [37:00]
3159c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
3169c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Since the node id in general will be non-zero, and the chiplet id
3179c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * will always be non-zero, it follows that the device must support
3189c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * a dma mask of at least 0xffffffffff (40 bits) to target node 0
3199c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * and in general should be 0xffffffffffff (48 bits) to target nodes
3209c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * up to 255.  Nodes above 255 need the support of the xxx register,
3219c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * and so a given CA can only directly target nodes in the range
3229c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * xxx - xxx+255.
3239c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
32453493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargavastatic u64
32553493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargavatioca_dma_d48(struct pci_dev *pdev, u64 paddr)
3269c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
3279c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_common *tioca_common;
328b3e5b5b2277f9c047082dcb309f665fe8b5706c1Al Viro	struct tioca __iomem *ca_base;
32953493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 ct_addr;
3309c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	dma_addr_t bus_addr;
33153493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u32 node_upper;
33253493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 agp_dma_extn;
3339c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
3349c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3359c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
336b3e5b5b2277f9c047082dcb309f665fe8b5706c1Al Viro	ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;
3379c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3389c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ct_addr = PHYS_TO_TIODMA(paddr);
3399c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (!ct_addr)
3409c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return 0;
3419c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
34292a582ed2757456ca9599f8b4ea2064f2154eb02Prarit Bhargava	bus_addr = (dma_addr_t) (ct_addr & 0xffffffffffffUL);
3439c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	node_upper = ct_addr >> 48;
3449c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3459c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (node_upper > 64) {
3469c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		printk(KERN_ERR "%s:  coretalk addr 0x%p node id out "
347d4ed80841ad4a1d59decccfbe2d010558568c5fbHarvey Harrison		       "of range\n", __func__, (void *)ct_addr);
3489c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return 0;
3499c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
3509c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3515fbcf9a5c6904bd563f584d12d1f4d3f68a19d7dMark Maule	agp_dma_extn = __sn_readq_relaxed(&ca_base->ca_agp_dma_addr_extn);
3529c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
3539c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		printk(KERN_ERR "%s:  coretalk upper node (%u) "
354e088a4ad7fa53c3dc3c29f930025f41ccf01953eMatthew Wilcox		       "mismatch with ca_agp_dma_addr_extn (%llu)\n",
355d4ed80841ad4a1d59decccfbe2d010558568c5fbHarvey Harrison		       __func__,
3569c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		       node_upper, (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT));
3579c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return 0;
3589c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
3599c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3609c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return bus_addr;
3619c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
3629c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3639c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
3649c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_dma_mapped - create a DMA mapping using a CA GART
3659c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @pdev: linux pci_dev representing the function
3669c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @paddr: host physical address to map
3679c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @req_size: len (bytes) to map
3689c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
3699c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Map @paddr into CA address space using the GART mechanism.  The mapped
37072fdbdce3d52282f8ea95f512e871791256754e6Simon Arlott * dma_addr_t is guaranteed to be contiguous in CA bus space.
3719c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
3729c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maulestatic dma_addr_t
373e088a4ad7fa53c3dc3c29f930025f41ccf01953eMatthew Wilcoxtioca_dma_mapped(struct pci_dev *pdev, unsigned long paddr, size_t req_size)
3749c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
37581f6527bd322ef1f3a58c2c438b9ded3bd8f606aAkinobu Mita	int ps, ps_shift, entry, entries, mapsize;
37653493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 xio_addr, end_xio_addr;
3779c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_common *tioca_common;
3789c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_kernel *tioca_kern;
3799c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	dma_addr_t bus_addr = 0;
3809c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_dmamap *ca_dmamap;
3819c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	void *map;
3829c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	unsigned long flags;
38353b3531bbbf70ac7551b32d1acc229d94de52658Alexey Dobriyan	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
3849c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3859c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
3869c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
3879c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3889c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	xio_addr = PHYS_TO_TIODMA(paddr);
3899c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (!xio_addr)
3909c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return 0;
3919c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3929c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	spin_lock_irqsave(&tioca_kern->ca_lock, flags);
3939c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
3949c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
3959c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * allocate a map struct
3969c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
3979c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
398f96cb1f0580324b95b7219466312a376a59a796fPekka Enberg	ca_dmamap = kzalloc(sizeof(struct tioca_dmamap), GFP_ATOMIC);
3999c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (!ca_dmamap)
4009c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		goto map_return;
4019c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4029c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
4039c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Locate free entries that can hold req_size.  Account for
4049c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * unaligned start/length when allocating.
4059c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
4069c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4079c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ps = tioca_kern->ca_ap_pagesize;	/* will be power of 2 */
4089c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ps_shift = ffs(ps) - 1;
4099c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	end_xio_addr = xio_addr + req_size - 1;
4109c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4119c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	entries = (end_xio_addr >> ps_shift) - (xio_addr >> ps_shift) + 1;
4129c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4139c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	map = tioca_kern->ca_pcigart_pagemap;
4149c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	mapsize = tioca_kern->ca_pcigart_entries;
4159c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
41681f6527bd322ef1f3a58c2c438b9ded3bd8f606aAkinobu Mita	entry = bitmap_find_next_zero_area(map, mapsize, 0, entries, 0);
41781f6527bd322ef1f3a58c2c438b9ded3bd8f606aAkinobu Mita	if (entry >= mapsize) {
4186bf6a1a49377c32a02939ec835553703994f3e41Julia Lawall		kfree(ca_dmamap);
4199c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		goto map_return;
4206bf6a1a49377c32a02939ec835553703994f3e41Julia Lawall	}
4219c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
42281f6527bd322ef1f3a58c2c438b9ded3bd8f606aAkinobu Mita	bitmap_set(map, entry, entries);
4239c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4249c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	bus_addr = tioca_kern->ca_pciap_base + (entry * ps);
4259c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4269c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ca_dmamap->cad_dma_addr = bus_addr;
4279c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ca_dmamap->cad_gart_size = entries;
4289c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ca_dmamap->cad_gart_entry = entry;
4293ea8b477b4b9d3e75b5e9b8aea41259f45031823Mark Maule	list_add(&ca_dmamap->cad_list, &tioca_kern->ca_dmamaps);
4309c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4319c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (xio_addr % ps) {
4329c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
4339c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		bus_addr += xio_addr & (ps - 1);
4349c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		xio_addr &= ~(ps - 1);
4359c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		xio_addr += ps;
4369c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		entry++;
4379c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
4389c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4399c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	while (xio_addr < end_xio_addr) {
4409c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
4419c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		xio_addr += ps;
4429c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		entry++;
4439c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
4449c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4459c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_tlbflush(tioca_kern);
4469c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4479c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maulemap_return:
4489c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
4499c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return bus_addr;
4509c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
4519c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4529c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
4539c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_dma_unmap - release CA mapping resources
4549c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @pdev: linux pci_dev representing the function
4559c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @bus_addr: bus address returned by an earlier tioca_dma_map
4569c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @dir: mapping direction (unused)
4579c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
4589c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Locate mapping resources associated with @bus_addr and release them.
4599c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * For mappings created using the direct modes (64 or 48) there are no
4609c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * resources to release.
4619c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
46292a582ed2757456ca9599f8b4ea2064f2154eb02Prarit Bhargavastatic void
4639c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Mauletioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
4649c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
4659c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	int i, entry;
4669c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_common *tioca_common;
4679c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_kernel *tioca_kern;
4689c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_dmamap *map;
4699c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
4709c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	unsigned long flags;
4719c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4729c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
4739c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
4749c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4759c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/* return straight away if this isn't be a mapped address */
4769c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4779c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (bus_addr < tioca_kern->ca_pciap_base ||
4789c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    bus_addr >= (tioca_kern->ca_pciap_base + tioca_kern->ca_pciap_size))
4799c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return;
4809c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4819c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	spin_lock_irqsave(&tioca_kern->ca_lock, flags);
4829c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4839c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	list_for_each_entry(map, &tioca_kern->ca_dmamaps, cad_list)
4849c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    if (map->cad_dma_addr == bus_addr)
4859c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		break;
4869c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4879c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	BUG_ON(map == NULL);
4889c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4899c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	entry = map->cad_gart_entry;
4909c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4919c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	for (i = 0; i < map->cad_gart_size; i++, entry++) {
4929c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		clear_bit(entry, tioca_kern->ca_pcigart_pagemap);
4939c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		tioca_kern->ca_pcigart[entry] = 0;
4949c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
4959c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_tlbflush(tioca_kern);
4969c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
4979c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	list_del(&map->cad_list);
4989c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
4999c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	kfree(map);
5009c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
5019c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5029c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
5039c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_dma_map - map pages for PCI DMA
5049c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @pdev: linux pci_dev representing the function
5059c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @paddr: host physical address to map
5069c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @byte_count: bytes to map
5079c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
5089c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * This is the main wrapper for mapping host physical pages to CA PCI space.
5099c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * The mapping mode used is based on the devices dma_mask.  As a last resort
5109c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * use the GART mapped mode.
5119c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
51253493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargavastatic u64
513b4a6b3436531f6c5256e6d60d388c3c28ff1a0e9Jeff Mahoneytioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
5149c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
51553493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 mapaddr;
5169c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5179c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
51883821d3f558dc651e555d62182ed0c95651f41a6Mark Maule	 * Not supported for now ...
51983821d3f558dc651e555d62182ed0c95651f41a6Mark Maule	 */
52083821d3f558dc651e555d62182ed0c95651f41a6Mark Maule	if (dma_flags & SN_DMA_MSI)
52183821d3f558dc651e555d62182ed0c95651f41a6Mark Maule		return 0;
52283821d3f558dc651e555d62182ed0c95651f41a6Mark Maule
52383821d3f558dc651e555d62182ed0c95651f41a6Mark Maule	/*
52472fdbdce3d52282f8ea95f512e871791256754e6Simon Arlott	 * If card is 64 or 48 bit addressable, use a direct mapping.  32
5259c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * bit direct is so restrictive w.r.t. where the memory resides that
5269c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * we don't use it even though CA has some support.
5279c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
5289c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5299c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (pdev->dma_mask == ~0UL)
5309c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		mapaddr = tioca_dma_d64(paddr);
5319c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	else if (pdev->dma_mask == 0xffffffffffffUL)
5329c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		mapaddr = tioca_dma_d48(pdev, paddr);
5339c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	else
5349c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		mapaddr = 0;
5359c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5369c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/* Last resort ... use PCI portion of CA GART */
5379c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5389c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (mapaddr == 0)
5399c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		mapaddr = tioca_dma_mapped(pdev, paddr, byte_count);
5409c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5419c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return mapaddr;
5429c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
5439c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5449c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
5459c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_error_intr_handler - SGI TIO CA error interrupt handler
5469c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @irq: unused
5479c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @arg: pointer to tioca_common struct for the given CA
5489c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
5499c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Handle a CA error interrupt.  Simply a wrapper around a SAL call which
5509c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * defers processing to the SGI prom.
5519c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
5529c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maulestatic irqreturn_t
5537d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellstioca_error_intr_handler(int irq, void *arg)
5549c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
5559c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_common *soft = arg;
5569c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct ia64_sal_retval ret_stuff;
55753493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 segment;
55853493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	u64 busnum;
5599c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ret_stuff.status = 0;
5609c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	ret_stuff.v0 = 0;
5619c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
562674c6479b7bdc78528ea83dd43897e3161558b8bColin Ngam	segment = soft->ca_common.bs_persist_segment;
5639c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	busnum = soft->ca_common.bs_persist_busnum;
5649c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5659c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	SAL_CALL_NOLOCK(ret_stuff,
5669c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			(u64) SN_SAL_IOIF_ERROR_INTERRUPT,
5679c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			segment, busnum, 0, 0, 0, 0, 0);
5689c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5699c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return IRQ_HANDLED;
5709c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
5719c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5729c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
5739c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_bus_fixup - perform final PCI fixup for a TIO CA bus
5749c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * @prom_bussoft: Common prom/kernel struct representing the bus
5759c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
5769c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * Replicates the tioca_common pointed to by @prom_bussoft in kernel
5779c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * space.  Allocates and initializes a kernel-only area for a given CA,
5789c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * and sets up an irq for handling CA error interrupts.
5799c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule *
5809c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * On successful setup, returns the kernel version of tioca_common back to
5819c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * the caller.
5829c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
58392a582ed2757456ca9599f8b4ea2064f2154eb02Prarit Bhargavastatic void *
5847c2a6c62c013a4ea57243536fc7f3987e4ba04bcChristoph Lametertioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
5859c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
5869c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_common *tioca_common;
5879c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct tioca_kernel *tioca_kern;
5889c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	struct pci_bus *bus;
5899c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5909c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/* sanity check prom rev */
5919c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
592d3e5e1a1b4f43bcfa1a34516e233911487c67307Aaron Young	if (is_shub1() && sn_sal_rev() < 0x0406) {
5939c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		printk
5949c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		    (KERN_ERR "%s:  SGI prom rev 4.06 or greater required "
595d4ed80841ad4a1d59decccfbe2d010558568c5fbHarvey Harrison		     "for tioca support\n", __func__);
5969c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return NULL;
5979c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
5989c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
5999c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/*
6009c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 * Allocate kernel bus soft and copy from prom.
6019c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	 */
6029c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
603ac0d1a48d8b18c4808ab73d990b83bb032f21c25Thomas Meyer	tioca_common = kmemdup(prom_bussoft, sizeof(struct tioca_common),
604ac0d1a48d8b18c4808ab73d990b83bb032f21c25Thomas Meyer			       GFP_KERNEL);
6059c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (!tioca_common)
6069c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return NULL;
6079c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6081ee27a4eedf3cc08245d395936c1bfaf80c074ccJes Sorensen	tioca_common->ca_common.bs_base = (unsigned long)
6091ee27a4eedf3cc08245d395936c1bfaf80c074ccJes Sorensen		ioremap(REGION_OFFSET(tioca_common->ca_common.bs_base),
6101ee27a4eedf3cc08245d395936c1bfaf80c074ccJes Sorensen			sizeof(struct tioca_common));
6119c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6129c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/* init kernel-private area */
6139c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
614f96cb1f0580324b95b7219466312a376a59a796fPekka Enberg	tioca_kern = kzalloc(sizeof(struct tioca_kernel), GFP_KERNEL);
6159c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (!tioca_kern) {
6169c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		kfree(tioca_common);
6179c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return NULL;
6189c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
6199c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6209c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_common = tioca_common;
6219c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	spin_lock_init(&tioca_kern->ca_lock);
6229c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	INIT_LIST_HEAD(&tioca_kern->ca_dmamaps);
6239c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_closest_node =
6249c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	    nasid_to_cnodeid(tioca_common->ca_closest_nasid);
62553493dcf6e9e27cc9379cbf8962642986927aea9Prarit Bhargava	tioca_common->ca_kernel_private = (u64) tioca_kern;
6269c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
627674c6479b7bdc78528ea83dd43897e3161558b8bColin Ngam	bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
628674c6479b7bdc78528ea83dd43897e3161558b8bColin Ngam		tioca_common->ca_common.bs_persist_busnum);
6299c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	BUG_ON(!bus);
6309c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_kern->ca_devices = &bus->devices;
6319c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6329c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	/* init GART */
6339c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6349c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (tioca_gart_init(tioca_kern) < 0) {
6359c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		kfree(tioca_kern);
6369c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		kfree(tioca_common);
6379c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		return NULL;
6389c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	}
6399c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6409c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	tioca_gart_found++;
6419c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	list_add(&tioca_kern->ca_list, &tioca_list);
6429c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6439c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	if (request_irq(SGI_TIOCA_ERROR,
6449c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule			tioca_error_intr_handler,
645121a4226e89aae6654d667d58ab72df740b97b92Thomas Gleixner			IRQF_SHARED, "TIOCA error", (void *)tioca_common))
6469c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		printk(KERN_WARNING
6479c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		       "%s:  Unable to get irq %d.  "
6489c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		       "Error interrupts won't be routed for TIOCA bus %d\n",
649d4ed80841ad4a1d59decccfbe2d010558568c5fbHarvey Harrison		       __func__, SGI_TIOCA_ERROR,
6509c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule		       (int)tioca_common->ca_common.bs_persist_busnum);
6519c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
65248e30fa0738be3688f655632d917498464019e60Dimitri Sivanich	irq_set_handler(SGI_TIOCA_ERROR, handle_level_irq);
6536e9de18120988388cdae5097c09e774416d58745John Keller	sn_set_err_irq_affinity(SGI_TIOCA_ERROR);
6546e9de18120988388cdae5097c09e774416d58745John Keller
6557c2a6c62c013a4ea57243536fc7f3987e4ba04bcChristoph Lameter	/* Setup locality information */
6567c2a6c62c013a4ea57243536fc7f3987e4ba04bcChristoph Lameter	controller->node = tioca_kern->ca_closest_node;
6579c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return tioca_common;
6589c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
6599c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6609c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maulestatic struct sn_pcibus_provider tioca_pci_interfaces = {
6619c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	.dma_map = tioca_dma_map,
6629c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	.dma_map_consistent = tioca_dma_map,
6639c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	.dma_unmap = tioca_dma_unmap,
6649c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	.bus_fixup = tioca_bus_fixup,
6658409668b561fbe464f7a392e8dc77eca225d27acMark Maule	.force_interrupt = NULL,
6668409668b561fbe464f7a392e8dc77eca225d27acMark Maule	.target_interrupt = NULL
6679c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule};
6689c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule
6699c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule/**
6709c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule * tioca_init_provider - init SN PCI provider ops for TIO CA
6719c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule */
6729c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Mauleint
6739c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Mauletioca_init_provider(void)
6749c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule{
6759c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	sn_pci_provider[PCIIO_ASIC_TYPE_TIOCA] = &tioca_pci_interfaces;
6769c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule	return 0;
6779c90bdde77f7b7a42f7ebb900275d459ce2bac05Mark Maule}
678