bios_uv.c 4.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * BIOS run time interface routines.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 18 19
 *
 *  Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
 *  Copyright (c) Russ Anderson
20 21
 */

22 23 24
#include <linux/efi.h>
#include <asm/efi.h>
#include <linux/io.h>
25
#include <asm/uv/bios.h>
R
Russ Anderson 已提交
26
#include <asm/uv/uv_hub.h>
27

28 29 30
struct uv_systab uv_systab;

s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
31
{
32 33 34 35 36 37 38 39 40 41
	struct uv_systab *tab = &uv_systab;

	if (!tab->function)
		/*
		 * BIOS does not support UV systab
		 */
		return BIOS_STATUS_UNIMPLEMENTED;

	return efi_call6((void *)__va(tab->function),
					(u64)which, a1, a2, a3, a4, a5);
42 43
}

44 45
s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
					u64 a4, u64 a5)
46
{
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
	unsigned long bios_flags;
	s64 ret;

	local_irq_save(bios_flags);
	ret = uv_bios_call(which, a1, a2, a3, a4, a5);
	local_irq_restore(bios_flags);

	return ret;
}

s64 uv_bios_call_reentrant(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
					u64 a4, u64 a5)
{
	s64 ret;

	preempt_disable();
	ret = uv_bios_call(which, a1, a2, a3, a4, a5);
	preempt_enable();
65

66 67 68
	return ret;
}

R
Russ Anderson 已提交
69 70 71

long sn_partition_id;
EXPORT_SYMBOL_GPL(sn_partition_id);
72 73 74 75
long sn_coherency_id;
EXPORT_SYMBOL_GPL(sn_coherency_id);
long sn_region_size;
EXPORT_SYMBOL_GPL(sn_region_size);
R
Russ Anderson 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
int uv_type;


s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher,
		long *region)
{
	s64 ret;
	u64 v0, v1;
	union partition_info_u part;

	ret = uv_bios_call_irqsave(UV_BIOS_GET_SN_INFO, fc,
				(u64)(&v0), (u64)(&v1), 0, 0);
	if (ret != BIOS_STATUS_SUCCESS)
		return ret;

	part.val = v0;
	if (uvtype)
		*uvtype = part.hub_version;
	if (partid)
		*partid = part.partition_id;
	if (coher)
		*coher = part.coherence_id;
	if (region)
		*region = part.region_size;
	return ret;
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
int
uv_bios_mq_watchlist_alloc(int blade, void *mq, unsigned int mq_size,
			   unsigned long *intr_mmr_offset)
{
	union uv_watchlist_u size_blade;
	unsigned long addr;
	u64 watchlist;
	s64 ret;

	addr = (unsigned long)mq;
	size_blade.size = mq_size;
	size_blade.blade = blade;

	/*
	 * bios returns watchlist number or negative error number.
	 */
	ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr,
			size_blade.val, (u64)intr_mmr_offset,
			(u64)&watchlist, 0);
	if (ret < BIOS_STATUS_SUCCESS)
		return ret;

	return watchlist;
}
EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_alloc);

int
uv_bios_mq_watchlist_free(int blade, int watchlist_num)
{
	return (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_FREE,
				blade, watchlist_num, 0, 0, 0);
}
EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_free);
R
Russ Anderson 已提交
136

137 138 139 140 141 142 143 144
s64
uv_bios_change_memprotect(u64 paddr, u64 len, enum uv_memprotect perms)
{
	return uv_bios_call_irqsave(UV_BIOS_MEMPROTECT, paddr, len,
					perms, 0, 0);
}
EXPORT_SYMBOL_GPL(uv_bios_change_memprotect);

R
Russ Anderson 已提交
145
s64 uv_bios_freq_base(u64 clock_type, u64 *ticks_per_second)
146 147
{
	return uv_bios_call(UV_BIOS_FREQ_BASE, clock_type,
R
Russ Anderson 已提交
148
			   (u64)ticks_per_second, 0, 0, 0);
149
}
R
Russ Anderson 已提交
150
EXPORT_SYMBOL_GPL(uv_bios_freq_base);
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182


#ifdef CONFIG_EFI
void uv_bios_init(void)
{
	struct uv_systab *tab;

	if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) ||
	    (efi.uv_systab == (unsigned long)NULL)) {
		printk(KERN_CRIT "No EFI UV System Table.\n");
		uv_systab.function = (unsigned long)NULL;
		return;
	}

	tab = (struct uv_systab *)ioremap(efi.uv_systab,
					sizeof(struct uv_systab));
	if (strncmp(tab->signature, "UVST", 4) != 0)
		printk(KERN_ERR "bad signature in UV system table!");

	/*
	 * Copy table to permanent spot for later use.
	 */
	memcpy(&uv_systab, tab, sizeof(struct uv_systab));
	iounmap(tab);

	printk(KERN_INFO "EFI UV System Table Revision %d\n", tab->revision);
}
#else	/* !CONFIG_EFI */

void uv_bios_init(void) { }
#endif