diff options
Diffstat (limited to 'arch/ia64/sn')
24 files changed, 343 insertions, 383 deletions
diff --git a/arch/ia64/sn/Makefile b/arch/ia64/sn/Makefile index a269f6d84c29..79a7df02e812 100644 --- a/arch/ia64/sn/Makefile +++ b/arch/ia64/sn/Makefile | |||
@@ -9,6 +9,4 @@ | |||
9 | # Makefile for the sn ia64 subplatform | 9 | # Makefile for the sn ia64 subplatform |
10 | # | 10 | # |
11 | 11 | ||
12 | CPPFLAGS += -I$(srctree)/arch/ia64/sn/include | ||
13 | |||
14 | obj-y += kernel/ pci/ | 12 | obj-y += kernel/ pci/ |
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 4351c4ff9845..3e9b4eea7418 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile | |||
@@ -7,6 +7,8 @@ | |||
7 | # Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved. | 7 | # Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved. |
8 | # | 8 | # |
9 | 9 | ||
10 | CPPFLAGS += -I$(srctree)/arch/ia64/sn/include | ||
11 | |||
10 | obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ | 12 | obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ |
11 | huberror.o io_init.o iomv.o klconflib.o sn2/ | 13 | huberror.o io_init.o iomv.o klconflib.o sn2/ |
12 | obj-$(CONFIG_IA64_GENERIC) += machvec.o | 14 | obj-$(CONFIG_IA64_GENERIC) += machvec.o |
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index dd73c0cb754b..1f11db470d90 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/config.h> | 9 | #include <linux/config.h> |
@@ -186,18 +186,13 @@ retry_bteop: | |||
186 | 186 | ||
187 | /* Initialize the notification to a known value. */ | 187 | /* Initialize the notification to a known value. */ |
188 | *bte->most_rcnt_na = BTE_WORD_BUSY; | 188 | *bte->most_rcnt_na = BTE_WORD_BUSY; |
189 | notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)); | 189 | notif_phys_addr = (u64)bte->most_rcnt_na; |
190 | 190 | ||
191 | if (is_shub2()) { | ||
192 | src = SH2_TIO_PHYS_TO_DMA(src); | ||
193 | dest = SH2_TIO_PHYS_TO_DMA(dest); | ||
194 | notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr); | ||
195 | } | ||
196 | /* Set the source and destination registers */ | 191 | /* Set the source and destination registers */ |
197 | BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src)))); | 192 | BTE_PRINTKV(("IBSA = 0x%lx)\n", src)); |
198 | BTE_SRC_STORE(bte, TO_PHYS(src)); | 193 | BTE_SRC_STORE(bte, src); |
199 | BTE_PRINTKV(("IBDA = 0x%lx)\n", (TO_PHYS(dest)))); | 194 | BTE_PRINTKV(("IBDA = 0x%lx)\n", dest)); |
200 | BTE_DEST_STORE(bte, TO_PHYS(dest)); | 195 | BTE_DEST_STORE(bte, dest); |
201 | 196 | ||
202 | /* Set the notification register */ | 197 | /* Set the notification register */ |
203 | BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr)); | 198 | BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr)); |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 00700f7e6837..dfb3f2902379 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/nodemask.h> | 10 | #include <linux/nodemask.h> |
11 | #include <asm/sn/types.h> | 11 | #include <asm/sn/types.h> |
12 | #include <asm/sn/addrs.h> | 12 | #include <asm/sn/addrs.h> |
13 | #include <asm/sn/sn_feature_sets.h> | ||
13 | #include <asm/sn/geo.h> | 14 | #include <asm/sn/geo.h> |
14 | #include <asm/sn/io.h> | 15 | #include <asm/sn/io.h> |
15 | #include <asm/sn/pcibr_provider.h> | 16 | #include <asm/sn/pcibr_provider.h> |
@@ -22,6 +23,10 @@ | |||
22 | #include "xtalk/hubdev.h" | 23 | #include "xtalk/hubdev.h" |
23 | #include "xtalk/xwidgetdev.h" | 24 | #include "xtalk/xwidgetdev.h" |
24 | 25 | ||
26 | |||
27 | extern void sn_init_cpei_timer(void); | ||
28 | extern void register_sn_procfs(void); | ||
29 | |||
25 | static struct list_head sn_sysdata_list; | 30 | static struct list_head sn_sysdata_list; |
26 | 31 | ||
27 | /* sysdata list struct */ | 32 | /* sysdata list struct */ |
@@ -39,12 +44,12 @@ struct brick { | |||
39 | struct slab_info slab_info[MAX_SLABS + 1]; | 44 | struct slab_info slab_info[MAX_SLABS + 1]; |
40 | }; | 45 | }; |
41 | 46 | ||
42 | int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ | 47 | int sn_ioif_inited; /* SN I/O infrastructure initialized? */ |
43 | 48 | ||
44 | struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ | 49 | struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ |
45 | 50 | ||
46 | static int max_segment_number = 0; /* Default highest segment number */ | 51 | static int max_segment_number; /* Default highest segment number */ |
47 | static int max_pcibus_number = 255; /* Default highest pci bus number */ | 52 | static int max_pcibus_number = 255; /* Default highest pci bus number */ |
48 | 53 | ||
49 | /* | 54 | /* |
50 | * Hooks and struct for unsupported pci providers | 55 | * Hooks and struct for unsupported pci providers |
@@ -83,7 +88,6 @@ static inline u64 | |||
83 | sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, | 88 | sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, |
84 | u64 address) | 89 | u64 address) |
85 | { | 90 | { |
86 | |||
87 | struct ia64_sal_retval ret_stuff; | 91 | struct ia64_sal_retval ret_stuff; |
88 | ret_stuff.status = 0; | 92 | ret_stuff.status = 0; |
89 | ret_stuff.v0 = 0; | 93 | ret_stuff.v0 = 0; |
@@ -93,7 +97,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, | |||
93 | (u64) nasid, (u64) widget_num, | 97 | (u64) nasid, (u64) widget_num, |
94 | (u64) device_num, (u64) address, 0, 0, 0); | 98 | (u64) device_num, (u64) address, 0, 0, 0); |
95 | return ret_stuff.status; | 99 | return ret_stuff.status; |
96 | |||
97 | } | 100 | } |
98 | 101 | ||
99 | /* | 102 | /* |
@@ -101,7 +104,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, | |||
101 | */ | 104 | */ |
102 | static inline u64 sal_get_hubdev_info(u64 handle, u64 address) | 105 | static inline u64 sal_get_hubdev_info(u64 handle, u64 address) |
103 | { | 106 | { |
104 | |||
105 | struct ia64_sal_retval ret_stuff; | 107 | struct ia64_sal_retval ret_stuff; |
106 | ret_stuff.status = 0; | 108 | ret_stuff.status = 0; |
107 | ret_stuff.v0 = 0; | 109 | ret_stuff.v0 = 0; |
@@ -117,7 +119,6 @@ static inline u64 sal_get_hubdev_info(u64 handle, u64 address) | |||
117 | */ | 119 | */ |
118 | static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) | 120 | static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) |
119 | { | 121 | { |
120 | |||
121 | struct ia64_sal_retval ret_stuff; | 122 | struct ia64_sal_retval ret_stuff; |
122 | ret_stuff.status = 0; | 123 | ret_stuff.status = 0; |
123 | ret_stuff.v0 = 0; | 124 | ret_stuff.v0 = 0; |
@@ -173,8 +174,8 @@ sn_pcidev_info_get(struct pci_dev *dev) | |||
173 | */ | 174 | */ |
174 | static u8 war_implemented = 0; | 175 | static u8 war_implemented = 0; |
175 | 176 | ||
176 | static void sn_device_fixup_war(u64 nasid, u64 widget, int device, | 177 | static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, |
177 | struct sn_flush_device_common *common) | 178 | struct sn_flush_device_common *common) |
178 | { | 179 | { |
179 | struct sn_flush_device_war *war_list; | 180 | struct sn_flush_device_war *war_list; |
180 | struct sn_flush_device_war *dev_entry; | 181 | struct sn_flush_device_war *dev_entry; |
@@ -198,22 +199,23 @@ static void sn_device_fixup_war(u64 nasid, u64 widget, int device, | |||
198 | 199 | ||
199 | dev_entry = war_list + device; | 200 | dev_entry = war_list + device; |
200 | memcpy(common,dev_entry, sizeof(*common)); | 201 | memcpy(common,dev_entry, sizeof(*common)); |
201 | |||
202 | kfree(war_list); | 202 | kfree(war_list); |
203 | |||
204 | return isrv.status; | ||
203 | } | 205 | } |
204 | 206 | ||
205 | /* | 207 | /* |
206 | * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for | 208 | * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for |
207 | * each node in the system. | 209 | * each node in the system. |
208 | */ | 210 | */ |
209 | static void sn_fixup_ionodes(void) | 211 | static void __init sn_fixup_ionodes(void) |
210 | { | 212 | { |
211 | struct sn_flush_device_kernel *sn_flush_device_kernel; | 213 | struct sn_flush_device_kernel *sn_flush_device_kernel; |
212 | struct sn_flush_device_kernel *dev_entry; | 214 | struct sn_flush_device_kernel *dev_entry; |
213 | struct hubdev_info *hubdev; | 215 | struct hubdev_info *hubdev; |
214 | u64 status; | 216 | u64 status; |
215 | u64 nasid; | 217 | u64 nasid; |
216 | int i, widget, device; | 218 | int i, widget, device, size; |
217 | 219 | ||
218 | /* | 220 | /* |
219 | * Get SGI Specific HUB chipset information. | 221 | * Get SGI Specific HUB chipset information. |
@@ -249,53 +251,40 @@ static void sn_fixup_ionodes(void) | |||
249 | if (!hubdev->hdi_flush_nasid_list.widget_p) | 251 | if (!hubdev->hdi_flush_nasid_list.widget_p) |
250 | continue; | 252 | continue; |
251 | 253 | ||
254 | size = (HUB_WIDGET_ID_MAX + 1) * | ||
255 | sizeof(struct sn_flush_device_kernel *); | ||
252 | hubdev->hdi_flush_nasid_list.widget_p = | 256 | hubdev->hdi_flush_nasid_list.widget_p = |
253 | kmalloc((HUB_WIDGET_ID_MAX + 1) * | 257 | kzalloc(size, GFP_KERNEL); |
254 | sizeof(struct sn_flush_device_kernel *), | 258 | if (!hubdev->hdi_flush_nasid_list.widget_p) |
255 | GFP_KERNEL); | 259 | BUG(); |
256 | memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, | ||
257 | (HUB_WIDGET_ID_MAX + 1) * | ||
258 | sizeof(struct sn_flush_device_kernel *)); | ||
259 | 260 | ||
260 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { | 261 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { |
261 | sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET * | 262 | size = DEV_PER_WIDGET * |
262 | sizeof(struct | 263 | sizeof(struct sn_flush_device_kernel); |
263 | sn_flush_device_kernel), | 264 | sn_flush_device_kernel = kzalloc(size, GFP_KERNEL); |
264 | GFP_KERNEL); | ||
265 | if (!sn_flush_device_kernel) | 265 | if (!sn_flush_device_kernel) |
266 | BUG(); | 266 | BUG(); |
267 | memset(sn_flush_device_kernel, 0x0, | ||
268 | DEV_PER_WIDGET * | ||
269 | sizeof(struct sn_flush_device_kernel)); | ||
270 | 267 | ||
271 | dev_entry = sn_flush_device_kernel; | 268 | dev_entry = sn_flush_device_kernel; |
272 | for (device = 0; device < DEV_PER_WIDGET; | 269 | for (device = 0; device < DEV_PER_WIDGET; |
273 | device++,dev_entry++) { | 270 | device++,dev_entry++) { |
274 | dev_entry->common = kmalloc(sizeof(struct | 271 | size = sizeof(struct sn_flush_device_common); |
275 | sn_flush_device_common), | 272 | dev_entry->common = kzalloc(size, GFP_KERNEL); |
276 | GFP_KERNEL); | ||
277 | if (!dev_entry->common) | 273 | if (!dev_entry->common) |
278 | BUG(); | 274 | BUG(); |
279 | memset(dev_entry->common, 0x0, sizeof(struct | 275 | |
280 | sn_flush_device_common)); | 276 | if (sn_prom_feature_available( |
281 | 277 | PRF_DEVICE_FLUSH_LIST)) | |
282 | status = sal_get_device_dmaflush_list(nasid, | 278 | status = sal_get_device_dmaflush_list( |
283 | widget, | 279 | nasid, widget, device, |
284 | device, | 280 | (u64)(dev_entry->common)); |
285 | (u64)(dev_entry->common)); | 281 | else |
286 | if (status) { | 282 | status = sn_device_fixup_war(nasid, |
287 | if (sn_sal_rev() < 0x0450) { | 283 | widget, device, |
288 | /* shortlived WAR for older | 284 | dev_entry->common); |
289 | * PROM images | 285 | if (status != SALRET_OK) |
290 | */ | 286 | panic("SAL call failed: %s\n", |
291 | sn_device_fixup_war(nasid, | 287 | ia64_sal_strerror(status)); |
292 | widget, | ||
293 | device, | ||
294 | dev_entry->common); | ||
295 | } | ||
296 | else | ||
297 | BUG(); | ||
298 | } | ||
299 | 288 | ||
300 | spin_lock_init(&dev_entry->sfdl_flush_lock); | 289 | spin_lock_init(&dev_entry->sfdl_flush_lock); |
301 | } | 290 | } |
@@ -383,13 +372,12 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
383 | 372 | ||
384 | pci_dev_get(dev); /* for the sysdata pointer */ | 373 | pci_dev_get(dev); /* for the sysdata pointer */ |
385 | pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); | 374 | pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); |
386 | if (pcidev_info <= 0) | 375 | if (!pcidev_info) |
387 | BUG(); /* Cannot afford to run out of memory */ | 376 | BUG(); /* Cannot afford to run out of memory */ |
388 | 377 | ||
389 | sn_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_KERNEL); | 378 | sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); |
390 | if (sn_irq_info <= 0) | 379 | if (!sn_irq_info) |
391 | BUG(); /* Cannot afford to run out of memory */ | 380 | BUG(); /* Cannot afford to run out of memory */ |
392 | memset(sn_irq_info, 0, sizeof(struct sn_irq_info)); | ||
393 | 381 | ||
394 | /* Call to retrieve pci device information needed by kernel. */ | 382 | /* Call to retrieve pci device information needed by kernel. */ |
395 | status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, | 383 | status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, |
@@ -467,6 +455,13 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
467 | pcidev_info->pdi_sn_irq_info = NULL; | 455 | pcidev_info->pdi_sn_irq_info = NULL; |
468 | kfree(sn_irq_info); | 456 | kfree(sn_irq_info); |
469 | } | 457 | } |
458 | |||
459 | /* | ||
460 | * MSI currently not supported on altix. Remove this when | ||
461 | * the MSI abstraction patches are integrated into the kernel | ||
462 | * (sometime after 2.6.16 releases) | ||
463 | */ | ||
464 | dev->no_msi = 1; | ||
470 | } | 465 | } |
471 | 466 | ||
472 | /* | 467 | /* |
@@ -475,13 +470,13 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
475 | */ | 470 | */ |
476 | void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | 471 | void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) |
477 | { | 472 | { |
478 | int status = 0; | 473 | int status; |
479 | int nasid, cnode; | 474 | int nasid, cnode; |
480 | struct pci_controller *controller; | 475 | struct pci_controller *controller; |
481 | struct sn_pci_controller *sn_controller; | 476 | struct sn_pci_controller *sn_controller; |
482 | struct pcibus_bussoft *prom_bussoft_ptr; | 477 | struct pcibus_bussoft *prom_bussoft_ptr; |
483 | struct hubdev_info *hubdev_info; | 478 | struct hubdev_info *hubdev_info; |
484 | void *provider_soft = NULL; | 479 | void *provider_soft; |
485 | struct sn_pcibus_provider *provider; | 480 | struct sn_pcibus_provider *provider; |
486 | 481 | ||
487 | status = sal_get_pcibus_info((u64) segment, (u64) busnum, | 482 | status = sal_get_pcibus_info((u64) segment, (u64) busnum, |
@@ -528,6 +523,8 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
528 | bus->sysdata = controller; | 523 | bus->sysdata = controller; |
529 | if (provider->bus_fixup) | 524 | if (provider->bus_fixup) |
530 | provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller); | 525 | provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller); |
526 | else | ||
527 | provider_soft = NULL; | ||
531 | 528 | ||
532 | if (provider_soft == NULL) { | 529 | if (provider_soft == NULL) { |
533 | /* fixup failed or not applicable */ | 530 | /* fixup failed or not applicable */ |
@@ -610,15 +607,15 @@ void sn_bus_store_sysdata(struct pci_dev *dev) | |||
610 | void sn_bus_free_sysdata(void) | 607 | void sn_bus_free_sysdata(void) |
611 | { | 608 | { |
612 | struct sysdata_el *element; | 609 | struct sysdata_el *element; |
613 | struct list_head *list; | 610 | struct list_head *list, *safe; |
614 | 611 | ||
615 | sn_sysdata_free_start: | 612 | list_for_each_safe(list, safe, &sn_sysdata_list) { |
616 | list_for_each(list, &sn_sysdata_list) { | ||
617 | element = list_entry(list, struct sysdata_el, entry); | 613 | element = list_entry(list, struct sysdata_el, entry); |
618 | list_del(&element->entry); | 614 | list_del(&element->entry); |
615 | list_del(&(((struct pcidev_info *) | ||
616 | (element->sysdata))->pdi_list)); | ||
619 | kfree(element->sysdata); | 617 | kfree(element->sysdata); |
620 | kfree(element); | 618 | kfree(element); |
621 | goto sn_sysdata_free_start; | ||
622 | } | 619 | } |
623 | return; | 620 | return; |
624 | } | 621 | } |
@@ -631,13 +628,8 @@ sn_sysdata_free_start: | |||
631 | 628 | ||
632 | static int __init sn_pci_init(void) | 629 | static int __init sn_pci_init(void) |
633 | { | 630 | { |
634 | int i = 0; | 631 | int i, j; |
635 | int j = 0; | ||
636 | struct pci_dev *pci_dev = NULL; | 632 | struct pci_dev *pci_dev = NULL; |
637 | extern void sn_init_cpei_timer(void); | ||
638 | #ifdef CONFIG_PROC_FS | ||
639 | extern void register_sn_procfs(void); | ||
640 | #endif | ||
641 | 633 | ||
642 | if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) | 634 | if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) |
643 | return 0; | 635 | return 0; |
@@ -693,32 +685,29 @@ static int __init sn_pci_init(void) | |||
693 | */ | 685 | */ |
694 | void hubdev_init_node(nodepda_t * npda, cnodeid_t node) | 686 | void hubdev_init_node(nodepda_t * npda, cnodeid_t node) |
695 | { | 687 | { |
696 | |||
697 | struct hubdev_info *hubdev_info; | 688 | struct hubdev_info *hubdev_info; |
689 | int size; | ||
690 | pg_data_t *pg; | ||
691 | |||
692 | size = sizeof(struct hubdev_info); | ||
698 | 693 | ||
699 | if (node >= num_online_nodes()) /* Headless/memless IO nodes */ | 694 | if (node >= num_online_nodes()) /* Headless/memless IO nodes */ |
700 | hubdev_info = | 695 | pg = NODE_DATA(0); |
701 | (struct hubdev_info *)alloc_bootmem_node(NODE_DATA(0), | ||
702 | sizeof(struct | ||
703 | hubdev_info)); | ||
704 | else | 696 | else |
705 | hubdev_info = | 697 | pg = NODE_DATA(node); |
706 | (struct hubdev_info *)alloc_bootmem_node(NODE_DATA(node), | 698 | |
707 | sizeof(struct | 699 | hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size); |
708 | hubdev_info)); | ||
709 | npda->pdinfo = (void *)hubdev_info; | ||
710 | 700 | ||
701 | npda->pdinfo = (void *)hubdev_info; | ||
711 | } | 702 | } |
712 | 703 | ||
713 | geoid_t | 704 | geoid_t |
714 | cnodeid_get_geoid(cnodeid_t cnode) | 705 | cnodeid_get_geoid(cnodeid_t cnode) |
715 | { | 706 | { |
716 | |||
717 | struct hubdev_info *hubdev; | 707 | struct hubdev_info *hubdev; |
718 | 708 | ||
719 | hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); | 709 | hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); |
720 | return hubdev->hdi_geoid; | 710 | return hubdev->hdi_geoid; |
721 | |||
722 | } | 711 | } |
723 | 712 | ||
724 | subsys_initcall(sn_pci_init); | 713 | subsys_initcall(sn_pci_init); |
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index ec37084bdc17..c373113d073a 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c | |||
@@ -5,11 +5,12 @@ | |||
5 | * License. See the file "COPYING" in the main directory of this archive | 5 | * License. See the file "COPYING" in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | * | 7 | * |
8 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. | 8 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/init.h> | ||
13 | #include <asm/sn/addrs.h> | 14 | #include <asm/sn/addrs.h> |
14 | #include <asm/sn/arch.h> | 15 | #include <asm/sn/arch.h> |
15 | #include <asm/sn/intr.h> | 16 | #include <asm/sn/intr.h> |
@@ -76,17 +77,15 @@ static void sn_enable_irq(unsigned int irq) | |||
76 | 77 | ||
77 | static void sn_ack_irq(unsigned int irq) | 78 | static void sn_ack_irq(unsigned int irq) |
78 | { | 79 | { |
79 | u64 event_occurred, mask = 0; | 80 | u64 event_occurred, mask; |
80 | 81 | ||
81 | irq = irq & 0xff; | 82 | irq = irq & 0xff; |
82 | event_occurred = | 83 | event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); |
83 | HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); | ||
84 | mask = event_occurred & SH_ALL_INT_MASK; | 84 | mask = event_occurred & SH_ALL_INT_MASK; |
85 | HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), | 85 | HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask); |
86 | mask); | ||
87 | __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); | 86 | __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); |
88 | 87 | ||
89 | move_irq(irq); | 88 | move_native_irq(irq); |
90 | } | 89 | } |
91 | 90 | ||
92 | static void sn_end_irq(unsigned int irq) | 91 | static void sn_end_irq(unsigned int irq) |
@@ -219,9 +218,8 @@ static void register_intr_pda(struct sn_irq_info *sn_irq_info) | |||
219 | pdacpu(cpu)->sn_last_irq = irq; | 218 | pdacpu(cpu)->sn_last_irq = irq; |
220 | } | 219 | } |
221 | 220 | ||
222 | if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) { | 221 | if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) |
223 | pdacpu(cpu)->sn_first_irq = irq; | 222 | pdacpu(cpu)->sn_first_irq = irq; |
224 | } | ||
225 | } | 223 | } |
226 | 224 | ||
227 | static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) | 225 | static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) |
@@ -289,7 +287,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) | |||
289 | list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); | 287 | list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); |
290 | spin_unlock(&sn_irq_info_lock); | 288 | spin_unlock(&sn_irq_info_lock); |
291 | 289 | ||
292 | (void)register_intr_pda(sn_irq_info); | 290 | register_intr_pda(sn_irq_info); |
293 | } | 291 | } |
294 | 292 | ||
295 | void sn_irq_unfixup(struct pci_dev *pci_dev) | 293 | void sn_irq_unfixup(struct pci_dev *pci_dev) |
@@ -301,7 +299,9 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) | |||
301 | return; | 299 | return; |
302 | 300 | ||
303 | sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info; | 301 | sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info; |
304 | if (!sn_irq_info || !sn_irq_info->irq_irq) { | 302 | if (!sn_irq_info) |
303 | return; | ||
304 | if (!sn_irq_info->irq_irq) { | ||
305 | kfree(sn_irq_info); | 305 | kfree(sn_irq_info); |
306 | return; | 306 | return; |
307 | } | 307 | } |
@@ -419,7 +419,7 @@ void sn_lb_int_war_check(void) | |||
419 | rcu_read_unlock(); | 419 | rcu_read_unlock(); |
420 | } | 420 | } |
421 | 421 | ||
422 | void sn_irq_lh_init(void) | 422 | void __init sn_irq_lh_init(void) |
423 | { | 423 | { |
424 | int i; | 424 | int i; |
425 | 425 | ||
@@ -434,5 +434,4 @@ void sn_irq_lh_init(void) | |||
434 | 434 | ||
435 | INIT_LIST_HEAD(sn_irq_lh[i]); | 435 | INIT_LIST_HEAD(sn_irq_lh[i]); |
436 | } | 436 | } |
437 | |||
438 | } | 437 | } |
diff --git a/arch/ia64/sn/kernel/klconflib.c b/arch/ia64/sn/kernel/klconflib.c index 0f11a3299cd2..87682b48ef83 100644 --- a/arch/ia64/sn/kernel/klconflib.c +++ b/arch/ia64/sn/kernel/klconflib.c | |||
@@ -78,31 +78,30 @@ format_module_id(char *buffer, moduleid_t m, int fmt) | |||
78 | position = MODULE_GET_BPOS(m); | 78 | position = MODULE_GET_BPOS(m); |
79 | 79 | ||
80 | if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) { | 80 | if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) { |
81 | /* Brief module number format, eg. 002c15 */ | 81 | /* Brief module number format, eg. 002c15 */ |
82 | 82 | ||
83 | /* Decompress the rack number */ | 83 | /* Decompress the rack number */ |
84 | *buffer++ = '0' + RACK_GET_CLASS(rack); | 84 | *buffer++ = '0' + RACK_GET_CLASS(rack); |
85 | *buffer++ = '0' + RACK_GET_GROUP(rack); | 85 | *buffer++ = '0' + RACK_GET_GROUP(rack); |
86 | *buffer++ = '0' + RACK_GET_NUM(rack); | 86 | *buffer++ = '0' + RACK_GET_NUM(rack); |
87 | 87 | ||
88 | /* Add the brick type */ | 88 | /* Add the brick type */ |
89 | *buffer++ = brickchar; | 89 | *buffer++ = brickchar; |
90 | } | 90 | } |
91 | else if (fmt == MODULE_FORMAT_LONG) { | 91 | else if (fmt == MODULE_FORMAT_LONG) { |
92 | /* Fuller hwgraph format, eg. rack/002/bay/15 */ | 92 | /* Fuller hwgraph format, eg. rack/002/bay/15 */ |
93 | 93 | ||
94 | strcpy(buffer, "rack" "/"); buffer += strlen(buffer); | 94 | strcpy(buffer, "rack" "/"); buffer += strlen(buffer); |
95 | 95 | ||
96 | *buffer++ = '0' + RACK_GET_CLASS(rack); | 96 | *buffer++ = '0' + RACK_GET_CLASS(rack); |
97 | *buffer++ = '0' + RACK_GET_GROUP(rack); | 97 | *buffer++ = '0' + RACK_GET_GROUP(rack); |
98 | *buffer++ = '0' + RACK_GET_NUM(rack); | 98 | *buffer++ = '0' + RACK_GET_NUM(rack); |
99 | 99 | ||
100 | strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer); | 100 | strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer); |
101 | } | 101 | } |
102 | 102 | ||
103 | /* Add the bay position, using at least two digits */ | 103 | /* Add the bay position, using at least two digits */ |
104 | if (position < 10) | 104 | if (position < 10) |
105 | *buffer++ = '0'; | 105 | *buffer++ = '0'; |
106 | sprintf(buffer, "%d", position); | 106 | sprintf(buffer, "%d", position); |
107 | |||
108 | } | 107 | } |
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c index 9ab684d1bb55..3db62f24596c 100644 --- a/arch/ia64/sn/kernel/mca.c +++ b/arch/ia64/sn/kernel/mca.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
@@ -137,7 +137,8 @@ int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdat | |||
137 | 137 | ||
138 | static int __init sn_salinfo_init(void) | 138 | static int __init sn_salinfo_init(void) |
139 | { | 139 | { |
140 | salinfo_platform_oemdata = &sn_salinfo_platform_oemdata; | 140 | if (ia64_platform_is("sn2")) |
141 | salinfo_platform_oemdata = &sn_salinfo_platform_oemdata; | ||
141 | return 0; | 142 | return 0; |
142 | } | 143 | } |
143 | 144 | ||
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index e510dce9971f..5b84836c2171 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c | |||
@@ -67,6 +67,7 @@ extern unsigned long last_time_offset; | |||
67 | extern void (*ia64_mark_idle) (int); | 67 | extern void (*ia64_mark_idle) (int); |
68 | extern void snidle(int); | 68 | extern void snidle(int); |
69 | extern unsigned char acpi_kbd_controller_present; | 69 | extern unsigned char acpi_kbd_controller_present; |
70 | extern unsigned long long (*ia64_printk_clock)(void); | ||
70 | 71 | ||
71 | unsigned long sn_rtc_cycles_per_second; | 72 | unsigned long sn_rtc_cycles_per_second; |
72 | EXPORT_SYMBOL(sn_rtc_cycles_per_second); | 73 | EXPORT_SYMBOL(sn_rtc_cycles_per_second); |
@@ -74,7 +75,7 @@ EXPORT_SYMBOL(sn_rtc_cycles_per_second); | |||
74 | DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); | 75 | DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); |
75 | EXPORT_PER_CPU_SYMBOL(__sn_hub_info); | 76 | EXPORT_PER_CPU_SYMBOL(__sn_hub_info); |
76 | 77 | ||
77 | DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]); | 78 | DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]); |
78 | EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid); | 79 | EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid); |
79 | 80 | ||
80 | DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); | 81 | DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); |
@@ -125,20 +126,6 @@ struct screen_info sn_screen_info = { | |||
125 | }; | 126 | }; |
126 | 127 | ||
127 | /* | 128 | /* |
128 | * This is here so we can use the CMOS detection in ide-probe.c to | ||
129 | * determine what drives are present. In theory, we don't need this | ||
130 | * as the auto-detection could be done via ide-probe.c:do_probe() but | ||
131 | * in practice that would be much slower, which is painful when | ||
132 | * running in the simulator. Note that passing zeroes in DRIVE_INFO | ||
133 | * is sufficient (the IDE driver will autodetect the drive geometry). | ||
134 | */ | ||
135 | #ifdef CONFIG_IA64_GENERIC | ||
136 | extern char drive_info[4 * 16]; | ||
137 | #else | ||
138 | char drive_info[4 * 16]; | ||
139 | #endif | ||
140 | |||
141 | /* | ||
142 | * This routine can only be used during init, since | 129 | * This routine can only be used during init, since |
143 | * smp_boot_data is an init data structure. | 130 | * smp_boot_data is an init data structure. |
144 | * We have to use smp_boot_data.cpu_phys_id to find | 131 | * We have to use smp_boot_data.cpu_phys_id to find |
@@ -209,7 +196,7 @@ void __init early_sn_setup(void) | |||
209 | } | 196 | } |
210 | 197 | ||
211 | extern int platform_intr_list[]; | 198 | extern int platform_intr_list[]; |
212 | static int __initdata shub_1_1_found = 0; | 199 | static int __initdata shub_1_1_found; |
213 | 200 | ||
214 | /* | 201 | /* |
215 | * sn_check_for_wars | 202 | * sn_check_for_wars |
@@ -330,6 +317,7 @@ struct pcdp_vga_device { | |||
330 | #define PCDP_PCI_TRANS_IOPORT 0x02 | 317 | #define PCDP_PCI_TRANS_IOPORT 0x02 |
331 | #define PCDP_PCI_TRANS_MMIO 0x01 | 318 | #define PCDP_PCI_TRANS_MMIO 0x01 |
332 | 319 | ||
320 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) | ||
333 | static void | 321 | static void |
334 | sn_scan_pcdp(void) | 322 | sn_scan_pcdp(void) |
335 | { | 323 | { |
@@ -371,6 +359,17 @@ sn_scan_pcdp(void) | |||
371 | break; /* once we find the primary, we're done */ | 359 | break; /* once we find the primary, we're done */ |
372 | } | 360 | } |
373 | } | 361 | } |
362 | #endif | ||
363 | |||
364 | static unsigned long sn2_rtc_initial; | ||
365 | |||
366 | static unsigned long long ia64_sn2_printk_clock(void) | ||
367 | { | ||
368 | unsigned long rtc_now = rtc_time(); | ||
369 | |||
370 | return (rtc_now - sn2_rtc_initial) * | ||
371 | (1000000000 / sn_rtc_cycles_per_second); | ||
372 | } | ||
374 | 373 | ||
375 | /** | 374 | /** |
376 | * sn_setup - SN platform setup routine | 375 | * sn_setup - SN platform setup routine |
@@ -386,6 +385,7 @@ void __init sn_setup(char **cmdline_p) | |||
386 | u32 version = sn_sal_rev(); | 385 | u32 version = sn_sal_rev(); |
387 | extern void sn_cpu_init(void); | 386 | extern void sn_cpu_init(void); |
388 | 387 | ||
388 | sn2_rtc_initial = rtc_time(); | ||
389 | ia64_sn_plat_set_error_handling_features(); // obsolete | 389 | ia64_sn_plat_set_error_handling_features(); // obsolete |
390 | ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV); | 390 | ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV); |
391 | ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES); | 391 | ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES); |
@@ -437,19 +437,6 @@ void __init sn_setup(char **cmdline_p) | |||
437 | */ | 437 | */ |
438 | build_cnode_tables(); | 438 | build_cnode_tables(); |
439 | 439 | ||
440 | /* | ||
441 | * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard | ||
442 | * support here so we don't have to listen to failed keyboard probe | ||
443 | * messages. | ||
444 | */ | ||
445 | if (version <= 0x0209 && acpi_kbd_controller_present) { | ||
446 | printk(KERN_INFO "Disabling legacy keyboard support as prom " | ||
447 | "is too old and doesn't provide FADT\n"); | ||
448 | acpi_kbd_controller_present = 0; | ||
449 | } | ||
450 | |||
451 | printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); | ||
452 | |||
453 | status = | 440 | status = |
454 | ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, | 441 | ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, |
455 | &drift); | 442 | &drift); |
@@ -463,6 +450,21 @@ void __init sn_setup(char **cmdline_p) | |||
463 | 450 | ||
464 | platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR; | 451 | platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR; |
465 | 452 | ||
453 | ia64_printk_clock = ia64_sn2_printk_clock; | ||
454 | |||
455 | /* | ||
456 | * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard | ||
457 | * support here so we don't have to listen to failed keyboard probe | ||
458 | * messages. | ||
459 | */ | ||
460 | if (version <= 0x0209 && acpi_kbd_controller_present) { | ||
461 | printk(KERN_INFO "Disabling legacy keyboard support as prom " | ||
462 | "is too old and doesn't provide FADT\n"); | ||
463 | acpi_kbd_controller_present = 0; | ||
464 | } | ||
465 | |||
466 | printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); | ||
467 | |||
466 | /* | 468 | /* |
467 | * we set the default root device to /dev/hda | 469 | * we set the default root device to /dev/hda |
468 | * to make simulation easy | 470 | * to make simulation easy |
@@ -578,13 +580,17 @@ void __init sn_cpu_init(void) | |||
578 | sn_prom_type = 2; | 580 | sn_prom_type = 2; |
579 | else | 581 | else |
580 | sn_prom_type = 1; | 582 | sn_prom_type = 1; |
581 | printk("Running on medusa with %s PROM\n", (sn_prom_type == 1) ? "real" : "fake"); | 583 | printk(KERN_INFO "Running on medusa with %s PROM\n", |
584 | (sn_prom_type == 1) ? "real" : "fake"); | ||
582 | } | 585 | } |
583 | 586 | ||
584 | memset(pda, 0, sizeof(pda)); | 587 | memset(pda, 0, sizeof(pda)); |
585 | if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift, | 588 | if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, |
586 | &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, | 589 | &sn_hub_info->nasid_bitmask, |
587 | &sn_coherency_id, &sn_region_size)) | 590 | &sn_hub_info->nasid_shift, |
591 | &sn_system_size, &sn_sharing_domain_size, | ||
592 | &sn_partition_id, &sn_coherency_id, | ||
593 | &sn_region_size)) | ||
588 | BUG(); | 594 | BUG(); |
589 | sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2; | 595 | sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2; |
590 | 596 | ||
@@ -716,7 +722,8 @@ void __init build_cnode_tables(void) | |||
716 | for_each_online_node(node) { | 722 | for_each_online_node(node) { |
717 | kl_config_hdr_t *klgraph_header; | 723 | kl_config_hdr_t *klgraph_header; |
718 | nasid = cnodeid_to_nasid(node); | 724 | nasid = cnodeid_to_nasid(node); |
719 | if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL) | 725 | klgraph_header = ia64_sn_get_klconfig_addr(nasid); |
726 | if (klgraph_header == NULL) | ||
720 | BUG(); | 727 | BUG(); |
721 | brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info); | 728 | brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info); |
722 | while (brd) { | 729 | while (brd) { |
@@ -734,7 +741,7 @@ nasid_slice_to_cpuid(int nasid, int slice) | |||
734 | { | 741 | { |
735 | long cpu; | 742 | long cpu; |
736 | 743 | ||
737 | for (cpu=0; cpu < NR_CPUS; cpu++) | 744 | for (cpu = 0; cpu < NR_CPUS; cpu++) |
738 | if (cpuid_to_nasid(cpu) == nasid && | 745 | if (cpuid_to_nasid(cpu) == nasid && |
739 | cpuid_to_slice(cpu) == slice) | 746 | cpuid_to_slice(cpu) == slice) |
740 | return cpu; | 747 | return cpu; |
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile index 170bde4549da..99e177693234 100644 --- a/arch/ia64/sn/kernel/sn2/Makefile +++ b/arch/ia64/sn/kernel/sn2/Makefile | |||
@@ -9,5 +9,7 @@ | |||
9 | # sn2 specific kernel files | 9 | # sn2 specific kernel files |
10 | # | 10 | # |
11 | 11 | ||
12 | CPPFLAGS += -I$(srctree)/arch/ia64/sn/include | ||
13 | |||
12 | obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ | 14 | obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ |
13 | prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o | 15 | prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o |
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c index 81c63b2f8ae9..6ae276d5d50c 100644 --- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c +++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (C) 1999,2001-2004, 2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | * | 7 | * |
8 | * Module to export the system's Firmware Interface Tables, including | 8 | * Module to export the system's Firmware Interface Tables, including |
9 | * PROM revision numbers and banners, in /proc | 9 | * PROM revision numbers and banners, in /proc |
@@ -190,7 +190,7 @@ static int | |||
190 | read_version_entry(char *page, char **start, off_t off, int count, int *eof, | 190 | read_version_entry(char *page, char **start, off_t off, int count, int *eof, |
191 | void *data) | 191 | void *data) |
192 | { | 192 | { |
193 | int len = 0; | 193 | int len; |
194 | 194 | ||
195 | /* data holds the NASID of the node */ | 195 | /* data holds the NASID of the node */ |
196 | len = dump_version(page, (unsigned long)data); | 196 | len = dump_version(page, (unsigned long)data); |
@@ -202,7 +202,7 @@ static int | |||
202 | read_fit_entry(char *page, char **start, off_t off, int count, int *eof, | 202 | read_fit_entry(char *page, char **start, off_t off, int count, int *eof, |
203 | void *data) | 203 | void *data) |
204 | { | 204 | { |
205 | int len = 0; | 205 | int len; |
206 | 206 | ||
207 | /* data holds the NASID of the node */ | 207 | /* data holds the NASID of the node */ |
208 | len = dump_fit(page, (unsigned long)data); | 208 | len = dump_fit(page, (unsigned long)data); |
@@ -229,13 +229,16 @@ int __init prominfo_init(void) | |||
229 | struct proc_dir_entry *p; | 229 | struct proc_dir_entry *p; |
230 | cnodeid_t cnodeid; | 230 | cnodeid_t cnodeid; |
231 | unsigned long nasid; | 231 | unsigned long nasid; |
232 | int size; | ||
232 | char name[NODE_NAME_LEN]; | 233 | char name[NODE_NAME_LEN]; |
233 | 234 | ||
234 | if (!ia64_platform_is("sn2")) | 235 | if (!ia64_platform_is("sn2")) |
235 | return 0; | 236 | return 0; |
236 | 237 | ||
237 | proc_entries = kmalloc(num_online_nodes() * sizeof(struct proc_dir_entry *), | 238 | size = num_online_nodes() * sizeof(struct proc_dir_entry *); |
238 | GFP_KERNEL); | 239 | proc_entries = kzalloc(size, GFP_KERNEL); |
240 | if (!proc_entries) | ||
241 | return -ENOMEM; | ||
239 | 242 | ||
240 | sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL); | 243 | sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL); |
241 | 244 | ||
@@ -244,14 +247,12 @@ int __init prominfo_init(void) | |||
244 | sprintf(name, "node%d", cnodeid); | 247 | sprintf(name, "node%d", cnodeid); |
245 | *entp = proc_mkdir(name, sgi_prominfo_entry); | 248 | *entp = proc_mkdir(name, sgi_prominfo_entry); |
246 | nasid = cnodeid_to_nasid(cnodeid); | 249 | nasid = cnodeid_to_nasid(cnodeid); |
247 | p = create_proc_read_entry( | 250 | p = create_proc_read_entry("fit", 0, *entp, read_fit_entry, |
248 | "fit", 0, *entp, read_fit_entry, | 251 | (void *)nasid); |
249 | (void *)nasid); | ||
250 | if (p) | 252 | if (p) |
251 | p->owner = THIS_MODULE; | 253 | p->owner = THIS_MODULE; |
252 | p = create_proc_read_entry( | 254 | p = create_proc_read_entry("version", 0, *entp, |
253 | "version", 0, *entp, read_version_entry, | 255 | read_version_entry, (void *)nasid); |
254 | (void *)nasid); | ||
255 | if (p) | 256 | if (p) |
256 | p->owner = THIS_MODULE; | 257 | p->owner = THIS_MODULE; |
257 | entp++; | 258 | entp++; |
@@ -263,7 +264,7 @@ int __init prominfo_init(void) | |||
263 | void __exit prominfo_exit(void) | 264 | void __exit prominfo_exit(void) |
264 | { | 265 | { |
265 | struct proc_dir_entry **entp; | 266 | struct proc_dir_entry **entp; |
266 | unsigned cnodeid; | 267 | unsigned int cnodeid; |
267 | char name[NODE_NAME_LEN]; | 268 | char name[NODE_NAME_LEN]; |
268 | 269 | ||
269 | entp = proc_entries; | 270 | entp = proc_entries; |
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 471bbaa65d1b..b2e1e746b47f 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * License. See the file "COPYING" in the main directory of this archive | 5 | * License. See the file "COPYING" in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | * | 7 | * |
8 | * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. | 8 | * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
@@ -46,104 +46,24 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats); | |||
46 | 46 | ||
47 | static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); | 47 | static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); |
48 | 48 | ||
49 | void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0, | 49 | extern unsigned long |
50 | volatile unsigned long *, unsigned long data1); | 50 | sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, |
51 | volatile unsigned long *, unsigned long, | ||
52 | volatile unsigned long *, unsigned long); | ||
53 | void | ||
54 | sn2_ptc_deadlock_recovery(short *, short, short, int, | ||
55 | volatile unsigned long *, unsigned long, | ||
56 | volatile unsigned long *, unsigned long); | ||
51 | 57 | ||
52 | #ifdef DEBUG_PTC | ||
53 | /* | 58 | /* |
54 | * ptctest: | 59 | * Note: some is the following is captured here to make degugging easier |
55 | * | 60 | * (the macros make more sense if you see the debug patch - not posted) |
56 | * xyz - 3 digit hex number: | ||
57 | * x - Force PTC purges to use shub: | ||
58 | * 0 - no force | ||
59 | * 1 - force | ||
60 | * y - interupt enable | ||
61 | * 0 - disable interrupts | ||
62 | * 1 - leave interuupts enabled | ||
63 | * z - type of lock: | ||
64 | * 0 - global lock | ||
65 | * 1 - node local lock | ||
66 | * 2 - no lock | ||
67 | * | ||
68 | * Note: on shub1, only ptctest == 0 is supported. Don't try other values! | ||
69 | */ | 61 | */ |
70 | |||
71 | static unsigned int sn2_ptctest = 0; | ||
72 | |||
73 | static int __init ptc_test(char *str) | ||
74 | { | ||
75 | get_option(&str, &sn2_ptctest); | ||
76 | return 1; | ||
77 | } | ||
78 | __setup("ptctest=", ptc_test); | ||
79 | |||
80 | static inline int ptc_lock(unsigned long *flagp) | ||
81 | { | ||
82 | unsigned long opt = sn2_ptctest & 255; | ||
83 | |||
84 | switch (opt) { | ||
85 | case 0x00: | ||
86 | spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); | ||
87 | break; | ||
88 | case 0x01: | ||
89 | spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp); | ||
90 | break; | ||
91 | case 0x02: | ||
92 | local_irq_save(*flagp); | ||
93 | break; | ||
94 | case 0x10: | ||
95 | spin_lock(&sn2_global_ptc_lock); | ||
96 | break; | ||
97 | case 0x11: | ||
98 | spin_lock(&sn_nodepda->ptc_lock); | ||
99 | break; | ||
100 | case 0x12: | ||
101 | break; | ||
102 | default: | ||
103 | BUG(); | ||
104 | } | ||
105 | return opt; | ||
106 | } | ||
107 | |||
108 | static inline void ptc_unlock(unsigned long flags, int opt) | ||
109 | { | ||
110 | switch (opt) { | ||
111 | case 0x00: | ||
112 | spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); | ||
113 | break; | ||
114 | case 0x01: | ||
115 | spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags); | ||
116 | break; | ||
117 | case 0x02: | ||
118 | local_irq_restore(flags); | ||
119 | break; | ||
120 | case 0x10: | ||
121 | spin_unlock(&sn2_global_ptc_lock); | ||
122 | break; | ||
123 | case 0x11: | ||
124 | spin_unlock(&sn_nodepda->ptc_lock); | ||
125 | break; | ||
126 | case 0x12: | ||
127 | break; | ||
128 | default: | ||
129 | BUG(); | ||
130 | } | ||
131 | } | ||
132 | #else | ||
133 | |||
134 | #define sn2_ptctest 0 | 62 | #define sn2_ptctest 0 |
135 | 63 | #define local_node_uses_ptc_ga(sh1) ((sh1) ? 1 : 0) | |
136 | static inline int ptc_lock(unsigned long *flagp) | 64 | #define max_active_pio(sh1) ((sh1) ? 32 : 7) |
137 | { | 65 | #define reset_max_active_on_deadlock() 1 |
138 | spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); | 66 | #define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock) |
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static inline void ptc_unlock(unsigned long flags, int opt) | ||
143 | { | ||
144 | spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); | ||
145 | } | ||
146 | #endif | ||
147 | 67 | ||
148 | struct ptc_stats { | 68 | struct ptc_stats { |
149 | unsigned long ptc_l; | 69 | unsigned long ptc_l; |
@@ -151,27 +71,32 @@ struct ptc_stats { | |||
151 | unsigned long shub_ptc_flushes; | 71 | unsigned long shub_ptc_flushes; |
152 | unsigned long nodes_flushed; | 72 | unsigned long nodes_flushed; |
153 | unsigned long deadlocks; | 73 | unsigned long deadlocks; |
74 | unsigned long deadlocks2; | ||
154 | unsigned long lock_itc_clocks; | 75 | unsigned long lock_itc_clocks; |
155 | unsigned long shub_itc_clocks; | 76 | unsigned long shub_itc_clocks; |
156 | unsigned long shub_itc_clocks_max; | 77 | unsigned long shub_itc_clocks_max; |
78 | unsigned long shub_ptc_flushes_not_my_mm; | ||
157 | }; | 79 | }; |
158 | 80 | ||
81 | #define sn2_ptctest 0 | ||
82 | |||
159 | static inline unsigned long wait_piowc(void) | 83 | static inline unsigned long wait_piowc(void) |
160 | { | 84 | { |
161 | volatile unsigned long *piows, zeroval; | 85 | volatile unsigned long *piows; |
162 | unsigned long ws; | 86 | unsigned long zeroval, ws; |
163 | 87 | ||
164 | piows = pda->pio_write_status_addr; | 88 | piows = pda->pio_write_status_addr; |
165 | zeroval = pda->pio_write_status_val; | 89 | zeroval = pda->pio_write_status_val; |
166 | do { | 90 | do { |
167 | cpu_relax(); | 91 | cpu_relax(); |
168 | } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval); | 92 | } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval); |
169 | return ws; | 93 | return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; |
170 | } | 94 | } |
171 | 95 | ||
172 | void sn_tlb_migrate_finish(struct mm_struct *mm) | 96 | void sn_tlb_migrate_finish(struct mm_struct *mm) |
173 | { | 97 | { |
174 | if (mm == current->mm) | 98 | /* flush_tlb_mm is inefficient if more than 1 users of mm */ |
99 | if (mm == current->mm && mm && atomic_read(&mm->mm_users) == 1) | ||
175 | flush_tlb_mm(mm); | 100 | flush_tlb_mm(mm); |
176 | } | 101 | } |
177 | 102 | ||
@@ -201,12 +126,14 @@ void | |||
201 | sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | 126 | sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, |
202 | unsigned long end, unsigned long nbits) | 127 | unsigned long end, unsigned long nbits) |
203 | { | 128 | { |
204 | int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; | 129 | int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid; |
205 | int mymm = (mm == current->active_mm && current->mm); | 130 | int mymm = (mm == current->active_mm && mm == current->mm); |
131 | int use_cpu_ptcga; | ||
206 | volatile unsigned long *ptc0, *ptc1; | 132 | volatile unsigned long *ptc0, *ptc1; |
207 | unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value; | 133 | unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0; |
208 | short nasids[MAX_NUMNODES], nix; | 134 | short nasids[MAX_NUMNODES], nix; |
209 | nodemask_t nodes_flushed; | 135 | nodemask_t nodes_flushed; |
136 | int active, max_active, deadlock; | ||
210 | 137 | ||
211 | nodes_clear(nodes_flushed); | 138 | nodes_clear(nodes_flushed); |
212 | i = 0; | 139 | i = 0; |
@@ -267,41 +194,56 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | |||
267 | 194 | ||
268 | 195 | ||
269 | mynasid = get_nasid(); | 196 | mynasid = get_nasid(); |
197 | use_cpu_ptcga = local_node_uses_ptc_ga(shub1); | ||
198 | max_active = max_active_pio(shub1); | ||
270 | 199 | ||
271 | itc = ia64_get_itc(); | 200 | itc = ia64_get_itc(); |
272 | opt = ptc_lock(&flags); | 201 | spin_lock_irqsave(PTC_LOCK(shub1), flags); |
273 | itc2 = ia64_get_itc(); | 202 | itc2 = ia64_get_itc(); |
203 | |||
274 | __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; | 204 | __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; |
275 | __get_cpu_var(ptcstats).shub_ptc_flushes++; | 205 | __get_cpu_var(ptcstats).shub_ptc_flushes++; |
276 | __get_cpu_var(ptcstats).nodes_flushed += nix; | 206 | __get_cpu_var(ptcstats).nodes_flushed += nix; |
207 | if (!mymm) | ||
208 | __get_cpu_var(ptcstats).shub_ptc_flushes_not_my_mm++; | ||
277 | 209 | ||
210 | if (use_cpu_ptcga && !mymm) { | ||
211 | old_rr = ia64_get_rr(start); | ||
212 | ia64_set_rr(start, (old_rr & 0xff) | (rr_value << 8)); | ||
213 | ia64_srlz_d(); | ||
214 | } | ||
215 | |||
216 | wait_piowc(); | ||
278 | do { | 217 | do { |
279 | if (shub1) | 218 | if (shub1) |
280 | data1 = start | (1UL << SH1_PTC_1_START_SHFT); | 219 | data1 = start | (1UL << SH1_PTC_1_START_SHFT); |
281 | else | 220 | else |
282 | data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK); | 221 | data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK); |
283 | for (i = 0; i < nix; i++) { | 222 | deadlock = 0; |
223 | active = 0; | ||
224 | for (ibegin = 0, i = 0; i < nix; i++) { | ||
284 | nasid = nasids[i]; | 225 | nasid = nasids[i]; |
285 | if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid && mymm)) { | 226 | if (use_cpu_ptcga && unlikely(nasid == mynasid)) { |
286 | ia64_ptcga(start, nbits << 2); | 227 | ia64_ptcga(start, nbits << 2); |
287 | ia64_srlz_i(); | 228 | ia64_srlz_i(); |
288 | } else { | 229 | } else { |
289 | ptc0 = CHANGE_NASID(nasid, ptc0); | 230 | ptc0 = CHANGE_NASID(nasid, ptc0); |
290 | if (ptc1) | 231 | if (ptc1) |
291 | ptc1 = CHANGE_NASID(nasid, ptc1); | 232 | ptc1 = CHANGE_NASID(nasid, ptc1); |
292 | pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, | 233 | pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1); |
293 | data1); | 234 | active++; |
294 | flushed = 1; | 235 | } |
236 | if (active >= max_active || i == (nix - 1)) { | ||
237 | if ((deadlock = wait_piowc())) { | ||
238 | sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1); | ||
239 | if (reset_max_active_on_deadlock()) | ||
240 | max_active = 1; | ||
241 | } | ||
242 | active = 0; | ||
243 | ibegin = i + 1; | ||
295 | } | 244 | } |
296 | } | 245 | } |
297 | if (flushed | ||
298 | && (wait_piowc() & | ||
299 | (SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) { | ||
300 | sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1); | ||
301 | } | ||
302 | |||
303 | start += (1UL << nbits); | 246 | start += (1UL << nbits); |
304 | |||
305 | } while (start < end); | 247 | } while (start < end); |
306 | 248 | ||
307 | itc2 = ia64_get_itc() - itc2; | 249 | itc2 = ia64_get_itc() - itc2; |
@@ -309,7 +251,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | |||
309 | if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) | 251 | if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) |
310 | __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2; | 252 | __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2; |
311 | 253 | ||
312 | ptc_unlock(flags, opt); | 254 | if (old_rr) { |
255 | ia64_set_rr(start, old_rr); | ||
256 | ia64_srlz_d(); | ||
257 | } | ||
258 | |||
259 | spin_unlock_irqrestore(PTC_LOCK(shub1), flags); | ||
313 | 260 | ||
314 | preempt_enable(); | 261 | preempt_enable(); |
315 | } | 262 | } |
@@ -321,27 +268,31 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | |||
321 | * TLB flush transaction. The recovery sequence is somewhat tricky & is | 268 | * TLB flush transaction. The recovery sequence is somewhat tricky & is |
322 | * coded in assembly language. | 269 | * coded in assembly language. |
323 | */ | 270 | */ |
324 | void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0, | 271 | |
325 | volatile unsigned long *ptc1, unsigned long data1) | 272 | void |
273 | sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid, | ||
274 | volatile unsigned long *ptc0, unsigned long data0, | ||
275 | volatile unsigned long *ptc1, unsigned long data1) | ||
326 | { | 276 | { |
327 | extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, | ||
328 | volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long); | ||
329 | short nasid, i; | 277 | short nasid, i; |
330 | unsigned long *piows, zeroval; | 278 | unsigned long *piows, zeroval, n; |
331 | 279 | ||
332 | __get_cpu_var(ptcstats).deadlocks++; | 280 | __get_cpu_var(ptcstats).deadlocks++; |
333 | 281 | ||
334 | piows = (unsigned long *) pda->pio_write_status_addr; | 282 | piows = (unsigned long *) pda->pio_write_status_addr; |
335 | zeroval = pda->pio_write_status_val; | 283 | zeroval = pda->pio_write_status_val; |
336 | 284 | ||
337 | for (i=0; i < nix; i++) { | 285 | |
286 | for (i=ib; i <= ie; i++) { | ||
338 | nasid = nasids[i]; | 287 | nasid = nasids[i]; |
339 | if (!(sn2_ptctest & 3) && nasid == mynasid) | 288 | if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid) |
340 | continue; | 289 | continue; |
341 | ptc0 = CHANGE_NASID(nasid, ptc0); | 290 | ptc0 = CHANGE_NASID(nasid, ptc0); |
342 | if (ptc1) | 291 | if (ptc1) |
343 | ptc1 = CHANGE_NASID(nasid, ptc1); | 292 | ptc1 = CHANGE_NASID(nasid, ptc1); |
344 | sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); | 293 | |
294 | n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); | ||
295 | __get_cpu_var(ptcstats).deadlocks2 += n; | ||
345 | } | 296 | } |
346 | 297 | ||
347 | } | 298 | } |
@@ -452,20 +403,22 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data) | |||
452 | cpu = *(loff_t *) data; | 403 | cpu = *(loff_t *) data; |
453 | 404 | ||
454 | if (!cpu) { | 405 | if (!cpu) { |
455 | seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n"); | 406 | seq_printf(file, |
407 | "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n"); | ||
456 | seq_printf(file, "# ptctest %d\n", sn2_ptctest); | 408 | seq_printf(file, "# ptctest %d\n", sn2_ptctest); |
457 | } | 409 | } |
458 | 410 | ||
459 | if (cpu < NR_CPUS && cpu_online(cpu)) { | 411 | if (cpu < NR_CPUS && cpu_online(cpu)) { |
460 | stat = &per_cpu(ptcstats, cpu); | 412 | stat = &per_cpu(ptcstats, cpu); |
461 | seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, | 413 | seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, |
462 | stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, | 414 | stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, |
463 | stat->deadlocks, | 415 | stat->deadlocks, |
464 | 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, | 416 | 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, |
465 | 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, | 417 | 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, |
466 | 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec); | 418 | 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, |
419 | stat->shub_ptc_flushes_not_my_mm, | ||
420 | stat->deadlocks2); | ||
467 | } | 421 | } |
468 | |||
469 | return 0; | 422 | return 0; |
470 | } | 423 | } |
471 | 424 | ||
@@ -476,7 +429,7 @@ static struct seq_operations sn2_ptc_seq_ops = { | |||
476 | .show = sn2_ptc_seq_show | 429 | .show = sn2_ptc_seq_show |
477 | }; | 430 | }; |
478 | 431 | ||
479 | int sn2_ptc_proc_open(struct inode *inode, struct file *file) | 432 | static int sn2_ptc_proc_open(struct inode *inode, struct file *file) |
480 | { | 433 | { |
481 | return seq_open(file, &sn2_ptc_seq_ops); | 434 | return seq_open(file, &sn2_ptc_seq_ops); |
482 | } | 435 | } |
@@ -493,7 +446,7 @@ static struct proc_dir_entry *proc_sn2_ptc; | |||
493 | static int __init sn2_ptc_init(void) | 446 | static int __init sn2_ptc_init(void) |
494 | { | 447 | { |
495 | if (!ia64_platform_is("sn2")) | 448 | if (!ia64_platform_is("sn2")) |
496 | return -ENOSYS; | 449 | return 0; |
497 | 450 | ||
498 | if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { | 451 | if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { |
499 | printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); | 452 | printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); |
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 19b54fbcd7ea..70db21f3df21 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved. |
7 | * | 7 | * |
8 | * SGI Altix topology and hardware performance monitoring API. | 8 | * SGI Altix topology and hardware performance monitoring API. |
9 | * Mark Goodwin <markgw@sgi.com>. | 9 | * Mark Goodwin <markgw@sgi.com>. |
@@ -973,6 +973,9 @@ static int __devinit sn_hwperf_misc_register_init(void) | |||
973 | { | 973 | { |
974 | int e; | 974 | int e; |
975 | 975 | ||
976 | if (!ia64_platform_is("sn2")) | ||
977 | return 0; | ||
978 | |||
976 | sn_hwperf_init(); | 979 | sn_hwperf_init(); |
977 | 980 | ||
978 | /* | 981 | /* |
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c index a06719d752a0..c686d9c12f7b 100644 --- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c | |||
@@ -6,11 +6,11 @@ | |||
6 | * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | #include <linux/config.h> | 8 | #include <linux/config.h> |
9 | #include <asm/uaccess.h> | ||
10 | 9 | ||
11 | #ifdef CONFIG_PROC_FS | 10 | #ifdef CONFIG_PROC_FS |
12 | #include <linux/proc_fs.h> | 11 | #include <linux/proc_fs.h> |
13 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/sn/sn_sal.h> | 14 | #include <asm/sn/sn_sal.h> |
15 | 15 | ||
16 | static int partition_id_show(struct seq_file *s, void *p) | 16 | static int partition_id_show(struct seq_file *s, void *p) |
@@ -90,10 +90,10 @@ static int coherence_id_open(struct inode *inode, struct file *file) | |||
90 | return single_open(file, coherence_id_show, NULL); | 90 | return single_open(file, coherence_id_show, NULL); |
91 | } | 91 | } |
92 | 92 | ||
93 | static struct proc_dir_entry *sn_procfs_create_entry( | 93 | static struct proc_dir_entry |
94 | const char *name, struct proc_dir_entry *parent, | 94 | *sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent, |
95 | int (*openfunc)(struct inode *, struct file *), | 95 | int (*openfunc)(struct inode *, struct file *), |
96 | int (*releasefunc)(struct inode *, struct file *)) | 96 | int (*releasefunc)(struct inode *, struct file *)) |
97 | { | 97 | { |
98 | struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); | 98 | struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); |
99 | 99 | ||
@@ -126,24 +126,24 @@ void register_sn_procfs(void) | |||
126 | return; | 126 | return; |
127 | 127 | ||
128 | sn_procfs_create_entry("partition_id", sgi_proc_dir, | 128 | sn_procfs_create_entry("partition_id", sgi_proc_dir, |
129 | partition_id_open, single_release); | 129 | partition_id_open, single_release); |
130 | 130 | ||
131 | sn_procfs_create_entry("system_serial_number", sgi_proc_dir, | 131 | sn_procfs_create_entry("system_serial_number", sgi_proc_dir, |
132 | system_serial_number_open, single_release); | 132 | system_serial_number_open, single_release); |
133 | 133 | ||
134 | sn_procfs_create_entry("licenseID", sgi_proc_dir, | 134 | sn_procfs_create_entry("licenseID", sgi_proc_dir, |
135 | licenseID_open, single_release); | 135 | licenseID_open, single_release); |
136 | 136 | ||
137 | e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, | 137 | e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, |
138 | sn_force_interrupt_open, single_release); | 138 | sn_force_interrupt_open, single_release); |
139 | if (e) | 139 | if (e) |
140 | e->proc_fops->write = sn_force_interrupt_write_proc; | 140 | e->proc_fops->write = sn_force_interrupt_write_proc; |
141 | 141 | ||
142 | sn_procfs_create_entry("coherence_id", sgi_proc_dir, | 142 | sn_procfs_create_entry("coherence_id", sgi_proc_dir, |
143 | coherence_id_open, single_release); | 143 | coherence_id_open, single_release); |
144 | 144 | ||
145 | sn_procfs_create_entry("sn_topology", sgi_proc_dir, | 145 | sn_procfs_create_entry("sn_topology", sgi_proc_dir, |
146 | sn_topology_open, sn_topology_release); | 146 | sn_topology_open, sn_topology_release); |
147 | } | 147 | } |
148 | 148 | ||
149 | #endif /* CONFIG_PROC_FS */ | 149 | #endif /* CONFIG_PROC_FS */ |
diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index deb9baf4d473..56a88b6df4b4 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <asm/hw_irq.h> | 15 | #include <asm/hw_irq.h> |
16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
17 | #include <asm/timex.h> | ||
17 | 18 | ||
18 | #include <asm/sn/leds.h> | 19 | #include <asm/sn/leds.h> |
19 | #include <asm/sn/shub_mmr.h> | 20 | #include <asm/sn/shub_mmr.h> |
@@ -28,9 +29,27 @@ static struct time_interpolator sn2_interpolator = { | |||
28 | .source = TIME_SOURCE_MMIO64 | 29 | .source = TIME_SOURCE_MMIO64 |
29 | }; | 30 | }; |
30 | 31 | ||
32 | /* | ||
33 | * sn udelay uses the RTC instead of the ITC because the ITC is not | ||
34 | * synchronized across all CPUs, and the thread may migrate to another CPU | ||
35 | * if preemption is enabled. | ||
36 | */ | ||
37 | static void | ||
38 | ia64_sn_udelay (unsigned long usecs) | ||
39 | { | ||
40 | unsigned long start = rtc_time(); | ||
41 | unsigned long end = start + | ||
42 | usecs * sn_rtc_cycles_per_second / 1000000; | ||
43 | |||
44 | while (time_before((unsigned long)rtc_time(), end)) | ||
45 | cpu_relax(); | ||
46 | } | ||
47 | |||
31 | void __init sn_timer_init(void) | 48 | void __init sn_timer_init(void) |
32 | { | 49 | { |
33 | sn2_interpolator.frequency = sn_rtc_cycles_per_second; | 50 | sn2_interpolator.frequency = sn_rtc_cycles_per_second; |
34 | sn2_interpolator.addr = RTC_COUNTER_ADDR; | 51 | sn2_interpolator.addr = RTC_COUNTER_ADDR; |
35 | register_time_interpolator(&sn2_interpolator); | 52 | register_time_interpolator(&sn2_interpolator); |
53 | |||
54 | ia64_udelay = &ia64_sn_udelay; | ||
36 | } | 55 | } |
diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c index adf5db2e2afe..fa7f69945917 100644 --- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c +++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. | 4 | * Copyright (c) 2005, 2006 Silicon Graphics, Inc. All Rights Reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of version 2 of the GNU General Public License | 7 | * under the terms of version 2 of the GNU General Public License |
@@ -22,11 +22,6 @@ | |||
22 | * License along with this program; if not, write the Free Software | 22 | * License along with this program; if not, write the Free Software |
23 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | 23 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. |
24 | * | 24 | * |
25 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | ||
26 | * Mountain View, CA 94043, or: | ||
27 | * | ||
28 | * http://www.sgi.com | ||
29 | * | ||
30 | * For further information regarding this notice, see: | 25 | * For further information regarding this notice, see: |
31 | * | 26 | * |
32 | * http://oss.sgi.com/projects/GenInfo/NoticeExplan | 27 | * http://oss.sgi.com/projects/GenInfo/NoticeExplan |
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index d263d3e8fbb9..99cb28e74295 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c | |||
@@ -284,12 +284,10 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq, | |||
284 | if ((nasid & 1) == 0) | 284 | if ((nasid & 1) == 0) |
285 | return NULL; | 285 | return NULL; |
286 | 286 | ||
287 | sn_irq_info = kmalloc(sn_irq_size, GFP_KERNEL); | 287 | sn_irq_info = kzalloc(sn_irq_size, GFP_KERNEL); |
288 | if (sn_irq_info == NULL) | 288 | if (sn_irq_info == NULL) |
289 | return NULL; | 289 | return NULL; |
290 | 290 | ||
291 | memset(sn_irq_info, 0x0, sn_irq_size); | ||
292 | |||
293 | status = tiocx_intr_alloc(nasid, widget, __pa(sn_irq_info), irq, | 291 | status = tiocx_intr_alloc(nasid, widget, __pa(sn_irq_info), irq, |
294 | req_nasid, slice); | 292 | req_nasid, slice); |
295 | if (status) { | 293 | if (status) { |
@@ -486,7 +484,7 @@ static int __init tiocx_init(void) | |||
486 | int found_tiocx_device = 0; | 484 | int found_tiocx_device = 0; |
487 | 485 | ||
488 | if (!ia64_platform_is("sn2")) | 486 | if (!ia64_platform_is("sn2")) |
489 | return -ENODEV; | 487 | return 0; |
490 | 488 | ||
491 | bus_register(&tiocx_bus_type); | 489 | bus_register(&tiocx_bus_type); |
492 | 490 | ||
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 8d950c778bb6..cdf6856ce089 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c | |||
@@ -447,7 +447,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) | |||
447 | 447 | ||
448 | nbytes = nentries * ch->msg_size; | 448 | nbytes = nentries * ch->msg_size; |
449 | ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, | 449 | ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, |
450 | (GFP_KERNEL | GFP_DMA), | 450 | GFP_KERNEL, |
451 | &ch->local_msgqueue_base); | 451 | &ch->local_msgqueue_base); |
452 | if (ch->local_msgqueue == NULL) { | 452 | if (ch->local_msgqueue == NULL) { |
453 | continue; | 453 | continue; |
@@ -455,7 +455,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) | |||
455 | memset(ch->local_msgqueue, 0, nbytes); | 455 | memset(ch->local_msgqueue, 0, nbytes); |
456 | 456 | ||
457 | nbytes = nentries * sizeof(struct xpc_notify); | 457 | nbytes = nentries * sizeof(struct xpc_notify); |
458 | ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA)); | 458 | ch->notify_queue = kmalloc(nbytes, GFP_KERNEL); |
459 | if (ch->notify_queue == NULL) { | 459 | if (ch->notify_queue == NULL) { |
460 | kfree(ch->local_msgqueue_base); | 460 | kfree(ch->local_msgqueue_base); |
461 | ch->local_msgqueue = NULL; | 461 | ch->local_msgqueue = NULL; |
@@ -502,7 +502,7 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) | |||
502 | 502 | ||
503 | nbytes = nentries * ch->msg_size; | 503 | nbytes = nentries * ch->msg_size; |
504 | ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, | 504 | ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, |
505 | (GFP_KERNEL | GFP_DMA), | 505 | GFP_KERNEL, |
506 | &ch->remote_msgqueue_base); | 506 | &ch->remote_msgqueue_base); |
507 | if (ch->remote_msgqueue == NULL) { | 507 | if (ch->remote_msgqueue == NULL) { |
508 | continue; | 508 | continue; |
@@ -738,7 +738,9 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
738 | 738 | ||
739 | /* make sure all activity has settled down first */ | 739 | /* make sure all activity has settled down first */ |
740 | 740 | ||
741 | if (atomic_read(&ch->references) > 0) { | 741 | if (atomic_read(&ch->references) > 0 || |
742 | ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && | ||
743 | !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) { | ||
742 | return; | 744 | return; |
743 | } | 745 | } |
744 | DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); | 746 | DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); |
@@ -775,7 +777,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
775 | 777 | ||
776 | /* both sides are disconnected now */ | 778 | /* both sides are disconnected now */ |
777 | 779 | ||
778 | if (ch->flags & XPC_C_CONNECTCALLOUT) { | 780 | if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) { |
779 | spin_unlock_irqrestore(&ch->lock, *irq_flags); | 781 | spin_unlock_irqrestore(&ch->lock, *irq_flags); |
780 | xpc_disconnect_callout(ch, xpcDisconnected); | 782 | xpc_disconnect_callout(ch, xpcDisconnected); |
781 | spin_lock_irqsave(&ch->lock, *irq_flags); | 783 | spin_lock_irqsave(&ch->lock, *irq_flags); |
@@ -1300,7 +1302,7 @@ xpc_process_msg_IPI(struct xpc_partition *part, int ch_number) | |||
1300 | "delivered=%d, partid=%d, channel=%d\n", | 1302 | "delivered=%d, partid=%d, channel=%d\n", |
1301 | nmsgs_sent, ch->partid, ch->number); | 1303 | nmsgs_sent, ch->partid, ch->number); |
1302 | 1304 | ||
1303 | if (ch->flags & XPC_C_CONNECTCALLOUT) { | 1305 | if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) { |
1304 | xpc_activate_kthreads(ch, nmsgs_sent); | 1306 | xpc_activate_kthreads(ch, nmsgs_sent); |
1305 | } | 1307 | } |
1306 | } | 1308 | } |
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index c75f8aeefc2b..8cbf16432570 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c | |||
@@ -575,18 +575,21 @@ xpc_activate_partition(struct xpc_partition *part) | |||
575 | 575 | ||
576 | spin_lock_irqsave(&part->act_lock, irq_flags); | 576 | spin_lock_irqsave(&part->act_lock, irq_flags); |
577 | 577 | ||
578 | pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0); | ||
579 | |||
580 | DBUG_ON(part->act_state != XPC_P_INACTIVE); | 578 | DBUG_ON(part->act_state != XPC_P_INACTIVE); |
581 | 579 | ||
582 | if (pid > 0) { | 580 | part->act_state = XPC_P_ACTIVATION_REQ; |
583 | part->act_state = XPC_P_ACTIVATION_REQ; | 581 | XPC_SET_REASON(part, xpcCloneKThread, __LINE__); |
584 | XPC_SET_REASON(part, xpcCloneKThread, __LINE__); | ||
585 | } else { | ||
586 | XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__); | ||
587 | } | ||
588 | 582 | ||
589 | spin_unlock_irqrestore(&part->act_lock, irq_flags); | 583 | spin_unlock_irqrestore(&part->act_lock, irq_flags); |
584 | |||
585 | pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0); | ||
586 | |||
587 | if (unlikely(pid <= 0)) { | ||
588 | spin_lock_irqsave(&part->act_lock, irq_flags); | ||
589 | part->act_state = XPC_P_INACTIVE; | ||
590 | XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__); | ||
591 | spin_unlock_irqrestore(&part->act_lock, irq_flags); | ||
592 | } | ||
590 | } | 593 | } |
591 | 594 | ||
592 | 595 | ||
@@ -747,12 +750,16 @@ xpc_daemonize_kthread(void *args) | |||
747 | /* let registerer know that connection has been established */ | 750 | /* let registerer know that connection has been established */ |
748 | 751 | ||
749 | spin_lock_irqsave(&ch->lock, irq_flags); | 752 | spin_lock_irqsave(&ch->lock, irq_flags); |
750 | if (!(ch->flags & XPC_C_CONNECTCALLOUT)) { | 753 | if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) { |
751 | ch->flags |= XPC_C_CONNECTCALLOUT; | 754 | ch->flags |= XPC_C_CONNECTEDCALLOUT; |
752 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 755 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
753 | 756 | ||
754 | xpc_connected_callout(ch); | 757 | xpc_connected_callout(ch); |
755 | 758 | ||
759 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
760 | ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE; | ||
761 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
762 | |||
756 | /* | 763 | /* |
757 | * It is possible that while the callout was being | 764 | * It is possible that while the callout was being |
758 | * made that the remote partition sent some messages. | 765 | * made that the remote partition sent some messages. |
@@ -774,15 +781,17 @@ xpc_daemonize_kthread(void *args) | |||
774 | 781 | ||
775 | if (atomic_dec_return(&ch->kthreads_assigned) == 0) { | 782 | if (atomic_dec_return(&ch->kthreads_assigned) == 0) { |
776 | spin_lock_irqsave(&ch->lock, irq_flags); | 783 | spin_lock_irqsave(&ch->lock, irq_flags); |
777 | if ((ch->flags & XPC_C_CONNECTCALLOUT) && | 784 | if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && |
778 | !(ch->flags & XPC_C_DISCONNECTCALLOUT)) { | 785 | !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { |
779 | ch->flags |= XPC_C_DISCONNECTCALLOUT; | 786 | ch->flags |= XPC_C_DISCONNECTINGCALLOUT; |
780 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 787 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
781 | 788 | ||
782 | xpc_disconnect_callout(ch, xpcDisconnecting); | 789 | xpc_disconnect_callout(ch, xpcDisconnecting); |
783 | } else { | 790 | |
784 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 791 | spin_lock_irqsave(&ch->lock, irq_flags); |
792 | ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; | ||
785 | } | 793 | } |
794 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
786 | if (atomic_dec_return(&part->nchannels_engaged) == 0) { | 795 | if (atomic_dec_return(&part->nchannels_engaged) == 0) { |
787 | xpc_mark_partition_disengaged(part); | 796 | xpc_mark_partition_disengaged(part); |
788 | xpc_IPI_send_disengage(part); | 797 | xpc_IPI_send_disengage(part); |
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile index 321576b1b425..c6946784a6a8 100644 --- a/arch/ia64/sn/pci/Makefile +++ b/arch/ia64/sn/pci/Makefile | |||
@@ -7,4 +7,6 @@ | |||
7 | # | 7 | # |
8 | # Makefile for the sn pci general routines. | 8 | # Makefile for the sn pci general routines. |
9 | 9 | ||
10 | CPPFLAGS += -I$(srctree)/arch/ia64/sn/include | ||
11 | |||
10 | obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/ | 12 | obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/ |
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 9bf9f23b9a1f..b4b84c269210 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c | |||
@@ -90,14 +90,14 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, | |||
90 | */ | 90 | */ |
91 | node = pcibus_to_node(pdev->bus); | 91 | node = pcibus_to_node(pdev->bus); |
92 | if (likely(node >=0)) { | 92 | if (likely(node >=0)) { |
93 | struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size)); | 93 | struct page *p = alloc_pages_node(node, flags, get_order(size)); |
94 | 94 | ||
95 | if (likely(p)) | 95 | if (likely(p)) |
96 | cpuaddr = page_address(p); | 96 | cpuaddr = page_address(p); |
97 | else | 97 | else |
98 | return NULL; | 98 | return NULL; |
99 | } else | 99 | } else |
100 | cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); | 100 | cpuaddr = (void *)__get_free_pages(flags, get_order(size)); |
101 | 101 | ||
102 | if (unlikely(!cpuaddr)) | 102 | if (unlikely(!cpuaddr)) |
103 | return NULL; | 103 | return NULL; |
@@ -335,10 +335,10 @@ int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) | |||
335 | */ | 335 | */ |
336 | 336 | ||
337 | SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, | 337 | SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, |
338 | pci_domain_nr(bus), bus->number, | 338 | pci_domain_nr(bus), bus->number, |
339 | 0, /* io */ | 339 | 0, /* io */ |
340 | 0, /* read */ | 340 | 0, /* read */ |
341 | port, size, __pa(val)); | 341 | port, size, __pa(val)); |
342 | 342 | ||
343 | if (isrv.status == 0) | 343 | if (isrv.status == 0) |
344 | return size; | 344 | return size; |
@@ -381,10 +381,10 @@ int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) | |||
381 | */ | 381 | */ |
382 | 382 | ||
383 | SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, | 383 | SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, |
384 | pci_domain_nr(bus), bus->number, | 384 | pci_domain_nr(bus), bus->number, |
385 | 0, /* io */ | 385 | 0, /* io */ |
386 | 1, /* write */ | 386 | 1, /* write */ |
387 | port, size, __pa(&val)); | 387 | port, size, __pa(&val)); |
388 | 388 | ||
389 | if (isrv.status == 0) | 389 | if (isrv.status == 0) |
390 | return size; | 390 | return size; |
diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile index 1850c4a94c41..3b403ea456f9 100644 --- a/arch/ia64/sn/pci/pcibr/Makefile +++ b/arch/ia64/sn/pci/pcibr/Makefile | |||
@@ -7,5 +7,7 @@ | |||
7 | # | 7 | # |
8 | # Makefile for the sn2 io routines. | 8 | # Makefile for the sn2 io routines. |
9 | 9 | ||
10 | CPPFLAGS += -I$(srctree)/arch/ia64/sn/include | ||
11 | |||
10 | obj-y += pcibr_dma.o pcibr_reg.o \ | 12 | obj-y += pcibr_dma.o pcibr_reg.o \ |
11 | pcibr_ate.o pcibr_provider.o | 13 | pcibr_ate.o pcibr_provider.o |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index aa3fa5152a32..1f0253bfe0a0 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
@@ -12,7 +12,7 @@ | |||
12 | #include <asm/sn/pcibus_provider_defs.h> | 12 | #include <asm/sn/pcibus_provider_defs.h> |
13 | #include <asm/sn/pcidev.h> | 13 | #include <asm/sn/pcidev.h> |
14 | 14 | ||
15 | int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ | 15 | int pcibr_invalidate_ate; /* by default don't invalidate ATE on free */ |
16 | 16 | ||
17 | /* | 17 | /* |
18 | * mark_ate: Mark the ate as either free or inuse. | 18 | * mark_ate: Mark the ate as either free or inuse. |
@@ -20,14 +20,12 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ | |||
20 | static void mark_ate(struct ate_resource *ate_resource, int start, int number, | 20 | static void mark_ate(struct ate_resource *ate_resource, int start, int number, |
21 | u64 value) | 21 | u64 value) |
22 | { | 22 | { |
23 | |||
24 | u64 *ate = ate_resource->ate; | 23 | u64 *ate = ate_resource->ate; |
25 | int index; | 24 | int index; |
26 | int length = 0; | 25 | int length = 0; |
27 | 26 | ||
28 | for (index = start; length < number; index++, length++) | 27 | for (index = start; length < number; index++, length++) |
29 | ate[index] = value; | 28 | ate[index] = value; |
30 | |||
31 | } | 29 | } |
32 | 30 | ||
33 | /* | 31 | /* |
@@ -37,7 +35,6 @@ static void mark_ate(struct ate_resource *ate_resource, int start, int number, | |||
37 | static int find_free_ate(struct ate_resource *ate_resource, int start, | 35 | static int find_free_ate(struct ate_resource *ate_resource, int start, |
38 | int count) | 36 | int count) |
39 | { | 37 | { |
40 | |||
41 | u64 *ate = ate_resource->ate; | 38 | u64 *ate = ate_resource->ate; |
42 | int index; | 39 | int index; |
43 | int start_free; | 40 | int start_free; |
@@ -70,12 +67,10 @@ static int find_free_ate(struct ate_resource *ate_resource, int start, | |||
70 | static inline void free_ate_resource(struct ate_resource *ate_resource, | 67 | static inline void free_ate_resource(struct ate_resource *ate_resource, |
71 | int start) | 68 | int start) |
72 | { | 69 | { |
73 | |||
74 | mark_ate(ate_resource, start, ate_resource->ate[start], 0); | 70 | mark_ate(ate_resource, start, ate_resource->ate[start], 0); |
75 | if ((ate_resource->lowest_free_index > start) || | 71 | if ((ate_resource->lowest_free_index > start) || |
76 | (ate_resource->lowest_free_index < 0)) | 72 | (ate_resource->lowest_free_index < 0)) |
77 | ate_resource->lowest_free_index = start; | 73 | ate_resource->lowest_free_index = start; |
78 | |||
79 | } | 74 | } |
80 | 75 | ||
81 | /* | 76 | /* |
@@ -84,7 +79,6 @@ static inline void free_ate_resource(struct ate_resource *ate_resource, | |||
84 | static inline int alloc_ate_resource(struct ate_resource *ate_resource, | 79 | static inline int alloc_ate_resource(struct ate_resource *ate_resource, |
85 | int ate_needed) | 80 | int ate_needed) |
86 | { | 81 | { |
87 | |||
88 | int start_index; | 82 | int start_index; |
89 | 83 | ||
90 | /* | 84 | /* |
@@ -118,19 +112,12 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, | |||
118 | */ | 112 | */ |
119 | int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) | 113 | int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) |
120 | { | 114 | { |
121 | int status = 0; | 115 | int status; |
122 | u64 flag; | 116 | unsigned long flags; |
123 | 117 | ||
124 | flag = pcibr_lock(pcibus_info); | 118 | spin_lock_irqsave(&pcibus_info->pbi_lock, flags); |
125 | status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); | 119 | status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); |
126 | 120 | spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags); | |
127 | if (status < 0) { | ||
128 | /* Failed to allocate */ | ||
129 | pcibr_unlock(pcibus_info, flag); | ||
130 | return -1; | ||
131 | } | ||
132 | |||
133 | pcibr_unlock(pcibus_info, flag); | ||
134 | 121 | ||
135 | return status; | 122 | return status; |
136 | } | 123 | } |
@@ -182,7 +169,7 @@ void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) | |||
182 | ate_write(pcibus_info, index, count, (ate & ~PCI32_ATE_V)); | 169 | ate_write(pcibus_info, index, count, (ate & ~PCI32_ATE_V)); |
183 | } | 170 | } |
184 | 171 | ||
185 | flags = pcibr_lock(pcibus_info); | 172 | spin_lock_irqsave(&pcibus_info->pbi_lock, flags); |
186 | free_ate_resource(&pcibus_info->pbi_int_ate_resource, index); | 173 | free_ate_resource(&pcibus_info->pbi_int_ate_resource, index); |
187 | pcibr_unlock(pcibus_info, flags); | 174 | spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags); |
188 | } | 175 | } |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 54ce5b7ceed2..9f86bb6519aa 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c | |||
@@ -137,14 +137,12 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, | |||
137 | pci_addr |= PCI64_ATTR_VIRTUAL; | 137 | pci_addr |= PCI64_ATTR_VIRTUAL; |
138 | 138 | ||
139 | return pci_addr; | 139 | return pci_addr; |
140 | |||
141 | } | 140 | } |
142 | 141 | ||
143 | static dma_addr_t | 142 | static dma_addr_t |
144 | pcibr_dmatrans_direct32(struct pcidev_info * info, | 143 | pcibr_dmatrans_direct32(struct pcidev_info * info, |
145 | u64 paddr, size_t req_size, u64 flags) | 144 | u64 paddr, size_t req_size, u64 flags) |
146 | { | 145 | { |
147 | |||
148 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; | 146 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; |
149 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> | 147 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> |
150 | pdi_pcibus_info; | 148 | pdi_pcibus_info; |
@@ -171,7 +169,6 @@ pcibr_dmatrans_direct32(struct pcidev_info * info, | |||
171 | } | 169 | } |
172 | 170 | ||
173 | return PCI32_DIRECT_BASE | offset; | 171 | return PCI32_DIRECT_BASE | offset; |
174 | |||
175 | } | 172 | } |
176 | 173 | ||
177 | /* | 174 | /* |
@@ -218,9 +215,8 @@ void sn_dma_flush(u64 addr) | |||
218 | u64 flags; | 215 | u64 flags; |
219 | u64 itte; | 216 | u64 itte; |
220 | struct hubdev_info *hubinfo; | 217 | struct hubdev_info *hubinfo; |
221 | volatile struct sn_flush_device_kernel *p; | 218 | struct sn_flush_device_kernel *p; |
222 | volatile struct sn_flush_device_common *common; | 219 | struct sn_flush_device_common *common; |
223 | |||
224 | struct sn_flush_nasid_entry *flush_nasid_list; | 220 | struct sn_flush_nasid_entry *flush_nasid_list; |
225 | 221 | ||
226 | if (!sn_ioif_inited) | 222 | if (!sn_ioif_inited) |
@@ -310,8 +306,7 @@ void sn_dma_flush(u64 addr) | |||
310 | (common->sfdl_slot - 1)); | 306 | (common->sfdl_slot - 1)); |
311 | } | 307 | } |
312 | } else { | 308 | } else { |
313 | spin_lock_irqsave((spinlock_t *)&p->sfdl_flush_lock, | 309 | spin_lock_irqsave(&p->sfdl_flush_lock, flags); |
314 | flags); | ||
315 | *common->sfdl_flush_addr = 0; | 310 | *common->sfdl_flush_addr = 0; |
316 | 311 | ||
317 | /* force an interrupt. */ | 312 | /* force an interrupt. */ |
@@ -322,8 +317,7 @@ void sn_dma_flush(u64 addr) | |||
322 | cpu_relax(); | 317 | cpu_relax(); |
323 | 318 | ||
324 | /* okay, everything is synched up. */ | 319 | /* okay, everything is synched up. */ |
325 | spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, | 320 | spin_unlock_irqrestore(&p->sfdl_flush_lock, flags); |
326 | flags); | ||
327 | } | 321 | } |
328 | return; | 322 | return; |
329 | } | 323 | } |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 2fac27049bf6..98f716bd92f0 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c | |||
@@ -163,9 +163,12 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
163 | /* Setup the PMU ATE map */ | 163 | /* Setup the PMU ATE map */ |
164 | soft->pbi_int_ate_resource.lowest_free_index = 0; | 164 | soft->pbi_int_ate_resource.lowest_free_index = 0; |
165 | soft->pbi_int_ate_resource.ate = | 165 | soft->pbi_int_ate_resource.ate = |
166 | kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); | 166 | kzalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); |
167 | memset(soft->pbi_int_ate_resource.ate, 0, | 167 | |
168 | (soft->pbi_int_ate_size * sizeof(u64))); | 168 | if (!soft->pbi_int_ate_resource.ate) { |
169 | kfree(soft); | ||
170 | return NULL; | ||
171 | } | ||
169 | 172 | ||
170 | if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { | 173 | if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { |
171 | /* TIO PCI Bridge: find nearest node with CPUs */ | 174 | /* TIO PCI Bridge: find nearest node with CPUs */ |