diff options
Diffstat (limited to 'arch/ia64/sn')
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 104 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/irq.c | 4 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/mca.c | 5 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/setup.c | 64 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/prominfo_proc.c | 25 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn2_smp.c | 58 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn_hwperf.c | 5 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn_proc_fs.c | 22 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/timer.c | 19 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/timer_interrupt.c | 7 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/tiocx.c | 6 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/xpc_channel.c | 8 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/xpc_main.c | 20 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pci_dma.c | 16 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_ate.c | 29 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_dma.c | 14 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_provider.c | 9 | ||||
-rw-r--r-- | arch/ia64/sn/pci/tioce_provider.c | 326 |
18 files changed, 519 insertions, 222 deletions
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index d7e4d79e16a..dfb3f290237 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -23,6 +23,10 @@ | |||
23 | #include "xtalk/hubdev.h" | 23 | #include "xtalk/hubdev.h" |
24 | #include "xtalk/xwidgetdev.h" | 24 | #include "xtalk/xwidgetdev.h" |
25 | 25 | ||
26 | |||
27 | extern void sn_init_cpei_timer(void); | ||
28 | extern void register_sn_procfs(void); | ||
29 | |||
26 | static struct list_head sn_sysdata_list; | 30 | static struct list_head sn_sysdata_list; |
27 | 31 | ||
28 | /* sysdata list struct */ | 32 | /* sysdata list struct */ |
@@ -40,12 +44,12 @@ struct brick { | |||
40 | struct slab_info slab_info[MAX_SLABS + 1]; | 44 | struct slab_info slab_info[MAX_SLABS + 1]; |
41 | }; | 45 | }; |
42 | 46 | ||
43 | int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ | 47 | int sn_ioif_inited; /* SN I/O infrastructure initialized? */ |
44 | 48 | ||
45 | 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 */ |
46 | 50 | ||
47 | static int max_segment_number = 0; /* Default highest segment number */ | 51 | static int max_segment_number; /* Default highest segment number */ |
48 | static int max_pcibus_number = 255; /* Default highest pci bus number */ | 52 | static int max_pcibus_number = 255; /* Default highest pci bus number */ |
49 | 53 | ||
50 | /* | 54 | /* |
51 | * Hooks and struct for unsupported pci providers | 55 | * Hooks and struct for unsupported pci providers |
@@ -84,7 +88,6 @@ static inline u64 | |||
84 | 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, |
85 | u64 address) | 89 | u64 address) |
86 | { | 90 | { |
87 | |||
88 | struct ia64_sal_retval ret_stuff; | 91 | struct ia64_sal_retval ret_stuff; |
89 | ret_stuff.status = 0; | 92 | ret_stuff.status = 0; |
90 | ret_stuff.v0 = 0; | 93 | ret_stuff.v0 = 0; |
@@ -94,7 +97,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, | |||
94 | (u64) nasid, (u64) widget_num, | 97 | (u64) nasid, (u64) widget_num, |
95 | (u64) device_num, (u64) address, 0, 0, 0); | 98 | (u64) device_num, (u64) address, 0, 0, 0); |
96 | return ret_stuff.status; | 99 | return ret_stuff.status; |
97 | |||
98 | } | 100 | } |
99 | 101 | ||
100 | /* | 102 | /* |
@@ -102,7 +104,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, | |||
102 | */ | 104 | */ |
103 | static inline u64 sal_get_hubdev_info(u64 handle, u64 address) | 105 | static inline u64 sal_get_hubdev_info(u64 handle, u64 address) |
104 | { | 106 | { |
105 | |||
106 | struct ia64_sal_retval ret_stuff; | 107 | struct ia64_sal_retval ret_stuff; |
107 | ret_stuff.status = 0; | 108 | ret_stuff.status = 0; |
108 | ret_stuff.v0 = 0; | 109 | ret_stuff.v0 = 0; |
@@ -118,7 +119,6 @@ static inline u64 sal_get_hubdev_info(u64 handle, u64 address) | |||
118 | */ | 119 | */ |
119 | 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) |
120 | { | 121 | { |
121 | |||
122 | struct ia64_sal_retval ret_stuff; | 122 | struct ia64_sal_retval ret_stuff; |
123 | ret_stuff.status = 0; | 123 | ret_stuff.status = 0; |
124 | ret_stuff.v0 = 0; | 124 | ret_stuff.v0 = 0; |
@@ -215,7 +215,7 @@ static void __init sn_fixup_ionodes(void) | |||
215 | struct hubdev_info *hubdev; | 215 | struct hubdev_info *hubdev; |
216 | u64 status; | 216 | u64 status; |
217 | u64 nasid; | 217 | u64 nasid; |
218 | int i, widget, device; | 218 | int i, widget, device, size; |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Get SGI Specific HUB chipset information. | 221 | * Get SGI Specific HUB chipset information. |
@@ -251,48 +251,37 @@ static void __init sn_fixup_ionodes(void) | |||
251 | if (!hubdev->hdi_flush_nasid_list.widget_p) | 251 | if (!hubdev->hdi_flush_nasid_list.widget_p) |
252 | continue; | 252 | continue; |
253 | 253 | ||
254 | size = (HUB_WIDGET_ID_MAX + 1) * | ||
255 | sizeof(struct sn_flush_device_kernel *); | ||
254 | hubdev->hdi_flush_nasid_list.widget_p = | 256 | hubdev->hdi_flush_nasid_list.widget_p = |
255 | kmalloc((HUB_WIDGET_ID_MAX + 1) * | 257 | kzalloc(size, GFP_KERNEL); |
256 | sizeof(struct sn_flush_device_kernel *), | 258 | if (!hubdev->hdi_flush_nasid_list.widget_p) |
257 | GFP_KERNEL); | 259 | BUG(); |
258 | memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, | ||
259 | (HUB_WIDGET_ID_MAX + 1) * | ||
260 | sizeof(struct sn_flush_device_kernel *)); | ||
261 | 260 | ||
262 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { | 261 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { |
263 | sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET * | 262 | size = DEV_PER_WIDGET * |
264 | sizeof(struct | 263 | sizeof(struct sn_flush_device_kernel); |
265 | sn_flush_device_kernel), | 264 | sn_flush_device_kernel = kzalloc(size, GFP_KERNEL); |
266 | GFP_KERNEL); | ||
267 | if (!sn_flush_device_kernel) | 265 | if (!sn_flush_device_kernel) |
268 | BUG(); | 266 | BUG(); |
269 | memset(sn_flush_device_kernel, 0x0, | ||
270 | DEV_PER_WIDGET * | ||
271 | sizeof(struct sn_flush_device_kernel)); | ||
272 | 267 | ||
273 | dev_entry = sn_flush_device_kernel; | 268 | dev_entry = sn_flush_device_kernel; |
274 | for (device = 0; device < DEV_PER_WIDGET; | 269 | for (device = 0; device < DEV_PER_WIDGET; |
275 | device++,dev_entry++) { | 270 | device++,dev_entry++) { |
276 | dev_entry->common = kmalloc(sizeof(struct | 271 | size = sizeof(struct sn_flush_device_common); |
277 | sn_flush_device_common), | 272 | dev_entry->common = kzalloc(size, GFP_KERNEL); |
278 | GFP_KERNEL); | ||
279 | if (!dev_entry->common) | 273 | if (!dev_entry->common) |
280 | BUG(); | 274 | BUG(); |
281 | memset(dev_entry->common, 0x0, sizeof(struct | ||
282 | sn_flush_device_common)); | ||
283 | 275 | ||
284 | if (sn_prom_feature_available( | 276 | if (sn_prom_feature_available( |
285 | PRF_DEVICE_FLUSH_LIST)) | 277 | PRF_DEVICE_FLUSH_LIST)) |
286 | status = sal_get_device_dmaflush_list( | 278 | status = sal_get_device_dmaflush_list( |
287 | nasid, | 279 | nasid, widget, device, |
288 | widget, | 280 | (u64)(dev_entry->common)); |
289 | device, | ||
290 | (u64)(dev_entry->common)); | ||
291 | else | 281 | else |
292 | status = sn_device_fixup_war(nasid, | 282 | status = sn_device_fixup_war(nasid, |
293 | widget, | 283 | widget, device, |
294 | device, | 284 | dev_entry->common); |
295 | dev_entry->common); | ||
296 | if (status != SALRET_OK) | 285 | if (status != SALRET_OK) |
297 | panic("SAL call failed: %s\n", | 286 | panic("SAL call failed: %s\n", |
298 | ia64_sal_strerror(status)); | 287 | ia64_sal_strerror(status)); |
@@ -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, |
@@ -482,13 +470,13 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
482 | */ | 470 | */ |
483 | 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) |
484 | { | 472 | { |
485 | int status = 0; | 473 | int status; |
486 | int nasid, cnode; | 474 | int nasid, cnode; |
487 | struct pci_controller *controller; | 475 | struct pci_controller *controller; |
488 | struct sn_pci_controller *sn_controller; | 476 | struct sn_pci_controller *sn_controller; |
489 | struct pcibus_bussoft *prom_bussoft_ptr; | 477 | struct pcibus_bussoft *prom_bussoft_ptr; |
490 | struct hubdev_info *hubdev_info; | 478 | struct hubdev_info *hubdev_info; |
491 | void *provider_soft = NULL; | 479 | void *provider_soft; |
492 | struct sn_pcibus_provider *provider; | 480 | struct sn_pcibus_provider *provider; |
493 | 481 | ||
494 | status = sal_get_pcibus_info((u64) segment, (u64) busnum, | 482 | status = sal_get_pcibus_info((u64) segment, (u64) busnum, |
@@ -535,6 +523,8 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
535 | bus->sysdata = controller; | 523 | bus->sysdata = controller; |
536 | if (provider->bus_fixup) | 524 | if (provider->bus_fixup) |
537 | 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; | ||
538 | 528 | ||
539 | if (provider_soft == NULL) { | 529 | if (provider_soft == NULL) { |
540 | /* fixup failed or not applicable */ | 530 | /* fixup failed or not applicable */ |
@@ -617,15 +607,15 @@ void sn_bus_store_sysdata(struct pci_dev *dev) | |||
617 | void sn_bus_free_sysdata(void) | 607 | void sn_bus_free_sysdata(void) |
618 | { | 608 | { |
619 | struct sysdata_el *element; | 609 | struct sysdata_el *element; |
620 | struct list_head *list; | 610 | struct list_head *list, *safe; |
621 | 611 | ||
622 | sn_sysdata_free_start: | 612 | list_for_each_safe(list, safe, &sn_sysdata_list) { |
623 | list_for_each(list, &sn_sysdata_list) { | ||
624 | element = list_entry(list, struct sysdata_el, entry); | 613 | element = list_entry(list, struct sysdata_el, entry); |
625 | list_del(&element->entry); | 614 | list_del(&element->entry); |
615 | list_del(&(((struct pcidev_info *) | ||
616 | (element->sysdata))->pdi_list)); | ||
626 | kfree(element->sysdata); | 617 | kfree(element->sysdata); |
627 | kfree(element); | 618 | kfree(element); |
628 | goto sn_sysdata_free_start; | ||
629 | } | 619 | } |
630 | return; | 620 | return; |
631 | } | 621 | } |
@@ -638,13 +628,8 @@ sn_sysdata_free_start: | |||
638 | 628 | ||
639 | static int __init sn_pci_init(void) | 629 | static int __init sn_pci_init(void) |
640 | { | 630 | { |
641 | int i = 0; | 631 | int i, j; |
642 | int j = 0; | ||
643 | struct pci_dev *pci_dev = NULL; | 632 | struct pci_dev *pci_dev = NULL; |
644 | extern void sn_init_cpei_timer(void); | ||
645 | #ifdef CONFIG_PROC_FS | ||
646 | extern void register_sn_procfs(void); | ||
647 | #endif | ||
648 | 633 | ||
649 | if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) | 634 | if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) |
650 | return 0; | 635 | return 0; |
@@ -700,32 +685,29 @@ static int __init sn_pci_init(void) | |||
700 | */ | 685 | */ |
701 | void hubdev_init_node(nodepda_t * npda, cnodeid_t node) | 686 | void hubdev_init_node(nodepda_t * npda, cnodeid_t node) |
702 | { | 687 | { |
703 | |||
704 | 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); | ||
705 | 693 | ||
706 | if (node >= num_online_nodes()) /* Headless/memless IO nodes */ | 694 | if (node >= num_online_nodes()) /* Headless/memless IO nodes */ |
707 | hubdev_info = | 695 | pg = NODE_DATA(0); |
708 | (struct hubdev_info *)alloc_bootmem_node(NODE_DATA(0), | ||
709 | sizeof(struct | ||
710 | hubdev_info)); | ||
711 | else | 696 | else |
712 | hubdev_info = | 697 | pg = NODE_DATA(node); |
713 | (struct hubdev_info *)alloc_bootmem_node(NODE_DATA(node), | ||
714 | sizeof(struct | ||
715 | hubdev_info)); | ||
716 | npda->pdinfo = (void *)hubdev_info; | ||
717 | 698 | ||
699 | hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size); | ||
700 | |||
701 | npda->pdinfo = (void *)hubdev_info; | ||
718 | } | 702 | } |
719 | 703 | ||
720 | geoid_t | 704 | geoid_t |
721 | cnodeid_get_geoid(cnodeid_t cnode) | 705 | cnodeid_get_geoid(cnodeid_t cnode) |
722 | { | 706 | { |
723 | |||
724 | struct hubdev_info *hubdev; | 707 | struct hubdev_info *hubdev; |
725 | 708 | ||
726 | hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); | 709 | hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); |
727 | return hubdev->hdi_geoid; | 710 | return hubdev->hdi_geoid; |
728 | |||
729 | } | 711 | } |
730 | 712 | ||
731 | 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 74d87d903d5..c373113d073 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c | |||
@@ -299,7 +299,9 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) | |||
299 | return; | 299 | return; |
300 | 300 | ||
301 | 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; |
302 | if (!sn_irq_info || !sn_irq_info->irq_irq) { | 302 | if (!sn_irq_info) |
303 | return; | ||
304 | if (!sn_irq_info->irq_irq) { | ||
303 | kfree(sn_irq_info); | 305 | kfree(sn_irq_info); |
304 | return; | 306 | return; |
305 | } | 307 | } |
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c index 9ab684d1bb5..3db62f24596 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 ee36bff93c3..8b6d5c84470 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.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-2005 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/config.h> | 9 | #include <linux/config.h> |
@@ -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 |
@@ -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 |
@@ -496,6 +498,7 @@ void __init sn_setup(char **cmdline_p) | |||
496 | * for sn. | 498 | * for sn. |
497 | */ | 499 | */ |
498 | pm_power_off = ia64_sn_power_down; | 500 | pm_power_off = ia64_sn_power_down; |
501 | current->thread.flags |= IA64_THREAD_MIGRATION; | ||
499 | } | 502 | } |
500 | 503 | ||
501 | /** | 504 | /** |
@@ -658,7 +661,8 @@ void __init sn_cpu_init(void) | |||
658 | SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; | 661 | SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; |
659 | u64 *pio; | 662 | u64 *pio; |
660 | pio = is_shub1() ? pio1 : pio2; | 663 | pio = is_shub1() ? pio1 : pio2; |
661 | pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]); | 664 | pda->pio_write_status_addr = |
665 | (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]); | ||
662 | pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0; | 666 | pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0; |
663 | } | 667 | } |
664 | 668 | ||
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c index 81c63b2f8ae..6ae276d5d50 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 f153a4c35c7..d9d306c79f2 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c | |||
@@ -46,8 +46,14 @@ 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, short, int, volatile unsigned long *, unsigned long, | 49 | extern unsigned long |
50 | volatile unsigned long *, unsigned long); | 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 | /* | 58 | /* |
53 | * Note: some is the following is captured here to make degugging easier | 59 | * Note: some is the following is captured here to make degugging easier |
@@ -59,16 +65,6 @@ void sn2_ptc_deadlock_recovery(short *, short, short, int, volatile unsigned lon | |||
59 | #define reset_max_active_on_deadlock() 1 | 65 | #define reset_max_active_on_deadlock() 1 |
60 | #define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock) | 66 | #define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock) |
61 | 67 | ||
62 | static inline void ptc_lock(int sh1, unsigned long *flagp) | ||
63 | { | ||
64 | spin_lock_irqsave(PTC_LOCK(sh1), *flagp); | ||
65 | } | ||
66 | |||
67 | static inline void ptc_unlock(int sh1, unsigned long flags) | ||
68 | { | ||
69 | spin_unlock_irqrestore(PTC_LOCK(sh1), flags); | ||
70 | } | ||
71 | |||
72 | struct ptc_stats { | 68 | struct ptc_stats { |
73 | unsigned long ptc_l; | 69 | unsigned long ptc_l; |
74 | unsigned long change_rid; | 70 | unsigned long change_rid; |
@@ -82,6 +78,8 @@ struct ptc_stats { | |||
82 | unsigned long shub_ptc_flushes_not_my_mm; | 78 | unsigned long shub_ptc_flushes_not_my_mm; |
83 | }; | 79 | }; |
84 | 80 | ||
81 | #define sn2_ptctest 0 | ||
82 | |||
85 | static inline unsigned long wait_piowc(void) | 83 | static inline unsigned long wait_piowc(void) |
86 | { | 84 | { |
87 | volatile unsigned long *piows; | 85 | volatile unsigned long *piows; |
@@ -95,6 +93,27 @@ static inline unsigned long wait_piowc(void) | |||
95 | return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; | 93 | return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; |
96 | } | 94 | } |
97 | 95 | ||
96 | /** | ||
97 | * sn_migrate - SN-specific task migration actions | ||
98 | * @task: Task being migrated to new CPU | ||
99 | * | ||
100 | * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order. | ||
101 | * Context switching user threads which have memory-mapped MMIO may cause | ||
102 | * PIOs to issue from seperate CPUs, thus the PIO writes must be drained | ||
103 | * from the previous CPU's Shub before execution resumes on the new CPU. | ||
104 | */ | ||
105 | void sn_migrate(struct task_struct *task) | ||
106 | { | ||
107 | pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu); | ||
108 | volatile unsigned long *adr = last_pda->pio_write_status_addr; | ||
109 | unsigned long val = last_pda->pio_write_status_val; | ||
110 | |||
111 | /* Drain PIO writes from old CPU's Shub */ | ||
112 | while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) | ||
113 | != val)) | ||
114 | cpu_relax(); | ||
115 | } | ||
116 | |||
98 | void sn_tlb_migrate_finish(struct mm_struct *mm) | 117 | void sn_tlb_migrate_finish(struct mm_struct *mm) |
99 | { | 118 | { |
100 | /* flush_tlb_mm is inefficient if more than 1 users of mm */ | 119 | /* flush_tlb_mm is inefficient if more than 1 users of mm */ |
@@ -200,7 +219,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | |||
200 | max_active = max_active_pio(shub1); | 219 | max_active = max_active_pio(shub1); |
201 | 220 | ||
202 | itc = ia64_get_itc(); | 221 | itc = ia64_get_itc(); |
203 | ptc_lock(shub1, &flags); | 222 | spin_lock_irqsave(PTC_LOCK(shub1), flags); |
204 | itc2 = ia64_get_itc(); | 223 | itc2 = ia64_get_itc(); |
205 | 224 | ||
206 | __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; | 225 | __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; |
@@ -258,7 +277,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | |||
258 | ia64_srlz_d(); | 277 | ia64_srlz_d(); |
259 | } | 278 | } |
260 | 279 | ||
261 | ptc_unlock(shub1, flags); | 280 | spin_unlock_irqrestore(PTC_LOCK(shub1), flags); |
262 | 281 | ||
263 | preempt_enable(); | 282 | preempt_enable(); |
264 | } | 283 | } |
@@ -270,11 +289,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | |||
270 | * TLB flush transaction. The recovery sequence is somewhat tricky & is | 289 | * TLB flush transaction. The recovery sequence is somewhat tricky & is |
271 | * coded in assembly language. | 290 | * coded in assembly language. |
272 | */ | 291 | */ |
273 | void sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid, volatile unsigned long *ptc0, unsigned long data0, | 292 | |
274 | volatile unsigned long *ptc1, unsigned long data1) | 293 | void |
294 | sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid, | ||
295 | volatile unsigned long *ptc0, unsigned long data0, | ||
296 | volatile unsigned long *ptc1, unsigned long data1) | ||
275 | { | 297 | { |
276 | extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, | ||
277 | volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long); | ||
278 | short nasid, i; | 298 | short nasid, i; |
279 | unsigned long *piows, zeroval, n; | 299 | unsigned long *piows, zeroval, n; |
280 | 300 | ||
@@ -447,7 +467,7 @@ static struct proc_dir_entry *proc_sn2_ptc; | |||
447 | static int __init sn2_ptc_init(void) | 467 | static int __init sn2_ptc_init(void) |
448 | { | 468 | { |
449 | if (!ia64_platform_is("sn2")) | 469 | if (!ia64_platform_is("sn2")) |
450 | return -ENOSYS; | 470 | return 0; |
451 | 471 | ||
452 | if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { | 472 | if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { |
453 | printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); | 473 | 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 19b54fbcd7e..70db21f3df2 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 a06719d752a..c686d9c12f7 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 deb9baf4d47..56a88b6df4b 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 adf5db2e2af..fa7f6994591 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 d263d3e8fbb..99cb28e7429 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 36e5437a0fb..cdf6856ce08 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c | |||
@@ -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 9cd460dfe27..8cbf1643257 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c | |||
@@ -750,12 +750,16 @@ xpc_daemonize_kthread(void *args) | |||
750 | /* let registerer know that connection has been established */ | 750 | /* let registerer know that connection has been established */ |
751 | 751 | ||
752 | spin_lock_irqsave(&ch->lock, irq_flags); | 752 | spin_lock_irqsave(&ch->lock, irq_flags); |
753 | if (!(ch->flags & XPC_C_CONNECTCALLOUT)) { | 753 | if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) { |
754 | ch->flags |= XPC_C_CONNECTCALLOUT; | 754 | ch->flags |= XPC_C_CONNECTEDCALLOUT; |
755 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 755 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
756 | 756 | ||
757 | xpc_connected_callout(ch); | 757 | xpc_connected_callout(ch); |
758 | 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 | |||
759 | /* | 763 | /* |
760 | * It is possible that while the callout was being | 764 | * It is possible that while the callout was being |
761 | * made that the remote partition sent some messages. | 765 | * made that the remote partition sent some messages. |
@@ -777,15 +781,17 @@ xpc_daemonize_kthread(void *args) | |||
777 | 781 | ||
778 | if (atomic_dec_return(&ch->kthreads_assigned) == 0) { | 782 | if (atomic_dec_return(&ch->kthreads_assigned) == 0) { |
779 | spin_lock_irqsave(&ch->lock, irq_flags); | 783 | spin_lock_irqsave(&ch->lock, irq_flags); |
780 | if ((ch->flags & XPC_C_CONNECTCALLOUT) && | 784 | if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && |
781 | !(ch->flags & XPC_C_DISCONNECTCALLOUT)) { | 785 | !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { |
782 | ch->flags |= XPC_C_DISCONNECTCALLOUT; | 786 | ch->flags |= XPC_C_DISCONNECTINGCALLOUT; |
783 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 787 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
784 | 788 | ||
785 | xpc_disconnect_callout(ch, xpcDisconnecting); | 789 | xpc_disconnect_callout(ch, xpcDisconnecting); |
786 | } else { | 790 | |
787 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 791 | spin_lock_irqsave(&ch->lock, irq_flags); |
792 | ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; | ||
788 | } | 793 | } |
794 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
789 | if (atomic_dec_return(&part->nchannels_engaged) == 0) { | 795 | if (atomic_dec_return(&part->nchannels_engaged) == 0) { |
790 | xpc_mark_partition_disengaged(part); | 796 | xpc_mark_partition_disengaged(part); |
791 | xpc_IPI_send_disengage(part); | 797 | xpc_IPI_send_disengage(part); |
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 5a36292388e..b4b84c26921 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c | |||
@@ -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/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index aa3fa5152a3..1f0253bfe0a 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 54ce5b7ceed..9f86bb6519a 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 2fac27049bf..98f716bd92f 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 */ |
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index e52831ed93e..fa073cc4b56 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c | |||
@@ -15,6 +15,124 @@ | |||
15 | #include <asm/sn/pcidev.h> | 15 | #include <asm/sn/pcidev.h> |
16 | #include <asm/sn/pcibus_provider_defs.h> | 16 | #include <asm/sn/pcibus_provider_defs.h> |
17 | #include <asm/sn/tioce_provider.h> | 17 | #include <asm/sn/tioce_provider.h> |
18 | #include <asm/sn/sn2/sn_hwperf.h> | ||
19 | |||
20 | /* | ||
21 | * 1/26/2006 | ||
22 | * | ||
23 | * WAR for SGI PV 944642. For revA TIOCE, need to use the following recipe | ||
24 | * (taken from the above PV) before and after accessing tioce internal MMR's | ||
25 | * to avoid tioce lockups. | ||
26 | * | ||
27 | * The recipe as taken from the PV: | ||
28 | * | ||
29 | * if(mmr address < 0x45000) { | ||
30 | * if(mmr address == 0 or 0x80) | ||
31 | * mmr wrt or read address 0xc0 | ||
32 | * else if(mmr address == 0x148 or 0x200) | ||
33 | * mmr wrt or read address 0x28 | ||
34 | * else | ||
35 | * mmr wrt or read address 0x158 | ||
36 | * | ||
37 | * do desired mmr access (rd or wrt) | ||
38 | * | ||
39 | * if(mmr address == 0x100) | ||
40 | * mmr wrt or read address 0x38 | ||
41 | * mmr wrt or read address 0xb050 | ||
42 | * } else | ||
43 | * do desired mmr access | ||
44 | * | ||
45 | * According to hw, we can use reads instead of writes to the above addres | ||
46 | * | ||
47 | * Note this WAR can only to be used for accessing internal MMR's in the | ||
48 | * TIOCE Coretalk Address Range 0x0 - 0x07ff_ffff. This includes the | ||
49 | * "Local CE Registers and Memories" and "PCI Compatible Config Space" address | ||
50 | * spaces from table 2-1 of the "CE Programmer's Reference Overview" document. | ||
51 | * | ||
52 | * All registers defined in struct tioce will meet that criteria. | ||
53 | */ | ||
54 | |||
55 | static void inline | ||
56 | tioce_mmr_war_pre(struct tioce_kernel *kern, void *mmr_addr) | ||
57 | { | ||
58 | u64 mmr_base; | ||
59 | u64 mmr_offset; | ||
60 | |||
61 | if (kern->ce_common->ce_rev != TIOCE_REV_A) | ||
62 | return; | ||
63 | |||
64 | mmr_base = kern->ce_common->ce_pcibus.bs_base; | ||
65 | mmr_offset = (u64)mmr_addr - mmr_base; | ||
66 | |||
67 | if (mmr_offset < 0x45000) { | ||
68 | u64 mmr_war_offset; | ||
69 | |||
70 | if (mmr_offset == 0 || mmr_offset == 0x80) | ||
71 | mmr_war_offset = 0xc0; | ||
72 | else if (mmr_offset == 0x148 || mmr_offset == 0x200) | ||
73 | mmr_war_offset = 0x28; | ||
74 | else | ||
75 | mmr_war_offset = 0x158; | ||
76 | |||
77 | readq_relaxed((void *)(mmr_base + mmr_war_offset)); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static void inline | ||
82 | tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr) | ||
83 | { | ||
84 | u64 mmr_base; | ||
85 | u64 mmr_offset; | ||
86 | |||
87 | if (kern->ce_common->ce_rev != TIOCE_REV_A) | ||
88 | return; | ||
89 | |||
90 | mmr_base = kern->ce_common->ce_pcibus.bs_base; | ||
91 | mmr_offset = (u64)mmr_addr - mmr_base; | ||
92 | |||
93 | if (mmr_offset < 0x45000) { | ||
94 | if (mmr_offset == 0x100) | ||
95 | readq_relaxed((void *)(mmr_base + 0x38)); | ||
96 | readq_relaxed((void *)(mmr_base + 0xb050)); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* load mmr contents into a variable */ | ||
101 | #define tioce_mmr_load(kern, mmrp, varp) do {\ | ||
102 | tioce_mmr_war_pre(kern, mmrp); \ | ||
103 | *(varp) = readq_relaxed(mmrp); \ | ||
104 | tioce_mmr_war_post(kern, mmrp); \ | ||
105 | } while (0) | ||
106 | |||
107 | /* store variable contents into mmr */ | ||
108 | #define tioce_mmr_store(kern, mmrp, varp) do {\ | ||
109 | tioce_mmr_war_pre(kern, mmrp); \ | ||
110 | writeq(*varp, mmrp); \ | ||
111 | tioce_mmr_war_post(kern, mmrp); \ | ||
112 | } while (0) | ||
113 | |||
114 | /* store immediate value into mmr */ | ||
115 | #define tioce_mmr_storei(kern, mmrp, val) do {\ | ||
116 | tioce_mmr_war_pre(kern, mmrp); \ | ||
117 | writeq(val, mmrp); \ | ||
118 | tioce_mmr_war_post(kern, mmrp); \ | ||
119 | } while (0) | ||
120 | |||
121 | /* set bits (immediate value) into mmr */ | ||
122 | #define tioce_mmr_seti(kern, mmrp, bits) do {\ | ||
123 | u64 tmp; \ | ||
124 | tioce_mmr_load(kern, mmrp, &tmp); \ | ||
125 | tmp |= (bits); \ | ||
126 | tioce_mmr_store(kern, mmrp, &tmp); \ | ||
127 | } while (0) | ||
128 | |||
129 | /* clear bits (immediate value) into mmr */ | ||
130 | #define tioce_mmr_clri(kern, mmrp, bits) do { \ | ||
131 | u64 tmp; \ | ||
132 | tioce_mmr_load(kern, mmrp, &tmp); \ | ||
133 | tmp &= ~(bits); \ | ||
134 | tioce_mmr_store(kern, mmrp, &tmp); \ | ||
135 | } while (0) | ||
18 | 136 | ||
19 | /** | 137 | /** |
20 | * Bus address ranges for the 5 flavors of TIOCE DMA | 138 | * Bus address ranges for the 5 flavors of TIOCE DMA |
@@ -62,9 +180,9 @@ | |||
62 | #define TIOCE_ATE_M40 2 | 180 | #define TIOCE_ATE_M40 2 |
63 | #define TIOCE_ATE_M40S 3 | 181 | #define TIOCE_ATE_M40S 3 |
64 | 182 | ||
65 | #define KB(x) ((x) << 10) | 183 | #define KB(x) ((u64)(x) << 10) |
66 | #define MB(x) ((x) << 20) | 184 | #define MB(x) ((u64)(x) << 20) |
67 | #define GB(x) ((x) << 30) | 185 | #define GB(x) ((u64)(x) << 30) |
68 | 186 | ||
69 | /** | 187 | /** |
70 | * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode | 188 | * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode |
@@ -151,7 +269,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
151 | int last; | 269 | int last; |
152 | int entries; | 270 | int entries; |
153 | int nates; | 271 | int nates; |
154 | int pagesize; | 272 | u64 pagesize; |
155 | u64 *ate_shadow; | 273 | u64 *ate_shadow; |
156 | u64 *ate_reg; | 274 | u64 *ate_reg; |
157 | u64 addr; | 275 | u64 addr; |
@@ -228,7 +346,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
228 | 346 | ||
229 | ate = ATE_MAKE(addr, pagesize); | 347 | ate = ATE_MAKE(addr, pagesize); |
230 | ate_shadow[i + j] = ate; | 348 | ate_shadow[i + j] = ate; |
231 | writeq(ate, &ate_reg[i + j]); | 349 | tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate); |
232 | addr += pagesize; | 350 | addr += pagesize; |
233 | } | 351 | } |
234 | 352 | ||
@@ -272,7 +390,8 @@ tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) | |||
272 | u64 tmp; | 390 | u64 tmp; |
273 | 391 | ||
274 | ce_kern->ce_port[port].dirmap_shadow = ct_upper; | 392 | ce_kern->ce_port[port].dirmap_shadow = ct_upper; |
275 | writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]); | 393 | tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port], |
394 | ct_upper); | ||
276 | tmp = ce_mmr->ce_ure_dir_map[port]; | 395 | tmp = ce_mmr->ce_ure_dir_map[port]; |
277 | dma_ok = 1; | 396 | dma_ok = 1; |
278 | } else | 397 | } else |
@@ -344,7 +463,8 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) | |||
344 | if (TIOCE_D32_ADDR(bus_addr)) { | 463 | if (TIOCE_D32_ADDR(bus_addr)) { |
345 | if (--ce_kern->ce_port[port].dirmap_refcnt == 0) { | 464 | if (--ce_kern->ce_port[port].dirmap_refcnt == 0) { |
346 | ce_kern->ce_port[port].dirmap_shadow = 0; | 465 | ce_kern->ce_port[port].dirmap_shadow = 0; |
347 | writeq(0, &ce_mmr->ce_ure_dir_map[port]); | 466 | tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port], |
467 | 0); | ||
348 | } | 468 | } |
349 | } else { | 469 | } else { |
350 | struct tioce_dmamap *map; | 470 | struct tioce_dmamap *map; |
@@ -365,7 +485,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) | |||
365 | } else if (--map->refcnt == 0) { | 485 | } else if (--map->refcnt == 0) { |
366 | for (i = 0; i < map->ate_count; i++) { | 486 | for (i = 0; i < map->ate_count; i++) { |
367 | map->ate_shadow[i] = 0; | 487 | map->ate_shadow[i] = 0; |
368 | map->ate_hw[i] = 0; | 488 | tioce_mmr_storei(ce_kern, &map->ate_hw[i], 0); |
369 | } | 489 | } |
370 | 490 | ||
371 | list_del(&map->ce_dmamap_list); | 491 | list_del(&map->ce_dmamap_list); |
@@ -486,7 +606,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, | |||
486 | spin_unlock_irqrestore(&ce_kern->ce_lock, flags); | 606 | spin_unlock_irqrestore(&ce_kern->ce_lock, flags); |
487 | 607 | ||
488 | dma_map_done: | 608 | dma_map_done: |
489 | if (mapaddr & barrier) | 609 | if (mapaddr && barrier) |
490 | mapaddr = tioce_dma_barrier(mapaddr, 1); | 610 | mapaddr = tioce_dma_barrier(mapaddr, 1); |
491 | 611 | ||
492 | return mapaddr; | 612 | return mapaddr; |
@@ -541,17 +661,61 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) | |||
541 | soft->ce_pcibus.bs_persist_segment, | 661 | soft->ce_pcibus.bs_persist_segment, |
542 | soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0); | 662 | soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0); |
543 | 663 | ||
664 | if (ret_stuff.v0) | ||
665 | panic("tioce_error_intr_handler: Fatal TIOCE error"); | ||
666 | |||
544 | return IRQ_HANDLED; | 667 | return IRQ_HANDLED; |
545 | } | 668 | } |
546 | 669 | ||
547 | /** | 670 | /** |
671 | * tioce_reserve_m32 - reserve M32 ate's for the indicated address range | ||
672 | * @tioce_kernel: TIOCE context to reserve ate's for | ||
673 | * @base: starting bus address to reserve | ||
674 | * @limit: last bus address to reserve | ||
675 | * | ||
676 | * If base/limit falls within the range of bus space mapped through the | ||
677 | * M32 space, reserve the resources corresponding to the range. | ||
678 | */ | ||
679 | static void | ||
680 | tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit) | ||
681 | { | ||
682 | int ate_index, last_ate, ps; | ||
683 | struct tioce *ce_mmr; | ||
684 | |||
685 | if (!TIOCE_M32_ADDR(base)) | ||
686 | return; | ||
687 | |||
688 | ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; | ||
689 | ps = ce_kern->ce_ate3240_pagesize; | ||
690 | ate_index = ATE_PAGE(base, ps); | ||
691 | last_ate = ate_index + ATE_NPAGES(base, limit-base+1, ps) - 1; | ||
692 | |||
693 | if (ate_index < 64) | ||
694 | ate_index = 64; | ||
695 | |||
696 | while (ate_index <= last_ate) { | ||
697 | u64 ate; | ||
698 | |||
699 | ate = ATE_MAKE(0xdeadbeef, ps); | ||
700 | ce_kern->ce_ate3240_shadow[ate_index] = ate; | ||
701 | tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index], | ||
702 | ate); | ||
703 | ate_index++; | ||
704 | } | ||
705 | } | ||
706 | |||
707 | /** | ||
548 | * tioce_kern_init - init kernel structures related to a given TIOCE | 708 | * tioce_kern_init - init kernel structures related to a given TIOCE |
549 | * @tioce_common: ptr to a cached tioce_common struct that originated in prom | 709 | * @tioce_common: ptr to a cached tioce_common struct that originated in prom |
550 | */ static struct tioce_kernel * | 710 | */ |
711 | static struct tioce_kernel * | ||
551 | tioce_kern_init(struct tioce_common *tioce_common) | 712 | tioce_kern_init(struct tioce_common *tioce_common) |
552 | { | 713 | { |
553 | int i; | 714 | int i; |
715 | int ps; | ||
716 | int dev; | ||
554 | u32 tmp; | 717 | u32 tmp; |
718 | unsigned int seg, bus; | ||
555 | struct tioce *tioce_mmr; | 719 | struct tioce *tioce_mmr; |
556 | struct tioce_kernel *tioce_kern; | 720 | struct tioce_kernel *tioce_kern; |
557 | 721 | ||
@@ -572,9 +736,10 @@ tioce_kern_init(struct tioce_common *tioce_common) | |||
572 | * here to use pci_read_config_xxx() so use the raw_pci_ops vector. | 736 | * here to use pci_read_config_xxx() so use the raw_pci_ops vector. |
573 | */ | 737 | */ |
574 | 738 | ||
575 | raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, | 739 | seg = tioce_common->ce_pcibus.bs_persist_segment; |
576 | tioce_common->ce_pcibus.bs_persist_busnum, | 740 | bus = tioce_common->ce_pcibus.bs_persist_busnum; |
577 | PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); | 741 | |
742 | raw_pci_ops->read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp); | ||
578 | tioce_kern->ce_port1_secondary = (u8) tmp; | 743 | tioce_kern->ce_port1_secondary = (u8) tmp; |
579 | 744 | ||
580 | /* | 745 | /* |
@@ -583,18 +748,76 @@ tioce_kern_init(struct tioce_common *tioce_common) | |||
583 | */ | 748 | */ |
584 | 749 | ||
585 | tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base; | 750 | tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base; |
586 | __sn_clrq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_PAGESIZE_MASK); | 751 | tioce_mmr_clri(tioce_kern, &tioce_mmr->ce_ure_page_map, |
587 | __sn_setq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_256K_PAGESIZE); | 752 | CE_URE_PAGESIZE_MASK); |
588 | tioce_kern->ce_ate3240_pagesize = KB(256); | 753 | tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_ure_page_map, |
754 | CE_URE_256K_PAGESIZE); | ||
755 | ps = tioce_kern->ce_ate3240_pagesize = KB(256); | ||
589 | 756 | ||
590 | for (i = 0; i < TIOCE_NUM_M40_ATES; i++) { | 757 | for (i = 0; i < TIOCE_NUM_M40_ATES; i++) { |
591 | tioce_kern->ce_ate40_shadow[i] = 0; | 758 | tioce_kern->ce_ate40_shadow[i] = 0; |
592 | writeq(0, &tioce_mmr->ce_ure_ate40[i]); | 759 | tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate40[i], 0); |
593 | } | 760 | } |
594 | 761 | ||
595 | for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) { | 762 | for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) { |
596 | tioce_kern->ce_ate3240_shadow[i] = 0; | 763 | tioce_kern->ce_ate3240_shadow[i] = 0; |
597 | writeq(0, &tioce_mmr->ce_ure_ate3240[i]); | 764 | tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate3240[i], 0); |
765 | } | ||
766 | |||
767 | /* | ||
768 | * Reserve ATE's corresponding to reserved address ranges. These | ||
769 | * include: | ||
770 | * | ||
771 | * Memory space covered by each PPB mem base/limit register | ||
772 | * Memory space covered by each PPB prefetch base/limit register | ||
773 | * | ||
774 | * These bus ranges are for pio (downstream) traffic only, and so | ||
775 | * cannot be used for DMA. | ||
776 | */ | ||
777 | |||
778 | for (dev = 1; dev <= 2; dev++) { | ||
779 | u64 base, limit; | ||
780 | |||
781 | /* mem base/limit */ | ||
782 | |||
783 | raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), | ||
784 | PCI_MEMORY_BASE, 2, &tmp); | ||
785 | base = (u64)tmp << 16; | ||
786 | |||
787 | raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), | ||
788 | PCI_MEMORY_LIMIT, 2, &tmp); | ||
789 | limit = (u64)tmp << 16; | ||
790 | limit |= 0xfffffUL; | ||
791 | |||
792 | if (base < limit) | ||
793 | tioce_reserve_m32(tioce_kern, base, limit); | ||
794 | |||
795 | /* | ||
796 | * prefetch mem base/limit. The tioce ppb's have 64-bit | ||
797 | * decoders, so read the upper portions w/o checking the | ||
798 | * attributes. | ||
799 | */ | ||
800 | |||
801 | raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), | ||
802 | PCI_PREF_MEMORY_BASE, 2, &tmp); | ||
803 | base = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16; | ||
804 | |||
805 | raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), | ||
806 | PCI_PREF_BASE_UPPER32, 4, &tmp); | ||
807 | base |= (u64)tmp << 32; | ||
808 | |||
809 | raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), | ||
810 | PCI_PREF_MEMORY_LIMIT, 2, &tmp); | ||
811 | |||
812 | limit = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16; | ||
813 | limit |= 0xfffffUL; | ||
814 | |||
815 | raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0), | ||
816 | PCI_PREF_LIMIT_UPPER32, 4, &tmp); | ||
817 | limit |= (u64)tmp << 32; | ||
818 | |||
819 | if ((base < limit) && TIOCE_M32_ADDR(base)) | ||
820 | tioce_reserve_m32(tioce_kern, base, limit); | ||
598 | } | 821 | } |
599 | 822 | ||
600 | return tioce_kern; | 823 | return tioce_kern; |
@@ -614,6 +837,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) | |||
614 | { | 837 | { |
615 | struct pcidev_info *pcidev_info; | 838 | struct pcidev_info *pcidev_info; |
616 | struct tioce_common *ce_common; | 839 | struct tioce_common *ce_common; |
840 | struct tioce_kernel *ce_kern; | ||
617 | struct tioce *ce_mmr; | 841 | struct tioce *ce_mmr; |
618 | u64 force_int_val; | 842 | u64 force_int_val; |
619 | 843 | ||
@@ -629,6 +853,29 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) | |||
629 | 853 | ||
630 | ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; | 854 | ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; |
631 | ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; | 855 | ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; |
856 | ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private; | ||
857 | |||
858 | /* | ||
859 | * TIOCE Rev A workaround (PV 945826), force an interrupt by writing | ||
860 | * the TIO_INTx register directly (1/26/2006) | ||
861 | */ | ||
862 | if (ce_common->ce_rev == TIOCE_REV_A) { | ||
863 | u64 int_bit_mask = (1ULL << sn_irq_info->irq_int_bit); | ||
864 | u64 status; | ||
865 | |||
866 | tioce_mmr_load(ce_kern, &ce_mmr->ce_adm_int_status, &status); | ||
867 | if (status & int_bit_mask) { | ||
868 | u64 force_irq = (1 << 8) | sn_irq_info->irq_irq; | ||
869 | u64 ctalk = sn_irq_info->irq_xtalkaddr; | ||
870 | u64 nasid, offset; | ||
871 | |||
872 | nasid = (ctalk & CTALK_NASID_MASK) >> CTALK_NASID_SHFT; | ||
873 | offset = (ctalk & CTALK_NODE_OFFSET); | ||
874 | HUB_S(TIO_IOSPACE_ADDR(nasid, offset), force_irq); | ||
875 | } | ||
876 | |||
877 | return; | ||
878 | } | ||
632 | 879 | ||
633 | /* | 880 | /* |
634 | * irq_int_bit is originally set up by prom, and holds the interrupt | 881 | * irq_int_bit is originally set up by prom, and holds the interrupt |
@@ -666,7 +913,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) | |||
666 | default: | 913 | default: |
667 | return; | 914 | return; |
668 | } | 915 | } |
669 | writeq(force_int_val, &ce_mmr->ce_adm_force_int); | 916 | tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_force_int, force_int_val); |
670 | } | 917 | } |
671 | 918 | ||
672 | /** | 919 | /** |
@@ -685,6 +932,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) | |||
685 | { | 932 | { |
686 | struct pcidev_info *pcidev_info; | 933 | struct pcidev_info *pcidev_info; |
687 | struct tioce_common *ce_common; | 934 | struct tioce_common *ce_common; |
935 | struct tioce_kernel *ce_kern; | ||
688 | struct tioce *ce_mmr; | 936 | struct tioce *ce_mmr; |
689 | int bit; | 937 | int bit; |
690 | u64 vector; | 938 | u64 vector; |
@@ -695,14 +943,15 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) | |||
695 | 943 | ||
696 | ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; | 944 | ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; |
697 | ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; | 945 | ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; |
946 | ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private; | ||
698 | 947 | ||
699 | bit = sn_irq_info->irq_int_bit; | 948 | bit = sn_irq_info->irq_int_bit; |
700 | 949 | ||
701 | __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); | 950 | tioce_mmr_seti(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit)); |
702 | vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; | 951 | vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; |
703 | vector |= sn_irq_info->irq_xtalkaddr; | 952 | vector |= sn_irq_info->irq_xtalkaddr; |
704 | writeq(vector, &ce_mmr->ce_adm_int_dest[bit]); | 953 | tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_int_dest[bit], vector); |
705 | __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); | 954 | tioce_mmr_clri(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit)); |
706 | 955 | ||
707 | tioce_force_interrupt(sn_irq_info); | 956 | tioce_force_interrupt(sn_irq_info); |
708 | } | 957 | } |
@@ -721,7 +970,11 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) | |||
721 | static void * | 970 | static void * |
722 | tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) | 971 | tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) |
723 | { | 972 | { |
973 | int my_nasid; | ||
974 | cnodeid_t my_cnode, mem_cnode; | ||
724 | struct tioce_common *tioce_common; | 975 | struct tioce_common *tioce_common; |
976 | struct tioce_kernel *tioce_kern; | ||
977 | struct tioce *tioce_mmr; | ||
725 | 978 | ||
726 | /* | 979 | /* |
727 | * Allocate kernel bus soft and copy from prom. | 980 | * Allocate kernel bus soft and copy from prom. |
@@ -734,11 +987,23 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
734 | memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common)); | 987 | memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common)); |
735 | tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET; | 988 | tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET; |
736 | 989 | ||
737 | if (tioce_kern_init(tioce_common) == NULL) { | 990 | tioce_kern = tioce_kern_init(tioce_common); |
991 | if (tioce_kern == NULL) { | ||
738 | kfree(tioce_common); | 992 | kfree(tioce_common); |
739 | return NULL; | 993 | return NULL; |
740 | } | 994 | } |
741 | 995 | ||
996 | /* | ||
997 | * Clear out any transient errors before registering the error | ||
998 | * interrupt handler. | ||
999 | */ | ||
1000 | |||
1001 | tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base; | ||
1002 | tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL); | ||
1003 | tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias, | ||
1004 | ~0ULL); | ||
1005 | tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL); | ||
1006 | |||
742 | if (request_irq(SGI_PCIASIC_ERROR, | 1007 | if (request_irq(SGI_PCIASIC_ERROR, |
743 | tioce_error_intr_handler, | 1008 | tioce_error_intr_handler, |
744 | SA_SHIRQ, "TIOCE error", (void *)tioce_common)) | 1009 | SA_SHIRQ, "TIOCE error", (void *)tioce_common)) |
@@ -750,6 +1015,21 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
750 | tioce_common->ce_pcibus.bs_persist_segment, | 1015 | tioce_common->ce_pcibus.bs_persist_segment, |
751 | tioce_common->ce_pcibus.bs_persist_busnum); | 1016 | tioce_common->ce_pcibus.bs_persist_busnum); |
752 | 1017 | ||
1018 | /* | ||
1019 | * identify closest nasid for memory allocations | ||
1020 | */ | ||
1021 | |||
1022 | my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base); | ||
1023 | my_cnode = nasid_to_cnodeid(my_nasid); | ||
1024 | |||
1025 | if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) { | ||
1026 | printk(KERN_WARNING "tioce_bus_fixup: failed to find " | ||
1027 | "closest node with MEM to TIO node %d\n", my_cnode); | ||
1028 | mem_cnode = (cnodeid_t)-1; /* use any node */ | ||
1029 | } | ||
1030 | |||
1031 | controller->node = mem_cnode; | ||
1032 | |||
753 | return tioce_common; | 1033 | return tioce_common; |
754 | } | 1034 | } |
755 | 1035 | ||