···217217 If you are compiling a kernel that will run under SGI's IA-64218218 simulator (Medusa) then say Y, otherwise say N.219219220220+config IA64_SGI_SN_XP221221+ tristate "Support communication between SGI SSIs"222222+ depends on MSPEC223223+ help224224+ An SGI machine can be divided into multiple Single System225225+ Images which act independently of each other and have226226+ hardware based memory protection from the others. Enabling227227+ this feature will allow for direct communication between SSIs228228+ based on a network adapter and DMA messaging.229229+220230config FORCE_MAX_ZONEORDER221231 int222232 default "18"···270260 Say Y here to experiment with turning CPUs off and on. CPUs271261 can be controlled through /sys/devices/system/cpu/cpu#.272262 Say N if you want to disable CPU hotplug.263263+264264+config SCHED_SMT265265+ bool "SMT scheduler support"266266+ depends on SMP267267+ default off268268+ help269269+ Improves the CPU scheduler's decision making when dealing with270270+ Intel IA64 chips with MultiThreading at a cost of slightly increased271271+ overhead in some places. If unsure say N here.273272274273config PREEMPT275274 bool "Preemptible Kernel"
+57-39
arch/ia64/configs/tiger_defconfig
···11#22# Automatically generated make config: don't edit33-# Linux kernel version: 2.6.11-rc244-# Sat Jan 22 11:17:02 200533+# Linux kernel version: 2.6.12-rc344+# Tue May 3 15:55:04 200555#6677#···1010CONFIG_EXPERIMENTAL=y1111CONFIG_CLEAN_COMPILE=y1212CONFIG_LOCK_KERNEL=y1313+CONFIG_INIT_ENV_ARG_LIMIT=3213141415#1516# General setup···2221# CONFIG_BSD_PROCESS_ACCT is not set2322CONFIG_SYSCTL=y2423# CONFIG_AUDIT is not set2525-CONFIG_LOG_BUF_SHIFT=202624CONFIG_HOTPLUG=y2725CONFIG_KOBJECT_UEVENT=y2826CONFIG_IKCONFIG=y2927CONFIG_IKCONFIG_PROC=y2828+# CONFIG_CPUSETS is not set3029# CONFIG_EMBEDDED is not set3130CONFIG_KALLSYMS=y3231CONFIG_KALLSYMS_ALL=y3332# CONFIG_KALLSYMS_EXTRA_PASS is not set3333+CONFIG_PRINTK=y3434+CONFIG_BUG=y3535+CONFIG_BASE_FULL=y3436CONFIG_FUTEX=y3537CONFIG_EPOLL=y3636-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set3738CONFIG_SHMEM=y3839CONFIG_CC_ALIGN_FUNCTIONS=03940CONFIG_CC_ALIGN_LABELS=04041CONFIG_CC_ALIGN_LOOPS=04142CONFIG_CC_ALIGN_JUMPS=04243# CONFIG_TINY_SHMEM is not set4444+CONFIG_BASE_SMALL=043454446#4547# Loadable module support···8985CONFIG_SMP=y9086CONFIG_NR_CPUS=49187CONFIG_HOTPLUG_CPU=y8888+# CONFIG_SCHED_SMT is not set9289# CONFIG_PREEMPT is not set9390CONFIG_HAVE_DEC_LOCK=y9491CONFIG_IA32_SUPPORT=y···140135# CONFIG_PCI_MSI is not set141136CONFIG_PCI_LEGACY_PROC=y142137CONFIG_PCI_NAMES=y138138+# CONFIG_PCI_DEBUG is not set143139144140#145141# PCI Hotplug Support···156150# PCCARD (PCMCIA/CardBus) support157151#158152# CONFIG_PCCARD is not set159159-160160-#161161-# PC-card bridges162162-#163153164154#165155# Device Drivers···197195CONFIG_BLK_DEV_NBD=m198196# CONFIG_BLK_DEV_SX8 is not set199197# CONFIG_BLK_DEV_UB is not set200200-CONFIG_BLK_DEV_RAM=m198198+CONFIG_BLK_DEV_RAM=y201199CONFIG_BLK_DEV_RAM_COUNT=16202200CONFIG_BLK_DEV_RAM_SIZE=4096201201+CONFIG_BLK_DEV_INITRD=y203202CONFIG_INITRAMFS_SOURCE=""204203# CONFIG_CDROM_PKTCDVD is not set205204···316313# CONFIG_SCSI_BUSLOGIC is not set317314# CONFIG_SCSI_DMX3191D is not set318315# CONFIG_SCSI_EATA is not set319319-# CONFIG_SCSI_EATA_PIO is not set320316# CONFIG_SCSI_FUTURE_DOMAIN is not set321317# CONFIG_SCSI_GDTH is not set322318# CONFIG_SCSI_IPS is not set···327325CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64328326# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set329327# CONFIG_SCSI_IPR is not set330330-# CONFIG_SCSI_QLOGIC_ISP is not set331328CONFIG_SCSI_QLOGIC_FC=y332329# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set333330CONFIG_SCSI_QLOGIC_1280=y···337336CONFIG_SCSI_QLA2300=m338337CONFIG_SCSI_QLA2322=m339338# CONFIG_SCSI_QLA6312 is not set339339+# CONFIG_SCSI_LPFC is not set340340# CONFIG_SCSI_DC395x is not set341341# CONFIG_SCSI_DC390T is not set342342# CONFIG_SCSI_DEBUG is not set···360358CONFIG_DM_SNAPSHOT=m361359CONFIG_DM_MIRROR=m362360CONFIG_DM_ZERO=m361361+# CONFIG_DM_MULTIPATH is not set363362364363#365364# Fusion MPT device support···389386#390387CONFIG_PACKET=y391388# CONFIG_PACKET_MMAP is not set392392-CONFIG_NETLINK_DEV=y393389CONFIG_UNIX=y394390# CONFIG_NET_KEY is not set395391CONFIG_INET=y···448446# CONFIG_BONDING is not set449447# CONFIG_EQUALIZER is not set450448# CONFIG_TUN is not set451451-# CONFIG_ETHERTAP is not set452449453450#454451# ARCnet devices···485484# CONFIG_DGRS is not set486485CONFIG_EEPRO100=m487486CONFIG_E100=m488488-# CONFIG_E100_NAPI is not set489487# CONFIG_FEALNX is not set490488# CONFIG_NATSEMI is not set491489# CONFIG_NE2K_PCI is not set···566566# CONFIG_INPUT_EVBUG is not set567567568568#569569-# Input I/O drivers570570-#571571-CONFIG_GAMEPORT=m572572-CONFIG_SOUND_GAMEPORT=m573573-# CONFIG_GAMEPORT_NS558 is not set574574-# CONFIG_GAMEPORT_L4 is not set575575-# CONFIG_GAMEPORT_EMU10K1 is not set576576-# CONFIG_GAMEPORT_VORTEX is not set577577-# CONFIG_GAMEPORT_FM801 is not set578578-# CONFIG_GAMEPORT_CS461X is not set579579-CONFIG_SERIO=y580580-CONFIG_SERIO_I8042=y581581-# CONFIG_SERIO_SERPORT is not set582582-# CONFIG_SERIO_CT82C710 is not set583583-# CONFIG_SERIO_PCIPS2 is not set584584-CONFIG_SERIO_LIBPS2=y585585-# CONFIG_SERIO_RAW is not set586586-587587-#588569# Input Device Drivers589570#590571CONFIG_INPUT_KEYBOARD=y···583602# CONFIG_INPUT_MISC is not set584603585604#605605+# Hardware I/O ports606606+#607607+CONFIG_SERIO=y608608+CONFIG_SERIO_I8042=y609609+# CONFIG_SERIO_SERPORT is not set610610+# CONFIG_SERIO_PCIPS2 is not set611611+CONFIG_SERIO_LIBPS2=y612612+# CONFIG_SERIO_RAW is not set613613+CONFIG_GAMEPORT=m614614+# CONFIG_GAMEPORT_NS558 is not set615615+# CONFIG_GAMEPORT_L4 is not set616616+# CONFIG_GAMEPORT_EMU10K1 is not set617617+# CONFIG_GAMEPORT_VORTEX is not set618618+# CONFIG_GAMEPORT_FM801 is not set619619+# CONFIG_GAMEPORT_CS461X is not set620620+CONFIG_SOUND_GAMEPORT=m621621+622622+#586623# Character devices587624#588625CONFIG_VT=y···614615# CONFIG_SYNCLINK is not set615616# CONFIG_SYNCLINKMP is not set616617# CONFIG_N_HDLC is not set618618+# CONFIG_SPECIALIX is not set619619+# CONFIG_SX is not set617620# CONFIG_STALDRV is not set618621619622#···636635#637636CONFIG_SERIAL_CORE=y638637CONFIG_SERIAL_CORE_CONSOLE=y638638+# CONFIG_SERIAL_JSM is not set639639CONFIG_UNIX98_PTYS=y640640CONFIG_LEGACY_PTYS=y641641CONFIG_LEGACY_PTY_COUNT=256···672670# CONFIG_HPET_RTC_IRQ is not set673671CONFIG_HPET_MMAP=y674672CONFIG_MAX_RAW_DEVS=256673673+# CONFIG_HANGCHECK_TIMER is not set674674+675675+#676676+# TPM devices677677+#678678+# CONFIG_TCG_TPM is not set675679676680#677681# I2C support···713705#714706CONFIG_VGA_CONSOLE=y715707CONFIG_DUMMY_CONSOLE=y716716-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set717708718709#719710# Sound···722715#723716# USB support724717#718718+CONFIG_USB_ARCH_HAS_HCD=y719719+CONFIG_USB_ARCH_HAS_OHCI=y725720CONFIG_USB=y726721# CONFIG_USB_DEBUG is not set727722···735726# CONFIG_USB_DYNAMIC_MINORS is not set736727# CONFIG_USB_SUSPEND is not set737728# CONFIG_USB_OTG is not set738738-CONFIG_USB_ARCH_HAS_HCD=y739739-CONFIG_USB_ARCH_HAS_OHCI=y740729741730#742731# USB Host Controller Drivers···743736# CONFIG_USB_EHCI_SPLIT_ISO is not set744737# CONFIG_USB_EHCI_ROOT_HUB_TT is not set745738CONFIG_USB_OHCI_HCD=m739739+# CONFIG_USB_OHCI_BIG_ENDIAN is not set740740+CONFIG_USB_OHCI_LITTLE_ENDIAN=y746741CONFIG_USB_UHCI_HCD=y747742# CONFIG_USB_SL811_HCD is not set748743···760751#761752CONFIG_USB_STORAGE=m762753# CONFIG_USB_STORAGE_DEBUG is not set763763-# CONFIG_USB_STORAGE_RW_DETECT is not set764754# CONFIG_USB_STORAGE_DATAFAB is not set765755# CONFIG_USB_STORAGE_FREECOM is not set766756# CONFIG_USB_STORAGE_ISD200 is not set767757# CONFIG_USB_STORAGE_DPCM is not set768768-# CONFIG_USB_STORAGE_HP8200e is not set758758+# CONFIG_USB_STORAGE_USBAT is not set769759# CONFIG_USB_STORAGE_SDDR09 is not set770760# CONFIG_USB_STORAGE_SDDR55 is not set771761# CONFIG_USB_STORAGE_JUMPSHOT is not set···808800# CONFIG_USB_PEGASUS is not set809801# CONFIG_USB_RTL8150 is not set810802# CONFIG_USB_USBNET is not set803803+# CONFIG_USB_MON is not set811804812805#813806# USB port drivers···833824# CONFIG_USB_PHIDGETKIT is not set834825# CONFIG_USB_PHIDGETSERVO is not set835826# CONFIG_USB_IDMOUSE is not set827827+# CONFIG_USB_SISUSBVGA is not set836828# CONFIG_USB_TEST is not set837829838830#···877867CONFIG_REISERFS_FS_SECURITY=y878868# CONFIG_JFS_FS is not set879869CONFIG_FS_POSIX_ACL=y870870+871871+#872872+# XFS support873873+#880874CONFIG_XFS_FS=y875875+CONFIG_XFS_EXPORT=y881876# CONFIG_XFS_RT is not set882877# CONFIG_XFS_QUOTA is not set883878# CONFIG_XFS_SECURITY is not set···960945CONFIG_NFSD_TCP=y961946CONFIG_LOCKD=m962947CONFIG_LOCKD_V4=y963963-CONFIG_EXPORTFS=m948948+CONFIG_EXPORTFS=y964949CONFIG_SUNRPC=m965950CONFIG_SUNRPC_GSS=m966951CONFIG_RPCSEC_GSS_KRB5=m···10571042#10581043# Kernel hacking10591044#10451045+# CONFIG_PRINTK_TIME is not set10601046CONFIG_DEBUG_KERNEL=y10611047CONFIG_MAGIC_SYSRQ=y10481048+CONFIG_LOG_BUF_SHIFT=2010621049# CONFIG_SCHEDSTATS is not set10631050# CONFIG_DEBUG_SLAB is not set10641051# CONFIG_DEBUG_SPINLOCK is not set···10941077# CONFIG_CRYPTO_SHA256 is not set10951078# CONFIG_CRYPTO_SHA512 is not set10961079# CONFIG_CRYPTO_WP512 is not set10801080+# CONFIG_CRYPTO_TGR192 is not set10971081CONFIG_CRYPTO_DES=m10981082# CONFIG_CRYPTO_BLOWFISH is not set10991083# CONFIG_CRYPTO_TWOFISH is not set
+4-30
arch/ia64/hp/common/sba_iommu.c
···19441944static void __init19451945sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)19461946{19471947- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};19481948- union acpi_object *obj;19491949- acpi_handle phandle;19501947 unsigned int node;19481948+ int pxm;1951194919521950 ioc->node = MAX_NUMNODES;1953195119541954- /*19551955- * Check for a _PXM on this node first. We don't typically see19561956- * one here, so we'll end up getting it from the parent.19571957- */19581958- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) {19591959- if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))19601960- return;19521952+ pxm = acpi_get_pxm(handle);1961195319621962- /* Reset the acpi buffer */19631963- buffer.length = ACPI_ALLOCATE_BUFFER;19641964- buffer.pointer = NULL;19651965-19661966- if (ACPI_FAILURE(acpi_evaluate_object(phandle, "_PXM", NULL,19671967- &buffer)))19681968- return;19691969- }19701970-19711971- if (!buffer.length || !buffer.pointer)19541954+ if (pxm < 0)19721955 return;1973195619741974- obj = buffer.pointer;19751975-19761976- if (obj->type != ACPI_TYPE_INTEGER ||19771977- obj->integer.value >= MAX_PXM_DOMAINS) {19781978- acpi_os_free(buffer.pointer);19791979- return;19801980- }19811981-19821982- node = pxm_to_nid_map[obj->integer.value];19831983- acpi_os_free(buffer.pointer);19571957+ node = pxm_to_nid_map[pxm];1984195819851959 if (node >= MAX_NUMNODES || !node_online(node))19861960 return;
+5-18
arch/ia64/kernel/acpi.c
···779779 union acpi_object *obj;780780 struct acpi_table_iosapic *iosapic;781781 unsigned int gsi_base;782782- int node;782782+ int pxm, node;783783784784 /* Only care about objects w/ a method that returns the MADT */785785 if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))···805805 gsi_base = iosapic->global_irq_base;806806807807 acpi_os_free(buffer.pointer);808808- buffer.length = ACPI_ALLOCATE_BUFFER;809809- buffer.pointer = NULL;810808811809 /*812812- * OK, it's an IOSAPIC MADT entry, look for a _PXM method to tell810810+ * OK, it's an IOSAPIC MADT entry, look for a _PXM value to tell813811 * us which node to associate this with.814812 */815815- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer)))813813+ pxm = acpi_get_pxm(handle);814814+ if (pxm < 0)816815 return AE_OK;817816818818- if (!buffer.length || !buffer.pointer)819819- return AE_OK;820820-821821- obj = buffer.pointer;822822-823823- if (obj->type != ACPI_TYPE_INTEGER ||824824- obj->integer.value >= MAX_PXM_DOMAINS) {825825- acpi_os_free(buffer.pointer);826826- return AE_OK;827827- }828828-829829- node = pxm_to_nid_map[obj->integer.value];830830- acpi_os_free(buffer.pointer);817817+ node = pxm_to_nid_map[pxm];831818832819 if (node >= MAX_NUMNODES || !node_online(node) ||833820 cpus_empty(node_to_cpumask(node)))
+1-1
arch/ia64/kernel/entry.S
···782782 st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit783783 .mem.offset 8,0784784 st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit785785-END(ia64_ret_from_ia32_execve_syscall)785785+END(ia64_ret_from_ia32_execve)786786 // fall through787787#endif /* CONFIG_IA32_SUPPORT */788788GLOBAL_ENTRY(ia64_leave_kernel)
+3-1
arch/ia64/kernel/fsys.S
···611611 movl r2=ia64_ret_from_syscall612612 ;;613613 mov rp=r2 // set the real return addr614614- tbit.z p8,p0=r3,TIF_SYSCALL_TRACE614614+ and r3=_TIF_SYSCALL_TRACEAUDIT,r3615615 ;;616616+ cmp.eq p8,p0=r3,r0617617+616618(p10) br.cond.spnt.many ia64_ret_from_syscall // p10==true means out registers are more than 8617619(p8) br.call.sptk.many b6=b6 // ignore this return addr618620 br.cond.sptk ia64_trace_syscall
+2-2
arch/ia64/kernel/mca_drv.c
···132132 spin_unlock(&mca_bh_lock);133133134134 /* This process is about to be killed itself */135135- force_sig(SIGKILL, current);136136- schedule();135135+ do_exit(SIGKILL);137136}138137139138/**···438439 psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr;439440 psr2->cpl = 0;440441 psr2->ri = 0;442442+ psr2->i = 0;441443442444 return 1;443445 }
···12651265}12661266EXPORT_SYMBOL(pfm_unregister_buffer_fmt);1267126712681268+extern void update_pal_halt_status(int);12691269+12681270static int12691271pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)12701272{···13121310 pfm_sessions.pfs_sys_use_dbregs,13131311 is_syswide,13141312 cpu));13131313+13141314+ /*13151315+ * disable default_idle() to go to PAL_HALT13161316+ */13171317+ update_pal_halt_status(0);1315131813161319 UNLOCK_PFS(flags);13171320···13721365 pfm_sessions.pfs_sys_use_dbregs,13731366 is_syswide,13741367 cpu));13681368+13691369+ /*13701370+ * if possible, enable default_idle() to go into PAL_HALT13711371+ */13721372+ if (pfm_sessions.pfs_task_sessions == 0 && pfm_sessions.pfs_sys_sessions == 0)13731373+ update_pal_halt_status(1);1375137413761375 UNLOCK_PFS(flags);13771376···42154202 DPRINT(("cannot load to [%d], invalid ctx_state=%d\n",42164203 req->load_pid,42174204 ctx->ctx_state));42184218- return -EINVAL;42054205+ return -EBUSY;42194206 }4220420742214208 DPRINT(("load_pid [%d] using_dbreg=%d\n", req->load_pid, ctx->ctx_fl_using_dbreg));···47174704 if (task == current || ctx->ctx_fl_system) return 0;4718470547194706 /*47204720- * if context is UNLOADED we are safe to go47074707+ * we are monitoring another thread47214708 */47224722- if (state == PFM_CTX_UNLOADED) return 0;47234723-47244724- /*47254725- * no command can operate on a zombie context47264726- */47274727- if (state == PFM_CTX_ZOMBIE) {47284728- DPRINT(("cmd %d state zombie cannot operate on context\n", cmd));47294729- return -EINVAL;47094709+ switch(state) {47104710+ case PFM_CTX_UNLOADED:47114711+ /*47124712+ * if context is UNLOADED we are safe to go47134713+ */47144714+ return 0;47154715+ case PFM_CTX_ZOMBIE:47164716+ /*47174717+ * no command can operate on a zombie context47184718+ */47194719+ DPRINT(("cmd %d state zombie cannot operate on context\n", cmd));47204720+ return -EINVAL;47214721+ case PFM_CTX_MASKED:47224722+ /*47234723+ * PMU state has been saved to software even though47244724+ * the thread may still be running.47254725+ */47264726+ if (cmd != PFM_UNLOAD_CONTEXT) return 0;47304727 }4731472847324729 /*
+36-19
arch/ia64/kernel/process.c
···5050#include "sigframe.h"51515252void (*ia64_mark_idle)(int);5353-static cpumask_t cpu_idle_map;5353+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);54545555unsigned long boot_option_idle_override = 0;5656EXPORT_SYMBOL(boot_option_idle_override);···173173 ia64_do_signal(oldset, scr, in_syscall);174174}175175176176-static int pal_halt = 1;176176+static int pal_halt = 1;177177+static int can_do_pal_halt = 1;178178+177179static int __init nohalt_setup(char * str)178180{179181 pal_halt = 0;···183181}184182__setup("nohalt", nohalt_setup);185183184184+void185185+update_pal_halt_status(int status)186186+{187187+ can_do_pal_halt = pal_halt && status;188188+}189189+186190/*187191 * We use this if we don't have any better idle routine..188192 */189193void190194default_idle (void)191195{192192- unsigned long pmu_active = ia64_getreg(_IA64_REG_PSR) & (IA64_PSR_PP | IA64_PSR_UP);193193-194196 while (!need_resched())195195- if (pal_halt && !pmu_active)197197+ if (can_do_pal_halt)196198 safe_halt();197199 else198200 cpu_relax();···229223}230224#endif /* CONFIG_HOTPLUG_CPU */231225232232-233226void cpu_idle_wait(void)234227{235235- int cpu;236236- cpumask_t map;228228+ unsigned int cpu, this_cpu = get_cpu();229229+ cpumask_t map;237230238238- for_each_online_cpu(cpu)239239- cpu_set(cpu, cpu_idle_map);231231+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));232232+ put_cpu();240233241241- wmb();242242- do {243243- ssleep(1);244244- cpus_and(map, cpu_idle_map, cpu_online_map);245245- } while (!cpus_empty(map));234234+ cpus_clear(map);235235+ for_each_online_cpu(cpu) {236236+ per_cpu(cpu_idle_state, cpu) = 1;237237+ cpu_set(cpu, map);238238+ }239239+240240+ __get_cpu_var(cpu_idle_state) = 0;241241+242242+ wmb();243243+ do {244244+ ssleep(1);245245+ for_each_online_cpu(cpu) {246246+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))247247+ cpu_clear(cpu, map);248248+ }249249+ cpus_and(map, map, cpu_online_map);250250+ } while (!cpus_empty(map));246251}247252EXPORT_SYMBOL_GPL(cpu_idle_wait);248253···261244cpu_idle (void)262245{263246 void (*mark_idle)(int) = ia64_mark_idle;264264- int cpu = smp_processor_id();265247266248 /* endless idle loop with no priority at all */267249 while (1) {···271255 while (!need_resched()) {272256 void (*idle)(void);273257258258+ if (__get_cpu_var(cpu_idle_state))259259+ __get_cpu_var(cpu_idle_state) = 0;260260+261261+ rmb();274262 if (mark_idle)275263 (*mark_idle)(1);276264277277- if (cpu_isset(cpu, cpu_idle_map))278278- cpu_clear(cpu, cpu_idle_map);279279- rmb();280265 idle = pm_idle;281266 if (!idle)282267 idle = default_idle;
+2-1
arch/ia64/kernel/signal.c
···224224 * could be corrupted.225225 */226226 retval = (long) &ia64_leave_kernel;227227- if (test_thread_flag(TIF_SYSCALL_TRACE))227227+ if (test_thread_flag(TIF_SYSCALL_TRACE)228228+ || test_thread_flag(TIF_SYSCALL_AUDIT))228229 /*229230 * strace expects to be notified after sigreturn returns even though the230231 * context to which we return may not be in the middle of a syscall.
···7575 mov f6=f07676 br.cond.sptk .common_code7777 ;;7878+END(memcpy)7879GLOBAL_ENTRY(__copy_user)7980 .prologue8081// check dest alignment···525524#undef B526525#undef C527526#undef D528528-END(memcpy)529527530528/*531529 * Due to lack of local tag support in gcc 2.x assembler, it is not clear which
+1-1
arch/ia64/lib/memset.S
···5757{ .mmi5858 .prologue5959 alloc tmp = ar.pfs, 3, 0, 0, 06060- .body6160 lfetch.nt1 [dest] //6261 .save ar.lc, save_lc6362 mov.i save_lc = ar.lc6363+ .body6464} { .mmi6565 mov ret0 = dest // return value6666 cmp.ne p_nz, p_zr = value, r0 // use stf.spill if value is zero
+6-1
arch/ia64/sn/kernel/Makefile
···44# License. See the file "COPYING" in the main directory of this archive55# for more details.66#77-# Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved.77+# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved.88#991010obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \1111 huberror.o io_init.o iomv.o klconflib.o sn2/1212obj-$(CONFIG_IA64_GENERIC) += machvec.o1313obj-$(CONFIG_SGI_TIOCX) += tiocx.o1414+obj-$(CONFIG_IA64_SGI_SN_XP) += xp.o1515+xp-y := xp_main.o xp_nofault.o1616+obj-$(CONFIG_IA64_SGI_SN_XP) += xpc.o1717+xpc-y := xpc_main.o xpc_channel.o xpc_partition.o1818+obj-$(CONFIG_IA64_SGI_SN_XP) += xpnet.o
+6-4
arch/ia64/sn/kernel/io_init.c
···174174 if (status)175175 continue;176176177177+ /* Attach the error interrupt handlers */178178+ if (nasid & 1)179179+ ice_error_init(hubdev);180180+ else181181+ hub_error_init(hubdev);182182+177183 for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)178184 hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;179185···217211 sn_flush_device_list;218212 }219213220220- if (!(i & 1))221221- hub_error_init(hubdev);222222- else223223- ice_error_init(hubdev);224214 }225215226216}
+21-13
arch/ia64/sn/kernel/mca.c
···3737 * This function is the callback routine that SAL calls to log error3838 * info for platform errors. buf is appended to sn_oemdata, resizing as3939 * required.4040+ * Note: this is a SAL to OS callback, running under the same rules as the SAL4141+ * code. SAL calls are run with preempt disabled so this routine must not4242+ * sleep. vmalloc can sleep so print_hook cannot resize the output buffer4343+ * itself, instead it must set the required size and return to let the caller4444+ * resize the buffer then redrive the SAL call.4045 */4146static int print_hook(const char *fmt, ...)4247{···5247 vsnprintf(buf, sizeof(buf), fmt, args);5348 va_end(args);5449 len = strlen(buf);5555- while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) {5656- u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000);5757- if (!newbuf) {5858- printk(KERN_ERR "%s: unable to extend sn_oemdata\n",5959- __FUNCTION__);6060- return 0;6161- }6262- memcpy(newbuf, *sn_oemdata, *sn_oemdata_size);6363- vfree(*sn_oemdata);6464- *sn_oemdata = newbuf;6565- }6666- memcpy(*sn_oemdata + *sn_oemdata_size, buf, len + 1);5050+ if (*sn_oemdata_size + len <= sn_oemdata_bufsize)5151+ memcpy(*sn_oemdata + *sn_oemdata_size, buf, len);6752 *sn_oemdata_size += len;6853 return 0;6954}···9398 sn_oemdata = oemdata;9499 sn_oemdata_size = oemdata_size;95100 sn_oemdata_bufsize = 0;9696- ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);101101+ *sn_oemdata_size = PAGE_SIZE; /* first guess at how much data will be generated */102102+ while (*sn_oemdata_size > sn_oemdata_bufsize) {103103+ u8 *newbuf = vmalloc(*sn_oemdata_size);104104+ if (!newbuf) {105105+ printk(KERN_ERR "%s: unable to extend sn_oemdata\n",106106+ __FUNCTION__);107107+ return 1;108108+ }109109+ vfree(*sn_oemdata);110110+ *sn_oemdata = newbuf;111111+ sn_oemdata_bufsize = *sn_oemdata_size;112112+ *sn_oemdata_size = 0;113113+ ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);114114+ }97115 up(&sn_oemdata_mutex);98116 return 0;99117}
+24-16
arch/ia64/sn/kernel/setup.c
···33 * License. See the file "COPYING" in the main directory of this archive44 * for more details.55 *66- * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All rights reserved.66+ * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.77 */8899#include <linux/config.h>···72727373DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);7474EXPORT_PER_CPU_SYMBOL(__sn_hub_info);7575+7676+DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]);7777+EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid);7878+7979+DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda);8080+EXPORT_PER_CPU_SYMBOL(__sn_nodepda);75817682partid_t sn_partid = -1;7783EXPORT_SYMBOL(sn_partid);···379373{380374 cnodeid_t cnode;381375382382- memset(pda->cnodeid_to_nasid_table, -1,383383- sizeof(pda->cnodeid_to_nasid_table));376376+ memset(sn_cnodeid_to_nasid, -1,377377+ sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));384378 for_each_online_node(cnode)385385- pda->cnodeid_to_nasid_table[cnode] =386386- pxm_to_nasid(nid_to_pxm_map[cnode]);379379+ sn_cnodeid_to_nasid[cnode] =380380+ pxm_to_nasid(nid_to_pxm_map[cnode]);387381388382 numionodes = num_online_nodes();389383 scan_for_ionodes();···483477484478 cnode = nasid_to_cnodeid(nasid);485479486486- pda->p_nodepda = nodepdaindr[cnode];480480+ sn_nodepda = nodepdaindr[cnode];481481+487482 pda->led_address =488483 (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));489484 pda->led_state = LED_ALWAYS_SET;···493486 pda->idle_flag = 0;494487495488 if (cpuid != 0) {496496- memcpy(pda->cnodeid_to_nasid_table,497497- pdacpu(0)->cnodeid_to_nasid_table,498498- sizeof(pda->cnodeid_to_nasid_table));489489+ /* copy cpu 0's sn_cnodeid_to_nasid table to this cpu's */490490+ memcpy(sn_cnodeid_to_nasid,491491+ (&per_cpu(__sn_cnodeid_to_nasid, 0)),492492+ sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));499493 }500494501495 /*502496 * Check for WARs.503497 * Only needs to be done once, on BSP.504504- * Has to be done after loop above, because it uses pda.cnodeid_to_nasid_table[i].498498+ * Has to be done after loop above, because it uses this cpu's499499+ * sn_cnodeid_to_nasid table which was just initialized if this500500+ * isn't cpu 0.505501 * Has to be done before assignment below.506502 */507503 if (!wars_have_been_checked) {···590580 brd = find_lboard_any(brd, KLTYPE_SNIA);591581592582 while (brd) {593593- pda->cnodeid_to_nasid_table[numionodes] =594594- brd->brd_nasid;583583+ sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;595584 physical_node_map[brd->brd_nasid] = numionodes;596585 root_lboard[numionodes] = brd;597586 numionodes++;···611602 root_lboard[nasid_to_cnodeid(nasid)],612603 KLTYPE_TIO);613604 while (brd) {614614- pda->cnodeid_to_nasid_table[numionodes] =615615- brd->brd_nasid;605605+ sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;616606 physical_node_map[brd->brd_nasid] = numionodes;617607 root_lboard[numionodes] = brd;618608 numionodes++;···622614 brd = find_lboard_any(brd, KLTYPE_TIO);623615 }624616 }625625-626617}627618628619int···630623 long cpu;631624632625 for (cpu=0; cpu < NR_CPUS; cpu++) 633633- if (nodepda->phys_cpuid[cpu].nasid == nasid && nodepda->phys_cpuid[cpu].slice == slice)626626+ if (cpuid_to_nasid(cpu) == nasid &&627627+ cpuid_to_slice(cpu) == slice)634628 return cpu;635629636630 return -1;
+32-28
arch/ia64/sn/kernel/tiocx.c
···2121#include <asm/sn/types.h>2222#include <asm/sn/shubio.h>2323#include <asm/sn/tiocx.h>2424+#include <asm/sn/l1.h>2525+#include <asm/sn/module.h>2426#include "tio.h"2527#include "xtalk/xwidgetdev.h"2628#include "xtalk/hubdev.h"···310308 }311309}312310313313-uint64_t314314-tiocx_dma_addr(uint64_t addr)311311+uint64_t tiocx_dma_addr(uint64_t addr)315312{316313 return PHYS_TO_TIODMA(addr);317314}318315319319-uint64_t320320-tiocx_swin_base(int nasid)316316+uint64_t tiocx_swin_base(int nasid)321317{322318 return TIO_SWIN_BASE(nasid, TIOCX_CORELET);323319}···329329EXPORT_SYMBOL(tiocx_bus_type);330330EXPORT_SYMBOL(tiocx_dma_addr);331331EXPORT_SYMBOL(tiocx_swin_base);332332-333333-static uint64_t tiocx_get_hubdev_info(u64 handle, u64 address)334334-{335335-336336- struct ia64_sal_retval ret_stuff;337337- ret_stuff.status = 0;338338- ret_stuff.v0 = 0;339339-340340- ia64_sal_oemcall_nolock(&ret_stuff,341341- SN_SAL_IOIF_GET_HUBDEV_INFO,342342- handle, address, 0, 0, 0, 0, 0);343343- return ret_stuff.v0;344344-}345332346333static void tio_conveyor_set(nasid_t nasid, int enable_flag)347334{···366379 udelay(2000);367380}368381369369-static int fpga_attached(nasid_t nasid)382382+static int tiocx_btchar_get(int nasid)383383+{384384+ moduleid_t module_id;385385+ geoid_t geoid;386386+ int cnodeid;387387+388388+ cnodeid = nasid_to_cnodeid(nasid);389389+ geoid = cnodeid_get_geoid(cnodeid);390390+ module_id = geo_module(geoid);391391+ return MODULE_GET_BTCHAR(module_id);392392+}393393+394394+static int is_fpga_brick(int nasid)395395+{396396+ switch (tiocx_btchar_get(nasid)) {397397+ case L1_BRICKTYPE_SA:398398+ case L1_BRICKTYPE_ATHENA:399399+ return 1;400400+ }401401+ return 0;402402+}403403+404404+static int bitstream_loaded(nasid_t nasid)370405{371406 uint64_t cx_credits;372407···405396 int mfg_num = CX_DEV_NONE;406397 nasid_t nasid = cx_dev->cx_id.nasid;407398408408- if (fpga_attached(nasid)) {399399+ if (bitstream_loaded(nasid)) {409400 uint64_t cx_id;410401411402 cx_id =···436427{437428 struct cx_dev *cx_dev = to_cx_dev(dev);438429439439- return sprintf(buf, "0x%x 0x%x 0x%x\n",430430+ return sprintf(buf, "0x%x 0x%x 0x%x %d\n",440431 cx_dev->cx_id.nasid,441441- cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num);432432+ cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,433433+ tiocx_btchar_get(cx_dev->cx_id.nasid));442434}443435444436static ssize_t store_cxdev_control(struct device *dev, const char *buf,···485475 if ((nasid = cnodeid_to_nasid(cnodeid)) < 0)486476 break; /* No more nasids .. bail out of loop */487477488488- if (nasid & 0x1) { /* TIO's are always odd */478478+ if ((nasid & 0x1) && is_fpga_brick(nasid)) {489479 struct hubdev_info *hubdev;490490- uint64_t status;491480 struct xwidget_info *widgetp;492481493482 DBG("Found TIO at nasid 0x%x\n", nasid);494483495484 hubdev =496485 (struct hubdev_info *)(NODEPDA(cnodeid)->pdinfo);497497- status =498498- tiocx_get_hubdev_info(nasid,499499- (uint64_t) __pa(hubdev));500500- if (status)501501- continue;502486503487 widgetp = &hubdev->hdi_xwidget_info[TIOCX_CORELET];504488
+289
arch/ia64/sn/kernel/xp_main.c
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.77+ */88+99+1010+/*1111+ * Cross Partition (XP) base.1212+ *1313+ * XP provides a base from which its users can interact1414+ * with XPC, yet not be dependent on XPC.1515+ *1616+ */1717+1818+1919+#include <linux/kernel.h>2020+#include <linux/interrupt.h>2121+#include <linux/module.h>2222+#include <asm/sn/intr.h>2323+#include <asm/sn/sn_sal.h>2424+#include <asm/sn/xp.h>2525+2626+2727+/*2828+ * Target of nofault PIO read.2929+ */3030+u64 xp_nofault_PIOR_target;3131+3232+3333+/*3434+ * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level3535+ * users of XPC.3636+ */3737+struct xpc_registration xpc_registrations[XPC_NCHANNELS];3838+3939+4040+/*4141+ * Initialize the XPC interface to indicate that XPC isn't loaded.4242+ */4343+static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }4444+4545+struct xpc_interface xpc_interface = {4646+ (void (*)(int)) xpc_notloaded,4747+ (void (*)(int)) xpc_notloaded,4848+ (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,4949+ (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,5050+ (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))5151+ xpc_notloaded,5252+ (void (*)(partid_t, int, void *)) xpc_notloaded,5353+ (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded5454+};5555+5656+5757+/*5858+ * XPC calls this when it (the XPC module) has been loaded.5959+ */6060+void6161+xpc_set_interface(void (*connect)(int),6262+ void (*disconnect)(int),6363+ enum xpc_retval (*allocate)(partid_t, int, u32, void **),6464+ enum xpc_retval (*send)(partid_t, int, void *),6565+ enum xpc_retval (*send_notify)(partid_t, int, void *,6666+ xpc_notify_func, void *),6767+ void (*received)(partid_t, int, void *),6868+ enum xpc_retval (*partid_to_nasids)(partid_t, void *))6969+{7070+ xpc_interface.connect = connect;7171+ xpc_interface.disconnect = disconnect;7272+ xpc_interface.allocate = allocate;7373+ xpc_interface.send = send;7474+ xpc_interface.send_notify = send_notify;7575+ xpc_interface.received = received;7676+ xpc_interface.partid_to_nasids = partid_to_nasids;7777+}7878+7979+8080+/*8181+ * XPC calls this when it (the XPC module) is being unloaded.8282+ */8383+void8484+xpc_clear_interface(void)8585+{8686+ xpc_interface.connect = (void (*)(int)) xpc_notloaded;8787+ xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;8888+ xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,8989+ void **)) xpc_notloaded;9090+ xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))9191+ xpc_notloaded;9292+ xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,9393+ xpc_notify_func, void *)) xpc_notloaded;9494+ xpc_interface.received = (void (*)(partid_t, int, void *))9595+ xpc_notloaded;9696+ xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))9797+ xpc_notloaded;9898+}9999+100100+101101+/*102102+ * Register for automatic establishment of a channel connection whenever103103+ * a partition comes up.104104+ *105105+ * Arguments:106106+ *107107+ * ch_number - channel # to register for connection.108108+ * func - function to call for asynchronous notification of channel109109+ * state changes (i.e., connection, disconnection, error) and110110+ * the arrival of incoming messages.111111+ * key - pointer to optional user-defined value that gets passed back112112+ * to the user on any callouts made to func.113113+ * payload_size - size in bytes of the XPC message's payload area which114114+ * contains a user-defined message. The user should make115115+ * this large enough to hold their largest message.116116+ * nentries - max #of XPC message entries a message queue can contain.117117+ * The actual number, which is determined when a connection118118+ * is established and may be less then requested, will be119119+ * passed to the user via the xpcConnected callout.120120+ * assigned_limit - max number of kthreads allowed to be processing121121+ * messages (per connection) at any given instant.122122+ * idle_limit - max number of kthreads allowed to be idle at any given123123+ * instant.124124+ */125125+enum xpc_retval126126+xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,127127+ u16 nentries, u32 assigned_limit, u32 idle_limit)128128+{129129+ struct xpc_registration *registration;130130+131131+132132+ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);133133+ DBUG_ON(payload_size == 0 || nentries == 0);134134+ DBUG_ON(func == NULL);135135+ DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);136136+137137+ registration = &xpc_registrations[ch_number];138138+139139+ if (down_interruptible(®istration->sema) != 0) {140140+ return xpcInterrupted;141141+ }142142+143143+ /* if XPC_CHANNEL_REGISTERED(ch_number) */144144+ if (registration->func != NULL) {145145+ up(®istration->sema);146146+ return xpcAlreadyRegistered;147147+ }148148+149149+ /* register the channel for connection */150150+ registration->msg_size = XPC_MSG_SIZE(payload_size);151151+ registration->nentries = nentries;152152+ registration->assigned_limit = assigned_limit;153153+ registration->idle_limit = idle_limit;154154+ registration->key = key;155155+ registration->func = func;156156+157157+ up(®istration->sema);158158+159159+ xpc_interface.connect(ch_number);160160+161161+ return xpcSuccess;162162+}163163+164164+165165+/*166166+ * Remove the registration for automatic connection of the specified channel167167+ * when a partition comes up.168168+ *169169+ * Before returning this xpc_disconnect() will wait for all connections on the170170+ * specified channel have been closed/torndown. So the caller can be assured171171+ * that they will not be receiving any more callouts from XPC to their172172+ * function registered via xpc_connect().173173+ *174174+ * Arguments:175175+ *176176+ * ch_number - channel # to unregister.177177+ */178178+void179179+xpc_disconnect(int ch_number)180180+{181181+ struct xpc_registration *registration;182182+183183+184184+ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);185185+186186+ registration = &xpc_registrations[ch_number];187187+188188+ /*189189+ * We've decided not to make this a down_interruptible(), since we190190+ * figured XPC's users will just turn around and call xpc_disconnect()191191+ * again anyways, so we might as well wait, if need be.192192+ */193193+ down(®istration->sema);194194+195195+ /* if !XPC_CHANNEL_REGISTERED(ch_number) */196196+ if (registration->func == NULL) {197197+ up(®istration->sema);198198+ return;199199+ }200200+201201+ /* remove the connection registration for the specified channel */202202+ registration->func = NULL;203203+ registration->key = NULL;204204+ registration->nentries = 0;205205+ registration->msg_size = 0;206206+ registration->assigned_limit = 0;207207+ registration->idle_limit = 0;208208+209209+ xpc_interface.disconnect(ch_number);210210+211211+ up(®istration->sema);212212+213213+ return;214214+}215215+216216+217217+int __init218218+xp_init(void)219219+{220220+ int ret, ch_number;221221+ u64 func_addr = *(u64 *) xp_nofault_PIOR;222222+ u64 err_func_addr = *(u64 *) xp_error_PIOR;223223+224224+225225+ if (!ia64_platform_is("sn2")) {226226+ return -ENODEV;227227+ }228228+229229+ /*230230+ * Register a nofault code region which performs a cross-partition231231+ * PIO read. If the PIO read times out, the MCA handler will consume232232+ * the error and return to a kernel-provided instruction to indicate233233+ * an error. This PIO read exists because it is guaranteed to timeout234234+ * if the destination is down (AMO operations do not timeout on at235235+ * least some CPUs on Shubs <= v1.2, which unfortunately we have to236236+ * work around).237237+ */238238+ if ((ret = sn_register_nofault_code(func_addr, err_func_addr,239239+ err_func_addr, 1, 1)) != 0) {240240+ printk(KERN_ERR "XP: can't register nofault code, error=%d\n",241241+ ret);242242+ }243243+ /*244244+ * Setup the nofault PIO read target. (There is no special reason why245245+ * SH_IPI_ACCESS was selected.)246246+ */247247+ if (is_shub2()) {248248+ xp_nofault_PIOR_target = SH2_IPI_ACCESS0;249249+ } else {250250+ xp_nofault_PIOR_target = SH1_IPI_ACCESS;251251+ }252252+253253+ /* initialize the connection registration semaphores */254254+ for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {255255+ sema_init(&xpc_registrations[ch_number].sema, 1); /* mutex */256256+ }257257+258258+ return 0;259259+}260260+module_init(xp_init);261261+262262+263263+void __exit264264+xp_exit(void)265265+{266266+ u64 func_addr = *(u64 *) xp_nofault_PIOR;267267+ u64 err_func_addr = *(u64 *) xp_error_PIOR;268268+269269+270270+ /* unregister the PIO read nofault code region */271271+ (void) sn_register_nofault_code(func_addr, err_func_addr,272272+ err_func_addr, 1, 0);273273+}274274+module_exit(xp_exit);275275+276276+277277+MODULE_AUTHOR("Silicon Graphics, Inc.");278278+MODULE_DESCRIPTION("Cross Partition (XP) base");279279+MODULE_LICENSE("GPL");280280+281281+EXPORT_SYMBOL(xp_nofault_PIOR);282282+EXPORT_SYMBOL(xp_nofault_PIOR_target);283283+EXPORT_SYMBOL(xpc_registrations);284284+EXPORT_SYMBOL(xpc_interface);285285+EXPORT_SYMBOL(xpc_clear_interface);286286+EXPORT_SYMBOL(xpc_set_interface);287287+EXPORT_SYMBOL(xpc_connect);288288+EXPORT_SYMBOL(xpc_disconnect);289289+
+31
arch/ia64/sn/kernel/xp_nofault.S
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.77+ */88+99+1010+/*1111+ * The xp_nofault_PIOR function takes a pointer to a remote PIO register1212+ * and attempts to load and consume a value from it. This function1313+ * will be registered as a nofault code block. In the event that the1414+ * PIO read fails, the MCA handler will force the error to look1515+ * corrected and vector to the xp_error_PIOR which will return an error.1616+ *1717+ * extern int xp_nofault_PIOR(void *remote_register);1818+ */1919+2020+ .global xp_nofault_PIOR2121+xp_nofault_PIOR:2222+ mov r8=r0 // Stage a success return value2323+ ld8.acq r9=[r32];; // PIO Read the specified register2424+ adds r9=1,r9 // Add to force a consume2525+ br.ret.sptk.many b0;; // Return success2626+2727+ .global xp_error_PIOR2828+xp_error_PIOR:2929+ mov r8=1 // Return value of 13030+ br.ret.sptk.many b0;; // Return failure3131+
+991
arch/ia64/sn/kernel/xpc.h
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.77+ */88+99+1010+/*1111+ * Cross Partition Communication (XPC) structures and macros.1212+ */1313+1414+#ifndef _IA64_SN_KERNEL_XPC_H1515+#define _IA64_SN_KERNEL_XPC_H1616+1717+1818+#include <linux/config.h>1919+#include <linux/interrupt.h>2020+#include <linux/sysctl.h>2121+#include <linux/device.h>2222+#include <asm/pgtable.h>2323+#include <asm/processor.h>2424+#include <asm/sn/bte.h>2525+#include <asm/sn/clksupport.h>2626+#include <asm/sn/addrs.h>2727+#include <asm/sn/mspec.h>2828+#include <asm/sn/shub_mmr.h>2929+#include <asm/sn/xp.h>3030+3131+3232+/*3333+ * XPC Version numbers consist of a major and minor number. XPC can always3434+ * talk to versions with same major #, and never talk to versions with a3535+ * different major #.3636+ */3737+#define _XPC_VERSION(_maj, _min) (((_maj) << 4) | ((_min) & 0xf))3838+#define XPC_VERSION_MAJOR(_v) ((_v) >> 4)3939+#define XPC_VERSION_MINOR(_v) ((_v) & 0xf)4040+4141+4242+/*4343+ * The next macros define word or bit representations for given4444+ * C-brick nasid in either the SAL provided bit array representing4545+ * nasids in the partition/machine or the AMO_t array used for4646+ * inter-partition initiation communications.4747+ *4848+ * For SN2 machines, C-Bricks are alway even numbered NASIDs. As4949+ * such, some space will be saved by insisting that nasid information5050+ * passed from SAL always be packed for C-Bricks and the5151+ * cross-partition interrupts use the same packing scheme.5252+ */5353+#define XPC_NASID_W_INDEX(_n) (((_n) / 64) / 2)5454+#define XPC_NASID_B_INDEX(_n) (((_n) / 2) & (64 - 1))5555+#define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \5656+ (1UL << XPC_NASID_B_INDEX(_n)))5757+#define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)5858+5959+#define XPC_HB_DEFAULT_INTERVAL 5 /* incr HB every x secs */6060+#define XPC_HB_CHECK_DEFAULT_TIMEOUT 20 /* check HB every x secs */6161+6262+/* define the process name of HB checker and the CPU it is pinned to */6363+#define XPC_HB_CHECK_THREAD_NAME "xpc_hb"6464+#define XPC_HB_CHECK_CPU 06565+6666+/* define the process name of the discovery thread */6767+#define XPC_DISCOVERY_THREAD_NAME "xpc_discovery"6868+6969+7070+#define XPC_HB_ALLOWED(_p, _v) ((_v)->heartbeating_to_mask & (1UL << (_p)))7171+#define XPC_ALLOW_HB(_p, _v) (_v)->heartbeating_to_mask |= (1UL << (_p))7272+#define XPC_DISALLOW_HB(_p, _v) (_v)->heartbeating_to_mask &= (~(1UL << (_p)))7373+7474+7575+/*7676+ * Reserved Page provided by SAL.7777+ *7878+ * SAL provides one page per partition of reserved memory. When SAL7979+ * initialization is complete, SAL_signature, SAL_version, partid,8080+ * part_nasids, and mach_nasids are set.8181+ *8282+ * Note: Until vars_pa is set, the partition XPC code has not been initialized.8383+ */8484+struct xpc_rsvd_page {8585+ u64 SAL_signature; /* SAL unique signature */8686+ u64 SAL_version; /* SAL specified version */8787+ u8 partid; /* partition ID from SAL */8888+ u8 version;8989+ u8 pad[6]; /* pad to u64 align */9090+ u64 vars_pa;9191+ u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;9292+ u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;9393+};9494+#define XPC_RP_VERSION _XPC_VERSION(1,0) /* version 1.0 of the reserved page */9595+9696+#define XPC_RSVD_PAGE_ALIGNED_SIZE \9797+ (L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page)))9898+9999+100100+/*101101+ * Define the structures by which XPC variables can be exported to other102102+ * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)103103+ */104104+105105+/*106106+ * The following structure describes the partition generic variables107107+ * needed by other partitions in order to properly initialize.108108+ *109109+ * struct xpc_vars version number also applies to struct xpc_vars_part.110110+ * Changes to either structure and/or related functionality should be111111+ * reflected by incrementing either the major or minor version numbers112112+ * of struct xpc_vars.113113+ */114114+struct xpc_vars {115115+ u8 version;116116+ u64 heartbeat;117117+ u64 heartbeating_to_mask;118118+ u64 kdb_status; /* 0 = machine running */119119+ int act_nasid;120120+ int act_phys_cpuid;121121+ u64 vars_part_pa;122122+ u64 amos_page_pa; /* paddr of page of AMOs from MSPEC driver */123123+ AMO_t *amos_page; /* vaddr of page of AMOs from MSPEC driver */124124+ AMO_t *act_amos; /* pointer to the first activation AMO */125125+};126126+#define XPC_V_VERSION _XPC_VERSION(3,0) /* version 3.0 of the cross vars */127127+128128+#define XPC_VARS_ALIGNED_SIZE (L1_CACHE_ALIGN(sizeof(struct xpc_vars)))129129+130130+/*131131+ * The following structure describes the per partition specific variables.132132+ *133133+ * An array of these structures, one per partition, will be defined. As a134134+ * partition becomes active XPC will copy the array entry corresponding to135135+ * itself from that partition. It is desirable that the size of this136136+ * structure evenly divide into a cacheline, such that none of the entries137137+ * in this array crosses a cacheline boundary. As it is now, each entry138138+ * occupies half a cacheline.139139+ */140140+struct xpc_vars_part {141141+ u64 magic;142142+143143+ u64 openclose_args_pa; /* physical address of open and close args */144144+ u64 GPs_pa; /* physical address of Get/Put values */145145+146146+ u64 IPI_amo_pa; /* physical address of IPI AMO_t structure */147147+ int IPI_nasid; /* nasid of where to send IPIs */148148+ int IPI_phys_cpuid; /* physical CPU ID of where to send IPIs */149149+150150+ u8 nchannels; /* #of defined channels supported */151151+152152+ u8 reserved[23]; /* pad to a full 64 bytes */153153+};154154+155155+/*156156+ * The vars_part MAGIC numbers play a part in the first contact protocol.157157+ *158158+ * MAGIC1 indicates that the per partition specific variables for a remote159159+ * partition have been initialized by this partition.160160+ *161161+ * MAGIC2 indicates that this partition has pulled the remote partititions162162+ * per partition variables that pertain to this partition.163163+ */164164+#define XPC_VP_MAGIC1 0x0053524156435058L /* 'XPCVARS\0'L (little endian) */165165+#define XPC_VP_MAGIC2 0x0073726176435058L /* 'XPCvars\0'L (little endian) */166166+167167+168168+169169+/*170170+ * Functions registered by add_timer() or called by kernel_thread() only171171+ * allow for a single 64-bit argument. The following macros can be used to172172+ * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from173173+ * the passed argument.174174+ */175175+#define XPC_PACK_ARGS(_arg1, _arg2) \176176+ ((((u64) _arg1) & 0xffffffff) | \177177+ ((((u64) _arg2) & 0xffffffff) << 32))178178+179179+#define XPC_UNPACK_ARG1(_args) (((u64) _args) & 0xffffffff)180180+#define XPC_UNPACK_ARG2(_args) ((((u64) _args) >> 32) & 0xffffffff)181181+182182+183183+184184+/*185185+ * Define a Get/Put value pair (pointers) used with a message queue.186186+ */187187+struct xpc_gp {188188+ s64 get; /* Get value */189189+ s64 put; /* Put value */190190+};191191+192192+#define XPC_GP_SIZE \193193+ L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)194194+195195+196196+197197+/*198198+ * Define a structure that contains arguments associated with opening and199199+ * closing a channel.200200+ */201201+struct xpc_openclose_args {202202+ u16 reason; /* reason why channel is closing */203203+ u16 msg_size; /* sizeof each message entry */204204+ u16 remote_nentries; /* #of message entries in remote msg queue */205205+ u16 local_nentries; /* #of message entries in local msg queue */206206+ u64 local_msgqueue_pa; /* physical address of local message queue */207207+};208208+209209+#define XPC_OPENCLOSE_ARGS_SIZE \210210+ L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)211211+212212+213213+214214+/* struct xpc_msg flags */215215+216216+#define XPC_M_DONE 0x01 /* msg has been received/consumed */217217+#define XPC_M_READY 0x02 /* msg is ready to be sent */218218+#define XPC_M_INTERRUPT 0x04 /* send interrupt when msg consumed */219219+220220+221221+#define XPC_MSG_ADDRESS(_payload) \222222+ ((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))223223+224224+225225+226226+/*227227+ * Defines notify entry.228228+ *229229+ * This is used to notify a message's sender that their message was received230230+ * and consumed by the intended recipient.231231+ */232232+struct xpc_notify {233233+ struct semaphore sema; /* notify semaphore */234234+ u8 type; /* type of notification */235235+236236+ /* the following two fields are only used if type == XPC_N_CALL */237237+ xpc_notify_func func; /* user's notify function */238238+ void *key; /* pointer to user's key */239239+};240240+241241+/* struct xpc_notify type of notification */242242+243243+#define XPC_N_CALL 0x01 /* notify function provided by user */244244+245245+246246+247247+/*248248+ * Define the structure that manages all the stuff required by a channel. In249249+ * particular, they are used to manage the messages sent across the channel.250250+ *251251+ * This structure is private to a partition, and is NOT shared across the252252+ * partition boundary.253253+ *254254+ * There is an array of these structures for each remote partition. It is255255+ * allocated at the time a partition becomes active. The array contains one256256+ * of these structures for each potential channel connection to that partition.257257+ *258258+ * Each of these structures manages two message queues (circular buffers).259259+ * They are allocated at the time a channel connection is made. One of260260+ * these message queues (local_msgqueue) holds the locally created messages261261+ * that are destined for the remote partition. The other of these message262262+ * queues (remote_msgqueue) is a locally cached copy of the remote partition's263263+ * own local_msgqueue.264264+ *265265+ * The following is a description of the Get/Put pointers used to manage these266266+ * two message queues. Consider the local_msgqueue to be on one partition267267+ * and the remote_msgqueue to be its cached copy on another partition. A268268+ * description of what each of the lettered areas contains is included.269269+ *270270+ *271271+ * local_msgqueue remote_msgqueue272272+ *273273+ * |/////////| |/////////|274274+ * w_remote_GP.get --> +---------+ |/////////|275275+ * | F | |/////////|276276+ * remote_GP.get --> +---------+ +---------+ <-- local_GP->get277277+ * | | | |278278+ * | | | E |279279+ * | | | |280280+ * | | +---------+ <-- w_local_GP.get281281+ * | B | |/////////|282282+ * | | |////D////|283283+ * | | |/////////|284284+ * | | +---------+ <-- w_remote_GP.put285285+ * | | |////C////|286286+ * local_GP->put --> +---------+ +---------+ <-- remote_GP.put287287+ * | | |/////////|288288+ * | A | |/////////|289289+ * | | |/////////|290290+ * w_local_GP.put --> +---------+ |/////////|291291+ * |/////////| |/////////|292292+ *293293+ *294294+ * ( remote_GP.[get|put] are cached copies of the remote295295+ * partition's local_GP->[get|put], and thus their values can296296+ * lag behind their counterparts on the remote partition. )297297+ *298298+ *299299+ * A - Messages that have been allocated, but have not yet been sent to the300300+ * remote partition.301301+ *302302+ * B - Messages that have been sent, but have not yet been acknowledged by the303303+ * remote partition as having been received.304304+ *305305+ * C - Area that needs to be prepared for the copying of sent messages, by306306+ * the clearing of the message flags of any previously received messages.307307+ *308308+ * D - Area into which sent messages are to be copied from the remote309309+ * partition's local_msgqueue and then delivered to their intended310310+ * recipients. [ To allow for a multi-message copy, another pointer311311+ * (next_msg_to_pull) has been added to keep track of the next message312312+ * number needing to be copied (pulled). It chases after w_remote_GP.put.313313+ * Any messages lying between w_local_GP.get and next_msg_to_pull have314314+ * been copied and are ready to be delivered. ]315315+ *316316+ * E - Messages that have been copied and delivered, but have not yet been317317+ * acknowledged by the recipient as having been received.318318+ *319319+ * F - Messages that have been acknowledged, but XPC has not yet notified the320320+ * sender that the message was received by its intended recipient.321321+ * This is also an area that needs to be prepared for the allocating of322322+ * new messages, by the clearing of the message flags of the acknowledged323323+ * messages.324324+ */325325+struct xpc_channel {326326+ partid_t partid; /* ID of remote partition connected */327327+ spinlock_t lock; /* lock for updating this structure */328328+ u32 flags; /* general flags */329329+330330+ enum xpc_retval reason; /* reason why channel is disconnect'g */331331+ int reason_line; /* line# disconnect initiated from */332332+333333+ u16 number; /* channel # */334334+335335+ u16 msg_size; /* sizeof each msg entry */336336+ u16 local_nentries; /* #of msg entries in local msg queue */337337+ u16 remote_nentries; /* #of msg entries in remote msg queue*/338338+339339+ void *local_msgqueue_base; /* base address of kmalloc'd space */340340+ struct xpc_msg *local_msgqueue; /* local message queue */341341+ void *remote_msgqueue_base; /* base address of kmalloc'd space */342342+ struct xpc_msg *remote_msgqueue;/* cached copy of remote partition's */343343+ /* local message queue */344344+ u64 remote_msgqueue_pa; /* phys addr of remote partition's */345345+ /* local message queue */346346+347347+ atomic_t references; /* #of external references to queues */348348+349349+ atomic_t n_on_msg_allocate_wq; /* #on msg allocation wait queue */350350+ wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */351351+352352+ /* queue of msg senders who want to be notified when msg received */353353+354354+ atomic_t n_to_notify; /* #of msg senders to notify */355355+ struct xpc_notify *notify_queue;/* notify queue for messages sent */356356+357357+ xpc_channel_func func; /* user's channel function */358358+ void *key; /* pointer to user's key */359359+360360+ struct semaphore msg_to_pull_sema; /* next msg to pull serialization */361361+ struct semaphore teardown_sema; /* wait for teardown completion */362362+363363+ struct xpc_openclose_args *local_openclose_args; /* args passed on */364364+ /* opening or closing of channel */365365+366366+ /* various flavors of local and remote Get/Put values */367367+368368+ struct xpc_gp *local_GP; /* local Get/Put values */369369+ struct xpc_gp remote_GP; /* remote Get/Put values */370370+ struct xpc_gp w_local_GP; /* working local Get/Put values */371371+ struct xpc_gp w_remote_GP; /* working remote Get/Put values */372372+ s64 next_msg_to_pull; /* Put value of next msg to pull */373373+374374+ /* kthread management related fields */375375+376376+// >>> rethink having kthreads_assigned_limit and kthreads_idle_limit; perhaps377377+// >>> allow the assigned limit be unbounded and let the idle limit be dynamic378378+// >>> dependent on activity over the last interval of time379379+ atomic_t kthreads_assigned; /* #of kthreads assigned to channel */380380+ u32 kthreads_assigned_limit; /* limit on #of kthreads assigned */381381+ atomic_t kthreads_idle; /* #of kthreads idle waiting for work */382382+ u32 kthreads_idle_limit; /* limit on #of kthreads idle */383383+ atomic_t kthreads_active; /* #of kthreads actively working */384384+ // >>> following field is temporary385385+ u32 kthreads_created; /* total #of kthreads created */386386+387387+ wait_queue_head_t idle_wq; /* idle kthread wait queue */388388+389389+} ____cacheline_aligned;390390+391391+392392+/* struct xpc_channel flags */393393+394394+#define XPC_C_WASCONNECTED 0x00000001 /* channel was connected */395395+396396+#define XPC_C_ROPENREPLY 0x00000002 /* remote open channel reply */397397+#define XPC_C_OPENREPLY 0x00000004 /* local open channel reply */398398+#define XPC_C_ROPENREQUEST 0x00000008 /* remote open channel request */399399+#define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */400400+401401+#define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */402402+#define XPC_C_CONNECTCALLOUT 0x00000040 /* channel connected callout made */403403+#define XPC_C_CONNECTED 0x00000080 /* local channel is connected */404404+#define XPC_C_CONNECTING 0x00000100 /* channel is being connected */405405+406406+#define XPC_C_RCLOSEREPLY 0x00000200 /* remote close channel reply */407407+#define XPC_C_CLOSEREPLY 0x00000400 /* local close channel reply */408408+#define XPC_C_RCLOSEREQUEST 0x00000800 /* remote close channel request */409409+#define XPC_C_CLOSEREQUEST 0x00001000 /* local close channel request */410410+411411+#define XPC_C_DISCONNECTED 0x00002000 /* channel is disconnected */412412+#define XPC_C_DISCONNECTING 0x00004000 /* channel is being disconnected */413413+414414+415415+416416+/*417417+ * Manages channels on a partition basis. There is one of these structures418418+ * for each partition (a partition will never utilize the structure that419419+ * represents itself).420420+ */421421+struct xpc_partition {422422+423423+ /* XPC HB infrastructure */424424+425425+ u64 remote_rp_pa; /* phys addr of partition's rsvd pg */426426+ u64 remote_vars_pa; /* phys addr of partition's vars */427427+ u64 remote_vars_part_pa; /* phys addr of partition's vars part */428428+ u64 last_heartbeat; /* HB at last read */429429+ u64 remote_amos_page_pa; /* phys addr of partition's amos page */430430+ int remote_act_nasid; /* active part's act/deact nasid */431431+ int remote_act_phys_cpuid; /* active part's act/deact phys cpuid */432432+ u32 act_IRQ_rcvd; /* IRQs since activation */433433+ spinlock_t act_lock; /* protect updating of act_state */434434+ u8 act_state; /* from XPC HB viewpoint */435435+ enum xpc_retval reason; /* reason partition is deactivating */436436+ int reason_line; /* line# deactivation initiated from */437437+ int reactivate_nasid; /* nasid in partition to reactivate */438438+439439+440440+ /* XPC infrastructure referencing and teardown control */441441+442442+ u8 setup_state; /* infrastructure setup state */443443+ wait_queue_head_t teardown_wq; /* kthread waiting to teardown infra */444444+ atomic_t references; /* #of references to infrastructure */445445+446446+447447+ /*448448+ * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN449449+ * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION450450+ * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE451451+ * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)452452+ */453453+454454+455455+ u8 nchannels; /* #of defined channels supported */456456+ atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */457457+ struct xpc_channel *channels;/* array of channel structures */458458+459459+ void *local_GPs_base; /* base address of kmalloc'd space */460460+ struct xpc_gp *local_GPs; /* local Get/Put values */461461+ void *remote_GPs_base; /* base address of kmalloc'd space */462462+ struct xpc_gp *remote_GPs;/* copy of remote partition's local Get/Put */463463+ /* values */464464+ u64 remote_GPs_pa; /* phys address of remote partition's local */465465+ /* Get/Put values */466466+467467+468468+ /* fields used to pass args when opening or closing a channel */469469+470470+ void *local_openclose_args_base; /* base address of kmalloc'd space */471471+ struct xpc_openclose_args *local_openclose_args; /* local's args */472472+ void *remote_openclose_args_base; /* base address of kmalloc'd space */473473+ struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */474474+ /* args */475475+ u64 remote_openclose_args_pa; /* phys addr of remote's args */476476+477477+478478+ /* IPI sending, receiving and handling related fields */479479+480480+ int remote_IPI_nasid; /* nasid of where to send IPIs */481481+ int remote_IPI_phys_cpuid; /* phys CPU ID of where to send IPIs */482482+ AMO_t *remote_IPI_amo_va; /* address of remote IPI AMO_t structure */483483+484484+ AMO_t *local_IPI_amo_va; /* address of IPI AMO_t structure */485485+ u64 local_IPI_amo; /* IPI amo flags yet to be handled */486486+ char IPI_owner[8]; /* IPI owner's name */487487+ struct timer_list dropped_IPI_timer; /* dropped IPI timer */488488+489489+ spinlock_t IPI_lock; /* IPI handler lock */490490+491491+492492+ /* channel manager related fields */493493+494494+ atomic_t channel_mgr_requests; /* #of requests to activate chan mgr */495495+ wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */496496+497497+} ____cacheline_aligned;498498+499499+500500+/* struct xpc_partition act_state values (for XPC HB) */501501+502502+#define XPC_P_INACTIVE 0x00 /* partition is not active */503503+#define XPC_P_ACTIVATION_REQ 0x01 /* created thread to activate */504504+#define XPC_P_ACTIVATING 0x02 /* activation thread started */505505+#define XPC_P_ACTIVE 0x03 /* xpc_partition_up() was called */506506+#define XPC_P_DEACTIVATING 0x04 /* partition deactivation initiated */507507+508508+509509+#define XPC_DEACTIVATE_PARTITION(_p, _reason) \510510+ xpc_deactivate_partition(__LINE__, (_p), (_reason))511511+512512+513513+/* struct xpc_partition setup_state values */514514+515515+#define XPC_P_UNSET 0x00 /* infrastructure was never setup */516516+#define XPC_P_SETUP 0x01 /* infrastructure is setup */517517+#define XPC_P_WTEARDOWN 0x02 /* waiting to teardown infrastructure */518518+#define XPC_P_TORNDOWN 0x03 /* infrastructure is torndown */519519+520520+521521+/*522522+ * struct xpc_partition IPI_timer #of seconds to wait before checking for523523+ * dropped IPIs. These occur whenever an IPI amo write doesn't complete until524524+ * after the IPI was received.525525+ */526526+#define XPC_P_DROPPED_IPI_WAIT (0.25 * HZ)527527+528528+529529+#define XPC_PARTID(_p) ((partid_t) ((_p) - &xpc_partitions[0]))530530+531531+532532+533533+/* found in xp_main.c */534534+extern struct xpc_registration xpc_registrations[];535535+536536+537537+/* >>> found in xpc_main.c only */538538+extern struct device *xpc_part;539539+extern struct device *xpc_chan;540540+extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);541541+extern void xpc_dropped_IPI_check(struct xpc_partition *);542542+extern void xpc_activate_kthreads(struct xpc_channel *, int);543543+extern void xpc_create_kthreads(struct xpc_channel *, int);544544+extern void xpc_disconnect_wait(int);545545+546546+547547+/* found in xpc_main.c and efi-xpc.c */548548+extern void xpc_activate_partition(struct xpc_partition *);549549+550550+551551+/* found in xpc_partition.c */552552+extern int xpc_exiting;553553+extern int xpc_hb_interval;554554+extern int xpc_hb_check_interval;555555+extern struct xpc_vars *xpc_vars;556556+extern struct xpc_rsvd_page *xpc_rsvd_page;557557+extern struct xpc_vars_part *xpc_vars_part;558558+extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];559559+extern char xpc_remote_copy_buffer[];560560+extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);561561+extern void xpc_allow_IPI_ops(void);562562+extern void xpc_restrict_IPI_ops(void);563563+extern int xpc_identify_act_IRQ_sender(void);564564+extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);565565+extern void xpc_mark_partition_inactive(struct xpc_partition *);566566+extern void xpc_discovery(void);567567+extern void xpc_check_remote_hb(void);568568+extern void xpc_deactivate_partition(const int, struct xpc_partition *,569569+ enum xpc_retval);570570+extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);571571+572572+573573+/* found in xpc_channel.c */574574+extern void xpc_initiate_connect(int);575575+extern void xpc_initiate_disconnect(int);576576+extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);577577+extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);578578+extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,579579+ xpc_notify_func, void *);580580+extern void xpc_initiate_received(partid_t, int, void *);581581+extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);582582+extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);583583+extern void xpc_process_channel_activity(struct xpc_partition *);584584+extern void xpc_connected_callout(struct xpc_channel *);585585+extern void xpc_deliver_msg(struct xpc_channel *);586586+extern void xpc_disconnect_channel(const int, struct xpc_channel *,587587+ enum xpc_retval, unsigned long *);588588+extern void xpc_disconnected_callout(struct xpc_channel *);589589+extern void xpc_partition_down(struct xpc_partition *, enum xpc_retval);590590+extern void xpc_teardown_infrastructure(struct xpc_partition *);591591+592592+593593+594594+static inline void595595+xpc_wakeup_channel_mgr(struct xpc_partition *part)596596+{597597+ if (atomic_inc_return(&part->channel_mgr_requests) == 1) {598598+ wake_up(&part->channel_mgr_wq);599599+ }600600+}601601+602602+603603+604604+/*605605+ * These next two inlines are used to keep us from tearing down a channel's606606+ * msg queues while a thread may be referencing them.607607+ */608608+static inline void609609+xpc_msgqueue_ref(struct xpc_channel *ch)610610+{611611+ atomic_inc(&ch->references);612612+}613613+614614+static inline void615615+xpc_msgqueue_deref(struct xpc_channel *ch)616616+{617617+ s32 refs = atomic_dec_return(&ch->references);618618+619619+ DBUG_ON(refs < 0);620620+ if (refs == 0) {621621+ xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);622622+ }623623+}624624+625625+626626+627627+#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \628628+ xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)629629+630630+631631+/*632632+ * These two inlines are used to keep us from tearing down a partition's633633+ * setup infrastructure while a thread may be referencing it.634634+ */635635+static inline void636636+xpc_part_deref(struct xpc_partition *part)637637+{638638+ s32 refs = atomic_dec_return(&part->references);639639+640640+641641+ DBUG_ON(refs < 0);642642+ if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN) {643643+ wake_up(&part->teardown_wq);644644+ }645645+}646646+647647+static inline int648648+xpc_part_ref(struct xpc_partition *part)649649+{650650+ int setup;651651+652652+653653+ atomic_inc(&part->references);654654+ setup = (part->setup_state == XPC_P_SETUP);655655+ if (!setup) {656656+ xpc_part_deref(part);657657+ }658658+ return setup;659659+}660660+661661+662662+663663+/*664664+ * The following macro is to be used for the setting of the reason and665665+ * reason_line fields in both the struct xpc_channel and struct xpc_partition666666+ * structures.667667+ */668668+#define XPC_SET_REASON(_p, _reason, _line) \669669+ { \670670+ (_p)->reason = _reason; \671671+ (_p)->reason_line = _line; \672672+ }673673+674674+675675+676676+/*677677+ * The following set of macros and inlines are used for the sending and678678+ * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,679679+ * one that is associated with partition activity (SGI_XPC_ACTIVATE) and680680+ * the other that is associated with channel activity (SGI_XPC_NOTIFY).681681+ */682682+683683+static inline u64684684+xpc_IPI_receive(AMO_t *amo)685685+{686686+ return FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_CLEAR);687687+}688688+689689+690690+static inline enum xpc_retval691691+xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)692692+{693693+ int ret = 0;694694+ unsigned long irq_flags;695695+696696+697697+ local_irq_save(irq_flags);698698+699699+ FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, flag);700700+ sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);701701+702702+ /*703703+ * We must always use the nofault function regardless of whether we704704+ * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we705705+ * didn't, we'd never know that the other partition is down and would706706+ * keep sending IPIs and AMOs to it until the heartbeat times out.707707+ */708708+ ret = xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),709709+ xp_nofault_PIOR_target));710710+711711+ local_irq_restore(irq_flags);712712+713713+ return ((ret == 0) ? xpcSuccess : xpcPioReadError);714714+}715715+716716+717717+/*718718+ * IPIs associated with SGI_XPC_ACTIVATE IRQ.719719+ */720720+721721+/*722722+ * Flag the appropriate AMO variable and send an IPI to the specified node.723723+ */724724+static inline void725725+xpc_activate_IRQ_send(u64 amos_page, int from_nasid, int to_nasid,726726+ int to_phys_cpuid)727727+{728728+ int w_index = XPC_NASID_W_INDEX(from_nasid);729729+ int b_index = XPC_NASID_B_INDEX(from_nasid);730730+ AMO_t *amos = (AMO_t *) __va(amos_page +731731+ (XP_MAX_PARTITIONS * sizeof(AMO_t)));732732+733733+734734+ (void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,735735+ to_phys_cpuid, SGI_XPC_ACTIVATE);736736+}737737+738738+static inline void739739+xpc_IPI_send_activate(struct xpc_vars *vars)740740+{741741+ xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),742742+ vars->act_nasid, vars->act_phys_cpuid);743743+}744744+745745+static inline void746746+xpc_IPI_send_activated(struct xpc_partition *part)747747+{748748+ xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),749749+ part->remote_act_nasid, part->remote_act_phys_cpuid);750750+}751751+752752+static inline void753753+xpc_IPI_send_reactivate(struct xpc_partition *part)754754+{755755+ xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,756756+ xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);757757+}758758+759759+760760+/*761761+ * IPIs associated with SGI_XPC_NOTIFY IRQ.762762+ */763763+764764+/*765765+ * Send an IPI to the remote partition that is associated with the766766+ * specified channel.767767+ */768768+#define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \769769+ xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)770770+771771+static inline void772772+xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,773773+ unsigned long *irq_flags)774774+{775775+ struct xpc_partition *part = &xpc_partitions[ch->partid];776776+ enum xpc_retval ret;777777+778778+779779+ if (likely(part->act_state != XPC_P_DEACTIVATING)) {780780+ ret = xpc_IPI_send(part->remote_IPI_amo_va,781781+ (u64) ipi_flag << (ch->number * 8),782782+ part->remote_IPI_nasid,783783+ part->remote_IPI_phys_cpuid,784784+ SGI_XPC_NOTIFY);785785+ dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",786786+ ipi_flag_string, ch->partid, ch->number, ret);787787+ if (unlikely(ret != xpcSuccess)) {788788+ if (irq_flags != NULL) {789789+ spin_unlock_irqrestore(&ch->lock, *irq_flags);790790+ }791791+ XPC_DEACTIVATE_PARTITION(part, ret);792792+ if (irq_flags != NULL) {793793+ spin_lock_irqsave(&ch->lock, *irq_flags);794794+ }795795+ }796796+ }797797+}798798+799799+800800+/*801801+ * Make it look like the remote partition, which is associated with the802802+ * specified channel, sent us an IPI. This faked IPI will be handled803803+ * by xpc_dropped_IPI_check().804804+ */805805+#define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \806806+ xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)807807+808808+static inline void809809+xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,810810+ char *ipi_flag_string)811811+{812812+ struct xpc_partition *part = &xpc_partitions[ch->partid];813813+814814+815815+ FETCHOP_STORE_OP(TO_AMO((u64) &part->local_IPI_amo_va->variable),816816+ FETCHOP_OR, ((u64) ipi_flag << (ch->number * 8)));817817+ dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",818818+ ipi_flag_string, ch->partid, ch->number);819819+}820820+821821+822822+/*823823+ * The sending and receiving of IPIs includes the setting of an AMO variable824824+ * to indicate the reason the IPI was sent. The 64-bit variable is divided825825+ * up into eight bytes, ordered from right to left. Byte zero pertains to826826+ * channel 0, byte one to channel 1, and so on. Each byte is described by827827+ * the following IPI flags.828828+ */829829+830830+#define XPC_IPI_CLOSEREQUEST 0x01831831+#define XPC_IPI_CLOSEREPLY 0x02832832+#define XPC_IPI_OPENREQUEST 0x04833833+#define XPC_IPI_OPENREPLY 0x08834834+#define XPC_IPI_MSGREQUEST 0x10835835+836836+837837+/* given an AMO variable and a channel#, get its associated IPI flags */838838+#define XPC_GET_IPI_FLAGS(_amo, _c) ((u8) (((_amo) >> ((_c) * 8)) & 0xff))839839+840840+#define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f)841841+#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & 0x1010101010101010)842842+843843+844844+static inline void845845+xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)846846+{847847+ struct xpc_openclose_args *args = ch->local_openclose_args;848848+849849+850850+ args->reason = ch->reason;851851+852852+ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);853853+}854854+855855+static inline void856856+xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)857857+{858858+ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);859859+}860860+861861+static inline void862862+xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)863863+{864864+ struct xpc_openclose_args *args = ch->local_openclose_args;865865+866866+867867+ args->msg_size = ch->msg_size;868868+ args->local_nentries = ch->local_nentries;869869+870870+ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);871871+}872872+873873+static inline void874874+xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)875875+{876876+ struct xpc_openclose_args *args = ch->local_openclose_args;877877+878878+879879+ args->remote_nentries = ch->remote_nentries;880880+ args->local_nentries = ch->local_nentries;881881+ args->local_msgqueue_pa = __pa(ch->local_msgqueue);882882+883883+ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);884884+}885885+886886+static inline void887887+xpc_IPI_send_msgrequest(struct xpc_channel *ch)888888+{889889+ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);890890+}891891+892892+static inline void893893+xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)894894+{895895+ XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);896896+}897897+898898+899899+/*900900+ * Memory for XPC's AMO variables is allocated by the MSPEC driver. These901901+ * pages are located in the lowest granule. The lowest granule uses 4k pages902902+ * for cached references and an alternate TLB handler to never provide a903903+ * cacheable mapping for the entire region. This will prevent speculative904904+ * reading of cached copies of our lines from being issued which will cause905905+ * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64906906+ * (XP_MAX_PARTITIONS) AMO variables for message notification (xpc_main.c)907907+ * and an additional 16 AMO variables for partition activation (xpc_hb.c).908908+ */909909+static inline AMO_t *910910+xpc_IPI_init(partid_t partid)911911+{912912+ AMO_t *part_amo = xpc_vars->amos_page + partid;913913+914914+915915+ xpc_IPI_receive(part_amo);916916+ return part_amo;917917+}918918+919919+920920+921921+static inline enum xpc_retval922922+xpc_map_bte_errors(bte_result_t error)923923+{924924+ switch (error) {925925+ case BTE_SUCCESS: return xpcSuccess;926926+ case BTEFAIL_DIR: return xpcBteDirectoryError;927927+ case BTEFAIL_POISON: return xpcBtePoisonError;928928+ case BTEFAIL_WERR: return xpcBteWriteError;929929+ case BTEFAIL_ACCESS: return xpcBteAccessError;930930+ case BTEFAIL_PWERR: return xpcBtePWriteError;931931+ case BTEFAIL_PRERR: return xpcBtePReadError;932932+ case BTEFAIL_TOUT: return xpcBteTimeOutError;933933+ case BTEFAIL_XTERR: return xpcBteXtalkError;934934+ case BTEFAIL_NOTAVAIL: return xpcBteNotAvailable;935935+ default: return xpcBteUnmappedError;936936+ }937937+}938938+939939+940940+941941+static inline void *942942+xpc_kmalloc_cacheline_aligned(size_t size, int flags, void **base)943943+{944944+ /* see if kmalloc will give us cachline aligned memory by default */945945+ *base = kmalloc(size, flags);946946+ if (*base == NULL) {947947+ return NULL;948948+ }949949+ if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {950950+ return *base;951951+ }952952+ kfree(*base);953953+954954+ /* nope, we'll have to do it ourselves */955955+ *base = kmalloc(size + L1_CACHE_BYTES, flags);956956+ if (*base == NULL) {957957+ return NULL;958958+ }959959+ return (void *) L1_CACHE_ALIGN((u64) *base);960960+}961961+962962+963963+/*964964+ * Check to see if there is any channel activity to/from the specified965965+ * partition.966966+ */967967+static inline void968968+xpc_check_for_channel_activity(struct xpc_partition *part)969969+{970970+ u64 IPI_amo;971971+ unsigned long irq_flags;972972+973973+974974+ IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);975975+ if (IPI_amo == 0) {976976+ return;977977+ }978978+979979+ spin_lock_irqsave(&part->IPI_lock, irq_flags);980980+ part->local_IPI_amo |= IPI_amo;981981+ spin_unlock_irqrestore(&part->IPI_lock, irq_flags);982982+983983+ dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",984984+ XPC_PARTID(part), IPI_amo);985985+986986+ xpc_wakeup_channel_mgr(part);987987+}988988+989989+990990+#endif /* _IA64_SN_KERNEL_XPC_H */991991+
+2297
arch/ia64/sn/kernel/xpc_channel.c
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.77+ */88+99+1010+/*1111+ * Cross Partition Communication (XPC) channel support.1212+ *1313+ * This is the part of XPC that manages the channels and1414+ * sends/receives messages across them to/from other partitions.1515+ *1616+ */1717+1818+1919+#include <linux/kernel.h>2020+#include <linux/init.h>2121+#include <linux/sched.h>2222+#include <linux/cache.h>2323+#include <linux/interrupt.h>2424+#include <linux/slab.h>2525+#include <asm/sn/bte.h>2626+#include <asm/sn/sn_sal.h>2727+#include "xpc.h"2828+2929+3030+/*3131+ * Set up the initial values for the XPartition Communication channels.3232+ */3333+static void3434+xpc_initialize_channels(struct xpc_partition *part, partid_t partid)3535+{3636+ int ch_number;3737+ struct xpc_channel *ch;3838+3939+4040+ for (ch_number = 0; ch_number < part->nchannels; ch_number++) {4141+ ch = &part->channels[ch_number];4242+4343+ ch->partid = partid;4444+ ch->number = ch_number;4545+ ch->flags = XPC_C_DISCONNECTED;4646+4747+ ch->local_GP = &part->local_GPs[ch_number];4848+ ch->local_openclose_args =4949+ &part->local_openclose_args[ch_number];5050+5151+ atomic_set(&ch->kthreads_assigned, 0);5252+ atomic_set(&ch->kthreads_idle, 0);5353+ atomic_set(&ch->kthreads_active, 0);5454+5555+ atomic_set(&ch->references, 0);5656+ atomic_set(&ch->n_to_notify, 0);5757+5858+ spin_lock_init(&ch->lock);5959+ sema_init(&ch->msg_to_pull_sema, 1); /* mutex */6060+6161+ atomic_set(&ch->n_on_msg_allocate_wq, 0);6262+ init_waitqueue_head(&ch->msg_allocate_wq);6363+ init_waitqueue_head(&ch->idle_wq);6464+ }6565+}6666+6767+6868+/*6969+ * Setup the infrastructure necessary to support XPartition Communication7070+ * between the specified remote partition and the local one.7171+ */7272+enum xpc_retval7373+xpc_setup_infrastructure(struct xpc_partition *part)7474+{7575+ int ret;7676+ struct timer_list *timer;7777+ partid_t partid = XPC_PARTID(part);7878+7979+8080+ /*8181+ * Zero out MOST of the entry for this partition. Only the fields8282+ * starting with `nchannels' will be zeroed. The preceding fields must8383+ * remain `viable' across partition ups and downs, since they may be8484+ * referenced during this memset() operation.8585+ */8686+ memset(&part->nchannels, 0, sizeof(struct xpc_partition) -8787+ offsetof(struct xpc_partition, nchannels));8888+8989+ /*9090+ * Allocate all of the channel structures as a contiguous chunk of9191+ * memory.9292+ */9393+ part->channels = kmalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,9494+ GFP_KERNEL);9595+ if (part->channels == NULL) {9696+ dev_err(xpc_chan, "can't get memory for channels\n");9797+ return xpcNoMemory;9898+ }9999+ memset(part->channels, 0, sizeof(struct xpc_channel) * XPC_NCHANNELS);100100+101101+ part->nchannels = XPC_NCHANNELS;102102+103103+104104+ /* allocate all the required GET/PUT values */105105+106106+ part->local_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,107107+ GFP_KERNEL, &part->local_GPs_base);108108+ if (part->local_GPs == NULL) {109109+ kfree(part->channels);110110+ part->channels = NULL;111111+ dev_err(xpc_chan, "can't get memory for local get/put "112112+ "values\n");113113+ return xpcNoMemory;114114+ }115115+ memset(part->local_GPs, 0, XPC_GP_SIZE);116116+117117+ part->remote_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,118118+ GFP_KERNEL, &part->remote_GPs_base);119119+ if (part->remote_GPs == NULL) {120120+ kfree(part->channels);121121+ part->channels = NULL;122122+ kfree(part->local_GPs_base);123123+ part->local_GPs = NULL;124124+ dev_err(xpc_chan, "can't get memory for remote get/put "125125+ "values\n");126126+ return xpcNoMemory;127127+ }128128+ memset(part->remote_GPs, 0, XPC_GP_SIZE);129129+130130+131131+ /* allocate all the required open and close args */132132+133133+ part->local_openclose_args = xpc_kmalloc_cacheline_aligned(134134+ XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,135135+ &part->local_openclose_args_base);136136+ if (part->local_openclose_args == NULL) {137137+ kfree(part->channels);138138+ part->channels = NULL;139139+ kfree(part->local_GPs_base);140140+ part->local_GPs = NULL;141141+ kfree(part->remote_GPs_base);142142+ part->remote_GPs = NULL;143143+ dev_err(xpc_chan, "can't get memory for local connect args\n");144144+ return xpcNoMemory;145145+ }146146+ memset(part->local_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);147147+148148+ part->remote_openclose_args = xpc_kmalloc_cacheline_aligned(149149+ XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,150150+ &part->remote_openclose_args_base);151151+ if (part->remote_openclose_args == NULL) {152152+ kfree(part->channels);153153+ part->channels = NULL;154154+ kfree(part->local_GPs_base);155155+ part->local_GPs = NULL;156156+ kfree(part->remote_GPs_base);157157+ part->remote_GPs = NULL;158158+ kfree(part->local_openclose_args_base);159159+ part->local_openclose_args = NULL;160160+ dev_err(xpc_chan, "can't get memory for remote connect args\n");161161+ return xpcNoMemory;162162+ }163163+ memset(part->remote_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);164164+165165+166166+ xpc_initialize_channels(part, partid);167167+168168+ atomic_set(&part->nchannels_active, 0);169169+170170+171171+ /* local_IPI_amo were set to 0 by an earlier memset() */172172+173173+ /* Initialize this partitions AMO_t structure */174174+ part->local_IPI_amo_va = xpc_IPI_init(partid);175175+176176+ spin_lock_init(&part->IPI_lock);177177+178178+ atomic_set(&part->channel_mgr_requests, 1);179179+ init_waitqueue_head(&part->channel_mgr_wq);180180+181181+ sprintf(part->IPI_owner, "xpc%02d", partid);182182+ ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ,183183+ part->IPI_owner, (void *) (u64) partid);184184+ if (ret != 0) {185185+ kfree(part->channels);186186+ part->channels = NULL;187187+ kfree(part->local_GPs_base);188188+ part->local_GPs = NULL;189189+ kfree(part->remote_GPs_base);190190+ part->remote_GPs = NULL;191191+ kfree(part->local_openclose_args_base);192192+ part->local_openclose_args = NULL;193193+ kfree(part->remote_openclose_args_base);194194+ part->remote_openclose_args = NULL;195195+ dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "196196+ "errno=%d\n", -ret);197197+ return xpcLackOfResources;198198+ }199199+200200+ /* Setup a timer to check for dropped IPIs */201201+ timer = &part->dropped_IPI_timer;202202+ init_timer(timer);203203+ timer->function = (void (*)(unsigned long)) xpc_dropped_IPI_check;204204+ timer->data = (unsigned long) part;205205+ timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT;206206+ add_timer(timer);207207+208208+ /*209209+ * With the setting of the partition setup_state to XPC_P_SETUP, we're210210+ * declaring that this partition is ready to go.211211+ */212212+ (volatile u8) part->setup_state = XPC_P_SETUP;213213+214214+215215+ /*216216+ * Setup the per partition specific variables required by the217217+ * remote partition to establish channel connections with us.218218+ *219219+ * The setting of the magic # indicates that these per partition220220+ * specific variables are ready to be used.221221+ */222222+ xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);223223+ xpc_vars_part[partid].openclose_args_pa =224224+ __pa(part->local_openclose_args);225225+ xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);226226+ xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(smp_processor_id());227227+ xpc_vars_part[partid].IPI_phys_cpuid =228228+ cpu_physical_id(smp_processor_id());229229+ xpc_vars_part[partid].nchannels = part->nchannels;230230+ (volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC1;231231+232232+ return xpcSuccess;233233+}234234+235235+236236+/*237237+ * Create a wrapper that hides the underlying mechanism for pulling a cacheline238238+ * (or multiple cachelines) from a remote partition.239239+ *240240+ * src must be a cacheline aligned physical address on the remote partition.241241+ * dst must be a cacheline aligned virtual address on this partition.242242+ * cnt must be an cacheline sized243243+ */244244+static enum xpc_retval245245+xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,246246+ const void *src, size_t cnt)247247+{248248+ bte_result_t bte_ret;249249+250250+251251+ DBUG_ON((u64) src != L1_CACHE_ALIGN((u64) src));252252+ DBUG_ON((u64) dst != L1_CACHE_ALIGN((u64) dst));253253+ DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));254254+255255+ if (part->act_state == XPC_P_DEACTIVATING) {256256+ return part->reason;257257+ }258258+259259+ bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst),260260+ (u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL);261261+ if (bte_ret == BTE_SUCCESS) {262262+ return xpcSuccess;263263+ }264264+265265+ dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n",266266+ XPC_PARTID(part), bte_ret);267267+268268+ return xpc_map_bte_errors(bte_ret);269269+}270270+271271+272272+/*273273+ * Pull the remote per partititon specific variables from the specified274274+ * partition.275275+ */276276+enum xpc_retval277277+xpc_pull_remote_vars_part(struct xpc_partition *part)278278+{279279+ u8 buffer[L1_CACHE_BYTES * 2];280280+ struct xpc_vars_part *pulled_entry_cacheline =281281+ (struct xpc_vars_part *) L1_CACHE_ALIGN((u64) buffer);282282+ struct xpc_vars_part *pulled_entry;283283+ u64 remote_entry_cacheline_pa, remote_entry_pa;284284+ partid_t partid = XPC_PARTID(part);285285+ enum xpc_retval ret;286286+287287+288288+ /* pull the cacheline that contains the variables we're interested in */289289+290290+ DBUG_ON(part->remote_vars_part_pa !=291291+ L1_CACHE_ALIGN(part->remote_vars_part_pa));292292+ DBUG_ON(sizeof(struct xpc_vars_part) != L1_CACHE_BYTES / 2);293293+294294+ remote_entry_pa = part->remote_vars_part_pa +295295+ sn_partition_id * sizeof(struct xpc_vars_part);296296+297297+ remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));298298+299299+ pulled_entry = (struct xpc_vars_part *) ((u64) pulled_entry_cacheline +300300+ (remote_entry_pa & (L1_CACHE_BYTES - 1)));301301+302302+ ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline,303303+ (void *) remote_entry_cacheline_pa,304304+ L1_CACHE_BYTES);305305+ if (ret != xpcSuccess) {306306+ dev_dbg(xpc_chan, "failed to pull XPC vars_part from "307307+ "partition %d, ret=%d\n", partid, ret);308308+ return ret;309309+ }310310+311311+312312+ /* see if they've been set up yet */313313+314314+ if (pulled_entry->magic != XPC_VP_MAGIC1 &&315315+ pulled_entry->magic != XPC_VP_MAGIC2) {316316+317317+ if (pulled_entry->magic != 0) {318318+ dev_dbg(xpc_chan, "partition %d's XPC vars_part for "319319+ "partition %d has bad magic value (=0x%lx)\n",320320+ partid, sn_partition_id, pulled_entry->magic);321321+ return xpcBadMagic;322322+ }323323+324324+ /* they've not been initialized yet */325325+ return xpcRetry;326326+ }327327+328328+ if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {329329+330330+ /* validate the variables */331331+332332+ if (pulled_entry->GPs_pa == 0 ||333333+ pulled_entry->openclose_args_pa == 0 ||334334+ pulled_entry->IPI_amo_pa == 0) {335335+336336+ dev_err(xpc_chan, "partition %d's XPC vars_part for "337337+ "partition %d are not valid\n", partid,338338+ sn_partition_id);339339+ return xpcInvalidAddress;340340+ }341341+342342+ /* the variables we imported look to be valid */343343+344344+ part->remote_GPs_pa = pulled_entry->GPs_pa;345345+ part->remote_openclose_args_pa =346346+ pulled_entry->openclose_args_pa;347347+ part->remote_IPI_amo_va =348348+ (AMO_t *) __va(pulled_entry->IPI_amo_pa);349349+ part->remote_IPI_nasid = pulled_entry->IPI_nasid;350350+ part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;351351+352352+ if (part->nchannels > pulled_entry->nchannels) {353353+ part->nchannels = pulled_entry->nchannels;354354+ }355355+356356+ /* let the other side know that we've pulled their variables */357357+358358+ (volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC2;359359+ }360360+361361+ if (pulled_entry->magic == XPC_VP_MAGIC1) {362362+ return xpcRetry;363363+ }364364+365365+ return xpcSuccess;366366+}367367+368368+369369+/*370370+ * Get the IPI flags and pull the openclose args and/or remote GPs as needed.371371+ */372372+static u64373373+xpc_get_IPI_flags(struct xpc_partition *part)374374+{375375+ unsigned long irq_flags;376376+ u64 IPI_amo;377377+ enum xpc_retval ret;378378+379379+380380+ /*381381+ * See if there are any IPI flags to be handled.382382+ */383383+384384+ spin_lock_irqsave(&part->IPI_lock, irq_flags);385385+ if ((IPI_amo = part->local_IPI_amo) != 0) {386386+ part->local_IPI_amo = 0;387387+ }388388+ spin_unlock_irqrestore(&part->IPI_lock, irq_flags);389389+390390+391391+ if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {392392+ ret = xpc_pull_remote_cachelines(part,393393+ part->remote_openclose_args,394394+ (void *) part->remote_openclose_args_pa,395395+ XPC_OPENCLOSE_ARGS_SIZE);396396+ if (ret != xpcSuccess) {397397+ XPC_DEACTIVATE_PARTITION(part, ret);398398+399399+ dev_dbg(xpc_chan, "failed to pull openclose args from "400400+ "partition %d, ret=%d\n", XPC_PARTID(part),401401+ ret);402402+403403+ /* don't bother processing IPIs anymore */404404+ IPI_amo = 0;405405+ }406406+ }407407+408408+ if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {409409+ ret = xpc_pull_remote_cachelines(part, part->remote_GPs,410410+ (void *) part->remote_GPs_pa,411411+ XPC_GP_SIZE);412412+ if (ret != xpcSuccess) {413413+ XPC_DEACTIVATE_PARTITION(part, ret);414414+415415+ dev_dbg(xpc_chan, "failed to pull GPs from partition "416416+ "%d, ret=%d\n", XPC_PARTID(part), ret);417417+418418+ /* don't bother processing IPIs anymore */419419+ IPI_amo = 0;420420+ }421421+ }422422+423423+ return IPI_amo;424424+}425425+426426+427427+/*428428+ * Allocate the local message queue and the notify queue.429429+ */430430+static enum xpc_retval431431+xpc_allocate_local_msgqueue(struct xpc_channel *ch)432432+{433433+ unsigned long irq_flags;434434+ int nentries;435435+ size_t nbytes;436436+437437+438438+ // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between439439+ // >>> iterations of the for-loop, bail if set?440440+441441+ // >>> should we impose a minumum #of entries? like 4 or 8?442442+ for (nentries = ch->local_nentries; nentries > 0; nentries--) {443443+444444+ nbytes = nentries * ch->msg_size;445445+ ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,446446+ (GFP_KERNEL | GFP_DMA),447447+ &ch->local_msgqueue_base);448448+ if (ch->local_msgqueue == NULL) {449449+ continue;450450+ }451451+ memset(ch->local_msgqueue, 0, nbytes);452452+453453+ nbytes = nentries * sizeof(struct xpc_notify);454454+ ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA));455455+ if (ch->notify_queue == NULL) {456456+ kfree(ch->local_msgqueue_base);457457+ ch->local_msgqueue = NULL;458458+ continue;459459+ }460460+ memset(ch->notify_queue, 0, nbytes);461461+462462+ spin_lock_irqsave(&ch->lock, irq_flags);463463+ if (nentries < ch->local_nentries) {464464+ dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "465465+ "partid=%d, channel=%d\n", nentries,466466+ ch->local_nentries, ch->partid, ch->number);467467+468468+ ch->local_nentries = nentries;469469+ }470470+ spin_unlock_irqrestore(&ch->lock, irq_flags);471471+ return xpcSuccess;472472+ }473473+474474+ dev_dbg(xpc_chan, "can't get memory for local message queue and notify "475475+ "queue, partid=%d, channel=%d\n", ch->partid, ch->number);476476+ return xpcNoMemory;477477+}478478+479479+480480+/*481481+ * Allocate the cached remote message queue.482482+ */483483+static enum xpc_retval484484+xpc_allocate_remote_msgqueue(struct xpc_channel *ch)485485+{486486+ unsigned long irq_flags;487487+ int nentries;488488+ size_t nbytes;489489+490490+491491+ DBUG_ON(ch->remote_nentries <= 0);492492+493493+ // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between494494+ // >>> iterations of the for-loop, bail if set?495495+496496+ // >>> should we impose a minumum #of entries? like 4 or 8?497497+ for (nentries = ch->remote_nentries; nentries > 0; nentries--) {498498+499499+ nbytes = nentries * ch->msg_size;500500+ ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,501501+ (GFP_KERNEL | GFP_DMA),502502+ &ch->remote_msgqueue_base);503503+ if (ch->remote_msgqueue == NULL) {504504+ continue;505505+ }506506+ memset(ch->remote_msgqueue, 0, nbytes);507507+508508+ spin_lock_irqsave(&ch->lock, irq_flags);509509+ if (nentries < ch->remote_nentries) {510510+ dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "511511+ "partid=%d, channel=%d\n", nentries,512512+ ch->remote_nentries, ch->partid, ch->number);513513+514514+ ch->remote_nentries = nentries;515515+ }516516+ spin_unlock_irqrestore(&ch->lock, irq_flags);517517+ return xpcSuccess;518518+ }519519+520520+ dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "521521+ "partid=%d, channel=%d\n", ch->partid, ch->number);522522+ return xpcNoMemory;523523+}524524+525525+526526+/*527527+ * Allocate message queues and other stuff associated with a channel.528528+ *529529+ * Note: Assumes all of the channel sizes are filled in.530530+ */531531+static enum xpc_retval532532+xpc_allocate_msgqueues(struct xpc_channel *ch)533533+{534534+ unsigned long irq_flags;535535+ int i;536536+ enum xpc_retval ret;537537+538538+539539+ DBUG_ON(ch->flags & XPC_C_SETUP);540540+541541+ if ((ret = xpc_allocate_local_msgqueue(ch)) != xpcSuccess) {542542+ return ret;543543+ }544544+545545+ if ((ret = xpc_allocate_remote_msgqueue(ch)) != xpcSuccess) {546546+ kfree(ch->local_msgqueue_base);547547+ ch->local_msgqueue = NULL;548548+ kfree(ch->notify_queue);549549+ ch->notify_queue = NULL;550550+ return ret;551551+ }552552+553553+ for (i = 0; i < ch->local_nentries; i++) {554554+ /* use a semaphore as an event wait queue */555555+ sema_init(&ch->notify_queue[i].sema, 0);556556+ }557557+558558+ sema_init(&ch->teardown_sema, 0); /* event wait */559559+560560+ spin_lock_irqsave(&ch->lock, irq_flags);561561+ ch->flags |= XPC_C_SETUP;562562+ spin_unlock_irqrestore(&ch->lock, irq_flags);563563+564564+ return xpcSuccess;565565+}566566+567567+568568+/*569569+ * Process a connect message from a remote partition.570570+ *571571+ * Note: xpc_process_connect() is expecting to be called with the572572+ * spin_lock_irqsave held and will leave it locked upon return.573573+ */574574+static void575575+xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)576576+{577577+ enum xpc_retval ret;578578+579579+580580+ DBUG_ON(!spin_is_locked(&ch->lock));581581+582582+ if (!(ch->flags & XPC_C_OPENREQUEST) ||583583+ !(ch->flags & XPC_C_ROPENREQUEST)) {584584+ /* nothing more to do for now */585585+ return;586586+ }587587+ DBUG_ON(!(ch->flags & XPC_C_CONNECTING));588588+589589+ if (!(ch->flags & XPC_C_SETUP)) {590590+ spin_unlock_irqrestore(&ch->lock, *irq_flags);591591+ ret = xpc_allocate_msgqueues(ch);592592+ spin_lock_irqsave(&ch->lock, *irq_flags);593593+594594+ if (ret != xpcSuccess) {595595+ XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);596596+ }597597+ if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) {598598+ return;599599+ }600600+601601+ DBUG_ON(!(ch->flags & XPC_C_SETUP));602602+ DBUG_ON(ch->local_msgqueue == NULL);603603+ DBUG_ON(ch->remote_msgqueue == NULL);604604+ }605605+606606+ if (!(ch->flags & XPC_C_OPENREPLY)) {607607+ ch->flags |= XPC_C_OPENREPLY;608608+ xpc_IPI_send_openreply(ch, irq_flags);609609+ }610610+611611+ if (!(ch->flags & XPC_C_ROPENREPLY)) {612612+ return;613613+ }614614+615615+ DBUG_ON(ch->remote_msgqueue_pa == 0);616616+617617+ ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */618618+619619+ dev_info(xpc_chan, "channel %d to partition %d connected\n",620620+ ch->number, ch->partid);621621+622622+ spin_unlock_irqrestore(&ch->lock, *irq_flags);623623+ xpc_create_kthreads(ch, 1);624624+ spin_lock_irqsave(&ch->lock, *irq_flags);625625+}626626+627627+628628+/*629629+ * Free up message queues and other stuff that were allocated for the specified630630+ * channel.631631+ *632632+ * Note: ch->reason and ch->reason_line are left set for debugging purposes,633633+ * they're cleared when XPC_C_DISCONNECTED is cleared.634634+ */635635+static void636636+xpc_free_msgqueues(struct xpc_channel *ch)637637+{638638+ DBUG_ON(!spin_is_locked(&ch->lock));639639+ DBUG_ON(atomic_read(&ch->n_to_notify) != 0);640640+641641+ ch->remote_msgqueue_pa = 0;642642+ ch->func = NULL;643643+ ch->key = NULL;644644+ ch->msg_size = 0;645645+ ch->local_nentries = 0;646646+ ch->remote_nentries = 0;647647+ ch->kthreads_assigned_limit = 0;648648+ ch->kthreads_idle_limit = 0;649649+650650+ ch->local_GP->get = 0;651651+ ch->local_GP->put = 0;652652+ ch->remote_GP.get = 0;653653+ ch->remote_GP.put = 0;654654+ ch->w_local_GP.get = 0;655655+ ch->w_local_GP.put = 0;656656+ ch->w_remote_GP.get = 0;657657+ ch->w_remote_GP.put = 0;658658+ ch->next_msg_to_pull = 0;659659+660660+ if (ch->flags & XPC_C_SETUP) {661661+ ch->flags &= ~XPC_C_SETUP;662662+663663+ dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",664664+ ch->flags, ch->partid, ch->number);665665+666666+ kfree(ch->local_msgqueue_base);667667+ ch->local_msgqueue = NULL;668668+ kfree(ch->remote_msgqueue_base);669669+ ch->remote_msgqueue = NULL;670670+ kfree(ch->notify_queue);671671+ ch->notify_queue = NULL;672672+673673+ /* in case someone is waiting for the teardown to complete */674674+ up(&ch->teardown_sema);675675+ }676676+}677677+678678+679679+/*680680+ * spin_lock_irqsave() is expected to be held on entry.681681+ */682682+static void683683+xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)684684+{685685+ struct xpc_partition *part = &xpc_partitions[ch->partid];686686+ u32 ch_flags = ch->flags;687687+688688+689689+ DBUG_ON(!spin_is_locked(&ch->lock));690690+691691+ if (!(ch->flags & XPC_C_DISCONNECTING)) {692692+ return;693693+ }694694+695695+ DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));696696+697697+ /* make sure all activity has settled down first */698698+699699+ if (atomic_read(&ch->references) > 0) {700700+ return;701701+ }702702+ DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);703703+704704+ /* it's now safe to free the channel's message queues */705705+706706+ xpc_free_msgqueues(ch);707707+ DBUG_ON(ch->flags & XPC_C_SETUP);708708+709709+ if (part->act_state != XPC_P_DEACTIVATING) {710710+711711+ /* as long as the other side is up do the full protocol */712712+713713+ if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {714714+ return;715715+ }716716+717717+ if (!(ch->flags & XPC_C_CLOSEREPLY)) {718718+ ch->flags |= XPC_C_CLOSEREPLY;719719+ xpc_IPI_send_closereply(ch, irq_flags);720720+ }721721+722722+ if (!(ch->flags & XPC_C_RCLOSEREPLY)) {723723+ return;724724+ }725725+ }726726+727727+ /* both sides are disconnected now */728728+729729+ ch->flags = XPC_C_DISCONNECTED; /* clear all flags, but this one */730730+731731+ atomic_dec(&part->nchannels_active);732732+733733+ if (ch_flags & XPC_C_WASCONNECTED) {734734+ dev_info(xpc_chan, "channel %d to partition %d disconnected, "735735+ "reason=%d\n", ch->number, ch->partid, ch->reason);736736+ }737737+}738738+739739+740740+/*741741+ * Process a change in the channel's remote connection state.742742+ */743743+static void744744+xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,745745+ u8 IPI_flags)746746+{747747+ unsigned long irq_flags;748748+ struct xpc_openclose_args *args =749749+ &part->remote_openclose_args[ch_number];750750+ struct xpc_channel *ch = &part->channels[ch_number];751751+ enum xpc_retval reason;752752+753753+754754+755755+ spin_lock_irqsave(&ch->lock, irq_flags);756756+757757+758758+ if (IPI_flags & XPC_IPI_CLOSEREQUEST) {759759+760760+ dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "761761+ "from partid=%d, channel=%d\n", args->reason,762762+ ch->partid, ch->number);763763+764764+ /*765765+ * If RCLOSEREQUEST is set, we're probably waiting for766766+ * RCLOSEREPLY. We should find it and a ROPENREQUEST packed767767+ * with this RCLOSEQREUQEST in the IPI_flags.768768+ */769769+770770+ if (ch->flags & XPC_C_RCLOSEREQUEST) {771771+ DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));772772+ DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));773773+ DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));774774+ DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);775775+776776+ DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));777777+ IPI_flags &= ~XPC_IPI_CLOSEREPLY;778778+ ch->flags |= XPC_C_RCLOSEREPLY;779779+780780+ /* both sides have finished disconnecting */781781+ xpc_process_disconnect(ch, &irq_flags);782782+ }783783+784784+ if (ch->flags & XPC_C_DISCONNECTED) {785785+ // >>> explain this section786786+787787+ if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {788788+ DBUG_ON(part->act_state !=789789+ XPC_P_DEACTIVATING);790790+ spin_unlock_irqrestore(&ch->lock, irq_flags);791791+ return;792792+ }793793+794794+ XPC_SET_REASON(ch, 0, 0);795795+ ch->flags &= ~XPC_C_DISCONNECTED;796796+797797+ atomic_inc(&part->nchannels_active);798798+ ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);799799+ }800800+801801+ IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);802802+803803+ /*804804+ * The meaningful CLOSEREQUEST connection state fields are:805805+ * reason = reason connection is to be closed806806+ */807807+808808+ ch->flags |= XPC_C_RCLOSEREQUEST;809809+810810+ if (!(ch->flags & XPC_C_DISCONNECTING)) {811811+ reason = args->reason;812812+ if (reason <= xpcSuccess || reason > xpcUnknownReason) {813813+ reason = xpcUnknownReason;814814+ } else if (reason == xpcUnregistering) {815815+ reason = xpcOtherUnregistering;816816+ }817817+818818+ XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);819819+ } else {820820+ xpc_process_disconnect(ch, &irq_flags);821821+ }822822+ }823823+824824+825825+ if (IPI_flags & XPC_IPI_CLOSEREPLY) {826826+827827+ dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"828828+ " channel=%d\n", ch->partid, ch->number);829829+830830+ if (ch->flags & XPC_C_DISCONNECTED) {831831+ DBUG_ON(part->act_state != XPC_P_DEACTIVATING);832832+ spin_unlock_irqrestore(&ch->lock, irq_flags);833833+ return;834834+ }835835+836836+ DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));837837+ DBUG_ON(!(ch->flags & XPC_C_RCLOSEREQUEST));838838+839839+ ch->flags |= XPC_C_RCLOSEREPLY;840840+841841+ if (ch->flags & XPC_C_CLOSEREPLY) {842842+ /* both sides have finished disconnecting */843843+ xpc_process_disconnect(ch, &irq_flags);844844+ }845845+ }846846+847847+848848+ if (IPI_flags & XPC_IPI_OPENREQUEST) {849849+850850+ dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "851851+ "local_nentries=%d) received from partid=%d, "852852+ "channel=%d\n", args->msg_size, args->local_nentries,853853+ ch->partid, ch->number);854854+855855+ if ((ch->flags & XPC_C_DISCONNECTING) ||856856+ part->act_state == XPC_P_DEACTIVATING) {857857+ spin_unlock_irqrestore(&ch->lock, irq_flags);858858+ return;859859+ }860860+ DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |861861+ XPC_C_OPENREQUEST)));862862+ DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |863863+ XPC_C_OPENREPLY | XPC_C_CONNECTED));864864+865865+ /*866866+ * The meaningful OPENREQUEST connection state fields are:867867+ * msg_size = size of channel's messages in bytes868868+ * local_nentries = remote partition's local_nentries869869+ */870870+ DBUG_ON(args->msg_size == 0);871871+ DBUG_ON(args->local_nentries == 0);872872+873873+ ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);874874+ ch->remote_nentries = args->local_nentries;875875+876876+877877+ if (ch->flags & XPC_C_OPENREQUEST) {878878+ if (args->msg_size != ch->msg_size) {879879+ XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,880880+ &irq_flags);881881+ spin_unlock_irqrestore(&ch->lock, irq_flags);882882+ return;883883+ }884884+ } else {885885+ ch->msg_size = args->msg_size;886886+887887+ XPC_SET_REASON(ch, 0, 0);888888+ ch->flags &= ~XPC_C_DISCONNECTED;889889+890890+ atomic_inc(&part->nchannels_active);891891+ }892892+893893+ xpc_process_connect(ch, &irq_flags);894894+ }895895+896896+897897+ if (IPI_flags & XPC_IPI_OPENREPLY) {898898+899899+ dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "900900+ "local_nentries=%d, remote_nentries=%d) received from "901901+ "partid=%d, channel=%d\n", args->local_msgqueue_pa,902902+ args->local_nentries, args->remote_nentries,903903+ ch->partid, ch->number);904904+905905+ if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {906906+ spin_unlock_irqrestore(&ch->lock, irq_flags);907907+ return;908908+ }909909+ DBUG_ON(!(ch->flags & XPC_C_OPENREQUEST));910910+ DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));911911+ DBUG_ON(ch->flags & XPC_C_CONNECTED);912912+913913+ /*914914+ * The meaningful OPENREPLY connection state fields are:915915+ * local_msgqueue_pa = physical address of remote916916+ * partition's local_msgqueue917917+ * local_nentries = remote partition's local_nentries918918+ * remote_nentries = remote partition's remote_nentries919919+ */920920+ DBUG_ON(args->local_msgqueue_pa == 0);921921+ DBUG_ON(args->local_nentries == 0);922922+ DBUG_ON(args->remote_nentries == 0);923923+924924+ ch->flags |= XPC_C_ROPENREPLY;925925+ ch->remote_msgqueue_pa = args->local_msgqueue_pa;926926+927927+ if (args->local_nentries < ch->remote_nentries) {928928+ dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "929929+ "remote_nentries=%d, old remote_nentries=%d, "930930+ "partid=%d, channel=%d\n",931931+ args->local_nentries, ch->remote_nentries,932932+ ch->partid, ch->number);933933+934934+ ch->remote_nentries = args->local_nentries;935935+ }936936+ if (args->remote_nentries < ch->local_nentries) {937937+ dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "938938+ "local_nentries=%d, old local_nentries=%d, "939939+ "partid=%d, channel=%d\n",940940+ args->remote_nentries, ch->local_nentries,941941+ ch->partid, ch->number);942942+943943+ ch->local_nentries = args->remote_nentries;944944+ }945945+946946+ xpc_process_connect(ch, &irq_flags);947947+ }948948+949949+ spin_unlock_irqrestore(&ch->lock, irq_flags);950950+}951951+952952+953953+/*954954+ * Attempt to establish a channel connection to a remote partition.955955+ */956956+static enum xpc_retval957957+xpc_connect_channel(struct xpc_channel *ch)958958+{959959+ unsigned long irq_flags;960960+ struct xpc_registration *registration = &xpc_registrations[ch->number];961961+962962+963963+ if (down_interruptible(®istration->sema) != 0) {964964+ return xpcInterrupted;965965+ }966966+967967+ if (!XPC_CHANNEL_REGISTERED(ch->number)) {968968+ up(®istration->sema);969969+ return xpcUnregistered;970970+ }971971+972972+ spin_lock_irqsave(&ch->lock, irq_flags);973973+974974+ DBUG_ON(ch->flags & XPC_C_CONNECTED);975975+ DBUG_ON(ch->flags & XPC_C_OPENREQUEST);976976+977977+ if (ch->flags & XPC_C_DISCONNECTING) {978978+ spin_unlock_irqrestore(&ch->lock, irq_flags);979979+ up(®istration->sema);980980+ return ch->reason;981981+ }982982+983983+984984+ /* add info from the channel connect registration to the channel */985985+986986+ ch->kthreads_assigned_limit = registration->assigned_limit;987987+ ch->kthreads_idle_limit = registration->idle_limit;988988+ DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);989989+ DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);990990+ DBUG_ON(atomic_read(&ch->kthreads_active) != 0);991991+992992+ ch->func = registration->func;993993+ DBUG_ON(registration->func == NULL);994994+ ch->key = registration->key;995995+996996+ ch->local_nentries = registration->nentries;997997+998998+ if (ch->flags & XPC_C_ROPENREQUEST) {999999+ if (registration->msg_size != ch->msg_size) {10001000+ /* the local and remote sides aren't the same */10011001+10021002+ /*10031003+ * Because XPC_DISCONNECT_CHANNEL() can block we're10041004+ * forced to up the registration sema before we unlock10051005+ * the channel lock. But that's okay here because we're10061006+ * done with the part that required the registration10071007+ * sema. XPC_DISCONNECT_CHANNEL() requires that the10081008+ * channel lock be locked and will unlock and relock10091009+ * the channel lock as needed.10101010+ */10111011+ up(®istration->sema);10121012+ XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,10131013+ &irq_flags);10141014+ spin_unlock_irqrestore(&ch->lock, irq_flags);10151015+ return xpcUnequalMsgSizes;10161016+ }10171017+ } else {10181018+ ch->msg_size = registration->msg_size;10191019+10201020+ XPC_SET_REASON(ch, 0, 0);10211021+ ch->flags &= ~XPC_C_DISCONNECTED;10221022+10231023+ atomic_inc(&xpc_partitions[ch->partid].nchannels_active);10241024+ }10251025+10261026+ up(®istration->sema);10271027+10281028+10291029+ /* initiate the connection */10301030+10311031+ ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);10321032+ xpc_IPI_send_openrequest(ch, &irq_flags);10331033+10341034+ xpc_process_connect(ch, &irq_flags);10351035+10361036+ spin_unlock_irqrestore(&ch->lock, irq_flags);10371037+10381038+ return xpcSuccess;10391039+}10401040+10411041+10421042+/*10431043+ * Notify those who wanted to be notified upon delivery of their message.10441044+ */10451045+static void10461046+xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)10471047+{10481048+ struct xpc_notify *notify;10491049+ u8 notify_type;10501050+ s64 get = ch->w_remote_GP.get - 1;10511051+10521052+10531053+ while (++get < put && atomic_read(&ch->n_to_notify) > 0) {10541054+10551055+ notify = &ch->notify_queue[get % ch->local_nentries];10561056+10571057+ /*10581058+ * See if the notify entry indicates it was associated with10591059+ * a message who's sender wants to be notified. It is possible10601060+ * that it is, but someone else is doing or has done the10611061+ * notification.10621062+ */10631063+ notify_type = notify->type;10641064+ if (notify_type == 0 ||10651065+ cmpxchg(¬ify->type, notify_type, 0) !=10661066+ notify_type) {10671067+ continue;10681068+ }10691069+10701070+ DBUG_ON(notify_type != XPC_N_CALL);10711071+10721072+ atomic_dec(&ch->n_to_notify);10731073+10741074+ if (notify->func != NULL) {10751075+ dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "10761076+ "msg_number=%ld, partid=%d, channel=%d\n",10771077+ (void *) notify, get, ch->partid, ch->number);10781078+10791079+ notify->func(reason, ch->partid, ch->number,10801080+ notify->key);10811081+10821082+ dev_dbg(xpc_chan, "notify->func() returned, "10831083+ "notify=0x%p, msg_number=%ld, partid=%d, "10841084+ "channel=%d\n", (void *) notify, get,10851085+ ch->partid, ch->number);10861086+ }10871087+ }10881088+}10891089+10901090+10911091+/*10921092+ * Clear some of the msg flags in the local message queue.10931093+ */10941094+static inline void10951095+xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)10961096+{10971097+ struct xpc_msg *msg;10981098+ s64 get;10991099+11001100+11011101+ get = ch->w_remote_GP.get;11021102+ do {11031103+ msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +11041104+ (get % ch->local_nentries) * ch->msg_size);11051105+ msg->flags = 0;11061106+ } while (++get < (volatile s64) ch->remote_GP.get);11071107+}11081108+11091109+11101110+/*11111111+ * Clear some of the msg flags in the remote message queue.11121112+ */11131113+static inline void11141114+xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)11151115+{11161116+ struct xpc_msg *msg;11171117+ s64 put;11181118+11191119+11201120+ put = ch->w_remote_GP.put;11211121+ do {11221122+ msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +11231123+ (put % ch->remote_nentries) * ch->msg_size);11241124+ msg->flags = 0;11251125+ } while (++put < (volatile s64) ch->remote_GP.put);11261126+}11271127+11281128+11291129+static void11301130+xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)11311131+{11321132+ struct xpc_channel *ch = &part->channels[ch_number];11331133+ int nmsgs_sent;11341134+11351135+11361136+ ch->remote_GP = part->remote_GPs[ch_number];11371137+11381138+11391139+ /* See what, if anything, has changed for each connected channel */11401140+11411141+ xpc_msgqueue_ref(ch);11421142+11431143+ if (ch->w_remote_GP.get == ch->remote_GP.get &&11441144+ ch->w_remote_GP.put == ch->remote_GP.put) {11451145+ /* nothing changed since GPs were last pulled */11461146+ xpc_msgqueue_deref(ch);11471147+ return;11481148+ }11491149+11501150+ if (!(ch->flags & XPC_C_CONNECTED)){11511151+ xpc_msgqueue_deref(ch);11521152+ return;11531153+ }11541154+11551155+11561156+ /*11571157+ * First check to see if messages recently sent by us have been11581158+ * received by the other side. (The remote GET value will have11591159+ * changed since we last looked at it.)11601160+ */11611161+11621162+ if (ch->w_remote_GP.get != ch->remote_GP.get) {11631163+11641164+ /*11651165+ * We need to notify any senders that want to be notified11661166+ * that their sent messages have been received by their11671167+ * intended recipients. We need to do this before updating11681168+ * w_remote_GP.get so that we don't allocate the same message11691169+ * queue entries prematurely (see xpc_allocate_msg()).11701170+ */11711171+ if (atomic_read(&ch->n_to_notify) > 0) {11721172+ /*11731173+ * Notify senders that messages sent have been11741174+ * received and delivered by the other side.11751175+ */11761176+ xpc_notify_senders(ch, xpcMsgDelivered,11771177+ ch->remote_GP.get);11781178+ }11791179+11801180+ /*11811181+ * Clear msg->flags in previously sent messages, so that11821182+ * they're ready for xpc_allocate_msg().11831183+ */11841184+ xpc_clear_local_msgqueue_flags(ch);11851185+11861186+ (volatile s64) ch->w_remote_GP.get = ch->remote_GP.get;11871187+11881188+ dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "11891189+ "channel=%d\n", ch->w_remote_GP.get, ch->partid,11901190+ ch->number);11911191+11921192+ /*11931193+ * If anyone was waiting for message queue entries to become11941194+ * available, wake them up.11951195+ */11961196+ if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {11971197+ wake_up(&ch->msg_allocate_wq);11981198+ }11991199+ }12001200+12011201+12021202+ /*12031203+ * Now check for newly sent messages by the other side. (The remote12041204+ * PUT value will have changed since we last looked at it.)12051205+ */12061206+12071207+ if (ch->w_remote_GP.put != ch->remote_GP.put) {12081208+ /*12091209+ * Clear msg->flags in previously received messages, so that12101210+ * they're ready for xpc_get_deliverable_msg().12111211+ */12121212+ xpc_clear_remote_msgqueue_flags(ch);12131213+12141214+ (volatile s64) ch->w_remote_GP.put = ch->remote_GP.put;12151215+12161216+ dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "12171217+ "channel=%d\n", ch->w_remote_GP.put, ch->partid,12181218+ ch->number);12191219+12201220+ nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;12211221+ if (nmsgs_sent > 0) {12221222+ dev_dbg(xpc_chan, "msgs waiting to be copied and "12231223+ "delivered=%d, partid=%d, channel=%d\n",12241224+ nmsgs_sent, ch->partid, ch->number);12251225+12261226+ if (ch->flags & XPC_C_CONNECTCALLOUT) {12271227+ xpc_activate_kthreads(ch, nmsgs_sent);12281228+ }12291229+ }12301230+ }12311231+12321232+ xpc_msgqueue_deref(ch);12331233+}12341234+12351235+12361236+void12371237+xpc_process_channel_activity(struct xpc_partition *part)12381238+{12391239+ unsigned long irq_flags;12401240+ u64 IPI_amo, IPI_flags;12411241+ struct xpc_channel *ch;12421242+ int ch_number;12431243+12441244+12451245+ IPI_amo = xpc_get_IPI_flags(part);12461246+12471247+ /*12481248+ * Initiate channel connections for registered channels.12491249+ *12501250+ * For each connected channel that has pending messages activate idle12511251+ * kthreads and/or create new kthreads as needed.12521252+ */12531253+12541254+ for (ch_number = 0; ch_number < part->nchannels; ch_number++) {12551255+ ch = &part->channels[ch_number];12561256+12571257+12581258+ /*12591259+ * Process any open or close related IPI flags, and then deal12601260+ * with connecting or disconnecting the channel as required.12611261+ */12621262+12631263+ IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);12641264+12651265+ if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags)) {12661266+ xpc_process_openclose_IPI(part, ch_number, IPI_flags);12671267+ }12681268+12691269+12701270+ if (ch->flags & XPC_C_DISCONNECTING) {12711271+ spin_lock_irqsave(&ch->lock, irq_flags);12721272+ xpc_process_disconnect(ch, &irq_flags);12731273+ spin_unlock_irqrestore(&ch->lock, irq_flags);12741274+ continue;12751275+ }12761276+12771277+ if (part->act_state == XPC_P_DEACTIVATING) {12781278+ continue;12791279+ }12801280+12811281+ if (!(ch->flags & XPC_C_CONNECTED)) {12821282+ if (!(ch->flags & XPC_C_OPENREQUEST)) {12831283+ DBUG_ON(ch->flags & XPC_C_SETUP);12841284+ (void) xpc_connect_channel(ch);12851285+ } else {12861286+ spin_lock_irqsave(&ch->lock, irq_flags);12871287+ xpc_process_connect(ch, &irq_flags);12881288+ spin_unlock_irqrestore(&ch->lock, irq_flags);12891289+ }12901290+ continue;12911291+ }12921292+12931293+12941294+ /*12951295+ * Process any message related IPI flags, this may involve the12961296+ * activation of kthreads to deliver any pending messages sent12971297+ * from the other partition.12981298+ */12991299+13001300+ if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags)) {13011301+ xpc_process_msg_IPI(part, ch_number);13021302+ }13031303+ }13041304+}13051305+13061306+13071307+/*13081308+ * XPC's heartbeat code calls this function to inform XPC that a partition has13091309+ * gone down. XPC responds by tearing down the XPartition Communication13101310+ * infrastructure used for the just downed partition.13111311+ *13121312+ * XPC's heartbeat code will never call this function and xpc_partition_up()13131313+ * at the same time. Nor will it ever make multiple calls to either function13141314+ * at the same time.13151315+ */13161316+void13171317+xpc_partition_down(struct xpc_partition *part, enum xpc_retval reason)13181318+{13191319+ unsigned long irq_flags;13201320+ int ch_number;13211321+ struct xpc_channel *ch;13221322+13231323+13241324+ dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",13251325+ XPC_PARTID(part), reason);13261326+13271327+ if (!xpc_part_ref(part)) {13281328+ /* infrastructure for this partition isn't currently set up */13291329+ return;13301330+ }13311331+13321332+13331333+ /* disconnect all channels associated with the downed partition */13341334+13351335+ for (ch_number = 0; ch_number < part->nchannels; ch_number++) {13361336+ ch = &part->channels[ch_number];13371337+13381338+13391339+ xpc_msgqueue_ref(ch);13401340+ spin_lock_irqsave(&ch->lock, irq_flags);13411341+13421342+ XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);13431343+13441344+ spin_unlock_irqrestore(&ch->lock, irq_flags);13451345+ xpc_msgqueue_deref(ch);13461346+ }13471347+13481348+ xpc_wakeup_channel_mgr(part);13491349+13501350+ xpc_part_deref(part);13511351+}13521352+13531353+13541354+/*13551355+ * Teardown the infrastructure necessary to support XPartition Communication13561356+ * between the specified remote partition and the local one.13571357+ */13581358+void13591359+xpc_teardown_infrastructure(struct xpc_partition *part)13601360+{13611361+ partid_t partid = XPC_PARTID(part);13621362+13631363+13641364+ /*13651365+ * We start off by making this partition inaccessible to local13661366+ * processes by marking it as no longer setup. Then we make it13671367+ * inaccessible to remote processes by clearing the XPC per partition13681368+ * specific variable's magic # (which indicates that these variables13691369+ * are no longer valid) and by ignoring all XPC notify IPIs sent to13701370+ * this partition.13711371+ */13721372+13731373+ DBUG_ON(atomic_read(&part->nchannels_active) != 0);13741374+ DBUG_ON(part->setup_state != XPC_P_SETUP);13751375+ part->setup_state = XPC_P_WTEARDOWN;13761376+13771377+ xpc_vars_part[partid].magic = 0;13781378+13791379+13801380+ free_irq(SGI_XPC_NOTIFY, (void *) (u64) partid);13811381+13821382+13831383+ /*13841384+ * Before proceding with the teardown we have to wait until all13851385+ * existing references cease.13861386+ */13871387+ wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));13881388+13891389+13901390+ /* now we can begin tearing down the infrastructure */13911391+13921392+ part->setup_state = XPC_P_TORNDOWN;13931393+13941394+ /* in case we've still got outstanding timers registered... */13951395+ del_timer_sync(&part->dropped_IPI_timer);13961396+13971397+ kfree(part->remote_openclose_args_base);13981398+ part->remote_openclose_args = NULL;13991399+ kfree(part->local_openclose_args_base);14001400+ part->local_openclose_args = NULL;14011401+ kfree(part->remote_GPs_base);14021402+ part->remote_GPs = NULL;14031403+ kfree(part->local_GPs_base);14041404+ part->local_GPs = NULL;14051405+ kfree(part->channels);14061406+ part->channels = NULL;14071407+ part->local_IPI_amo_va = NULL;14081408+}14091409+14101410+14111411+/*14121412+ * Called by XP at the time of channel connection registration to cause14131413+ * XPC to establish connections to all currently active partitions.14141414+ */14151415+void14161416+xpc_initiate_connect(int ch_number)14171417+{14181418+ partid_t partid;14191419+ struct xpc_partition *part;14201420+ struct xpc_channel *ch;14211421+14221422+14231423+ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);14241424+14251425+ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {14261426+ part = &xpc_partitions[partid];14271427+14281428+ if (xpc_part_ref(part)) {14291429+ ch = &part->channels[ch_number];14301430+14311431+ if (!(ch->flags & XPC_C_DISCONNECTING)) {14321432+ DBUG_ON(ch->flags & XPC_C_OPENREQUEST);14331433+ DBUG_ON(ch->flags & XPC_C_CONNECTED);14341434+ DBUG_ON(ch->flags & XPC_C_SETUP);14351435+14361436+ /*14371437+ * Initiate the establishment of a connection14381438+ * on the newly registered channel to the14391439+ * remote partition.14401440+ */14411441+ xpc_wakeup_channel_mgr(part);14421442+ }14431443+14441444+ xpc_part_deref(part);14451445+ }14461446+ }14471447+}14481448+14491449+14501450+void14511451+xpc_connected_callout(struct xpc_channel *ch)14521452+{14531453+ unsigned long irq_flags;14541454+14551455+14561456+ /* let the registerer know that a connection has been established */14571457+14581458+ if (ch->func != NULL) {14591459+ dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, "14601460+ "partid=%d, channel=%d\n", ch->partid, ch->number);14611461+14621462+ ch->func(xpcConnected, ch->partid, ch->number,14631463+ (void *) (u64) ch->local_nentries, ch->key);14641464+14651465+ dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "14661466+ "partid=%d, channel=%d\n", ch->partid, ch->number);14671467+ }14681468+14691469+ spin_lock_irqsave(&ch->lock, irq_flags);14701470+ ch->flags |= XPC_C_CONNECTCALLOUT;14711471+ spin_unlock_irqrestore(&ch->lock, irq_flags);14721472+}14731473+14741474+14751475+/*14761476+ * Called by XP at the time of channel connection unregistration to cause14771477+ * XPC to teardown all current connections for the specified channel.14781478+ *14791479+ * Before returning xpc_initiate_disconnect() will wait until all connections14801480+ * on the specified channel have been closed/torndown. So the caller can be14811481+ * assured that they will not be receiving any more callouts from XPC to the14821482+ * function they registered via xpc_connect().14831483+ *14841484+ * Arguments:14851485+ *14861486+ * ch_number - channel # to unregister.14871487+ */14881488+void14891489+xpc_initiate_disconnect(int ch_number)14901490+{14911491+ unsigned long irq_flags;14921492+ partid_t partid;14931493+ struct xpc_partition *part;14941494+ struct xpc_channel *ch;14951495+14961496+14971497+ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);14981498+14991499+ /* initiate the channel disconnect for every active partition */15001500+ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {15011501+ part = &xpc_partitions[partid];15021502+15031503+ if (xpc_part_ref(part)) {15041504+ ch = &part->channels[ch_number];15051505+ xpc_msgqueue_ref(ch);15061506+15071507+ spin_lock_irqsave(&ch->lock, irq_flags);15081508+15091509+ XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,15101510+ &irq_flags);15111511+15121512+ spin_unlock_irqrestore(&ch->lock, irq_flags);15131513+15141514+ xpc_msgqueue_deref(ch);15151515+ xpc_part_deref(part);15161516+ }15171517+ }15181518+15191519+ xpc_disconnect_wait(ch_number);15201520+}15211521+15221522+15231523+/*15241524+ * To disconnect a channel, and reflect it back to all who may be waiting.15251525+ *15261526+ * >>> An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by15271527+ * >>> xpc_free_msgqueues().15281528+ *15291529+ * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.15301530+ */15311531+void15321532+xpc_disconnect_channel(const int line, struct xpc_channel *ch,15331533+ enum xpc_retval reason, unsigned long *irq_flags)15341534+{15351535+ u32 flags;15361536+15371537+15381538+ DBUG_ON(!spin_is_locked(&ch->lock));15391539+15401540+ if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {15411541+ return;15421542+ }15431543+ DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));15441544+15451545+ dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",15461546+ reason, line, ch->partid, ch->number);15471547+15481548+ XPC_SET_REASON(ch, reason, line);15491549+15501550+ flags = ch->flags;15511551+ /* some of these may not have been set */15521552+ ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |15531553+ XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |15541554+ XPC_C_CONNECTING | XPC_C_CONNECTED);15551555+15561556+ ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);15571557+ xpc_IPI_send_closerequest(ch, irq_flags);15581558+15591559+ if (flags & XPC_C_CONNECTED) {15601560+ ch->flags |= XPC_C_WASCONNECTED;15611561+ }15621562+15631563+ if (atomic_read(&ch->kthreads_idle) > 0) {15641564+ /* wake all idle kthreads so they can exit */15651565+ wake_up_all(&ch->idle_wq);15661566+ }15671567+15681568+ spin_unlock_irqrestore(&ch->lock, *irq_flags);15691569+15701570+15711571+ /* wake those waiting to allocate an entry from the local msg queue */15721572+15731573+ if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {15741574+ wake_up(&ch->msg_allocate_wq);15751575+ }15761576+15771577+ /* wake those waiting for notify completion */15781578+15791579+ if (atomic_read(&ch->n_to_notify) > 0) {15801580+ xpc_notify_senders(ch, reason, ch->w_local_GP.put);15811581+ }15821582+15831583+ spin_lock_irqsave(&ch->lock, *irq_flags);15841584+}15851585+15861586+15871587+void15881588+xpc_disconnected_callout(struct xpc_channel *ch)15891589+{15901590+ /*15911591+ * Let the channel's registerer know that the channel is now15921592+ * disconnected. We don't want to do this if the registerer was never15931593+ * informed of a connection being made, unless the disconnect was for15941594+ * abnormal reasons.15951595+ */15961596+15971597+ if (ch->func != NULL) {15981598+ dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "15991599+ "channel=%d\n", ch->reason, ch->partid, ch->number);16001600+16011601+ ch->func(ch->reason, ch->partid, ch->number, NULL, ch->key);16021602+16031603+ dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "16041604+ "channel=%d\n", ch->reason, ch->partid, ch->number);16051605+ }16061606+}16071607+16081608+16091609+/*16101610+ * Wait for a message entry to become available for the specified channel,16111611+ * but don't wait any longer than 1 jiffy.16121612+ */16131613+static enum xpc_retval16141614+xpc_allocate_msg_wait(struct xpc_channel *ch)16151615+{16161616+ enum xpc_retval ret;16171617+16181618+16191619+ if (ch->flags & XPC_C_DISCONNECTING) {16201620+ DBUG_ON(ch->reason == xpcInterrupted); // >>> Is this true?16211621+ return ch->reason;16221622+ }16231623+16241624+ atomic_inc(&ch->n_on_msg_allocate_wq);16251625+ ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1);16261626+ atomic_dec(&ch->n_on_msg_allocate_wq);16271627+16281628+ if (ch->flags & XPC_C_DISCONNECTING) {16291629+ ret = ch->reason;16301630+ DBUG_ON(ch->reason == xpcInterrupted); // >>> Is this true?16311631+ } else if (ret == 0) {16321632+ ret = xpcTimeout;16331633+ } else {16341634+ ret = xpcInterrupted;16351635+ }16361636+16371637+ return ret;16381638+}16391639+16401640+16411641+/*16421642+ * Allocate an entry for a message from the message queue associated with the16431643+ * specified channel.16441644+ */16451645+static enum xpc_retval16461646+xpc_allocate_msg(struct xpc_channel *ch, u32 flags,16471647+ struct xpc_msg **address_of_msg)16481648+{16491649+ struct xpc_msg *msg;16501650+ enum xpc_retval ret;16511651+ s64 put;16521652+16531653+16541654+ /* this reference will be dropped in xpc_send_msg() */16551655+ xpc_msgqueue_ref(ch);16561656+16571657+ if (ch->flags & XPC_C_DISCONNECTING) {16581658+ xpc_msgqueue_deref(ch);16591659+ return ch->reason;16601660+ }16611661+ if (!(ch->flags & XPC_C_CONNECTED)) {16621662+ xpc_msgqueue_deref(ch);16631663+ return xpcNotConnected;16641664+ }16651665+16661666+16671667+ /*16681668+ * Get the next available message entry from the local message queue.16691669+ * If none are available, we'll make sure that we grab the latest16701670+ * GP values.16711671+ */16721672+ ret = xpcTimeout;16731673+16741674+ while (1) {16751675+16761676+ put = (volatile s64) ch->w_local_GP.put;16771677+ if (put - (volatile s64) ch->w_remote_GP.get <16781678+ ch->local_nentries) {16791679+16801680+ /* There are available message entries. We need to try16811681+ * to secure one for ourselves. We'll do this by trying16821682+ * to increment w_local_GP.put as long as someone else16831683+ * doesn't beat us to it. If they do, we'll have to16841684+ * try again.16851685+ */16861686+ if (cmpxchg(&ch->w_local_GP.put, put, put + 1) ==16871687+ put) {16881688+ /* we got the entry referenced by put */16891689+ break;16901690+ }16911691+ continue; /* try again */16921692+ }16931693+16941694+16951695+ /*16961696+ * There aren't any available msg entries at this time.16971697+ *16981698+ * In waiting for a message entry to become available,16991699+ * we set a timeout in case the other side is not17001700+ * sending completion IPIs. This lets us fake an IPI17011701+ * that will cause the IPI handler to fetch the latest17021702+ * GP values as if an IPI was sent by the other side.17031703+ */17041704+ if (ret == xpcTimeout) {17051705+ xpc_IPI_send_local_msgrequest(ch);17061706+ }17071707+17081708+ if (flags & XPC_NOWAIT) {17091709+ xpc_msgqueue_deref(ch);17101710+ return xpcNoWait;17111711+ }17121712+17131713+ ret = xpc_allocate_msg_wait(ch);17141714+ if (ret != xpcInterrupted && ret != xpcTimeout) {17151715+ xpc_msgqueue_deref(ch);17161716+ return ret;17171717+ }17181718+ }17191719+17201720+17211721+ /* get the message's address and initialize it */17221722+ msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +17231723+ (put % ch->local_nentries) * ch->msg_size);17241724+17251725+17261726+ DBUG_ON(msg->flags != 0);17271727+ msg->number = put;17281728+17291729+ dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "17301730+ "msg_number=%ld, partid=%d, channel=%d\n", put + 1,17311731+ (void *) msg, msg->number, ch->partid, ch->number);17321732+17331733+ *address_of_msg = msg;17341734+17351735+ return xpcSuccess;17361736+}17371737+17381738+17391739+/*17401740+ * Allocate an entry for a message from the message queue associated with the17411741+ * specified channel. NOTE that this routine can sleep waiting for a message17421742+ * entry to become available. To not sleep, pass in the XPC_NOWAIT flag.17431743+ *17441744+ * Arguments:17451745+ *17461746+ * partid - ID of partition to which the channel is connected.17471747+ * ch_number - channel #.17481748+ * flags - see xpc.h for valid flags.17491749+ * payload - address of the allocated payload area pointer (filled in on17501750+ * return) in which the user-defined message is constructed.17511751+ */17521752+enum xpc_retval17531753+xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)17541754+{17551755+ struct xpc_partition *part = &xpc_partitions[partid];17561756+ enum xpc_retval ret = xpcUnknownReason;17571757+ struct xpc_msg *msg;17581758+17591759+17601760+ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);17611761+ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);17621762+17631763+ *payload = NULL;17641764+17651765+ if (xpc_part_ref(part)) {17661766+ ret = xpc_allocate_msg(&part->channels[ch_number], flags, &msg);17671767+ xpc_part_deref(part);17681768+17691769+ if (msg != NULL) {17701770+ *payload = &msg->payload;17711771+ }17721772+ }17731773+17741774+ return ret;17751775+}17761776+17771777+17781778+/*17791779+ * Now we actually send the messages that are ready to be sent by advancing17801780+ * the local message queue's Put value and then send an IPI to the recipient17811781+ * partition.17821782+ */17831783+static void17841784+xpc_send_msgs(struct xpc_channel *ch, s64 initial_put)17851785+{17861786+ struct xpc_msg *msg;17871787+ s64 put = initial_put + 1;17881788+ int send_IPI = 0;17891789+17901790+17911791+ while (1) {17921792+17931793+ while (1) {17941794+ if (put == (volatile s64) ch->w_local_GP.put) {17951795+ break;17961796+ }17971797+17981798+ msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +17991799+ (put % ch->local_nentries) * ch->msg_size);18001800+18011801+ if (!(msg->flags & XPC_M_READY)) {18021802+ break;18031803+ }18041804+18051805+ put++;18061806+ }18071807+18081808+ if (put == initial_put) {18091809+ /* nothing's changed */18101810+ break;18111811+ }18121812+18131813+ if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=18141814+ initial_put) {18151815+ /* someone else beat us to it */18161816+ DBUG_ON((volatile s64) ch->local_GP->put < initial_put);18171817+ break;18181818+ }18191819+18201820+ /* we just set the new value of local_GP->put */18211821+18221822+ dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "18231823+ "channel=%d\n", put, ch->partid, ch->number);18241824+18251825+ send_IPI = 1;18261826+18271827+ /*18281828+ * We need to ensure that the message referenced by18291829+ * local_GP->put is not XPC_M_READY or that local_GP->put18301830+ * equals w_local_GP.put, so we'll go have a look.18311831+ */18321832+ initial_put = put;18331833+ }18341834+18351835+ if (send_IPI) {18361836+ xpc_IPI_send_msgrequest(ch);18371837+ }18381838+}18391839+18401840+18411841+/*18421842+ * Common code that does the actual sending of the message by advancing the18431843+ * local message queue's Put value and sends an IPI to the partition the18441844+ * message is being sent to.18451845+ */18461846+static enum xpc_retval18471847+xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,18481848+ xpc_notify_func func, void *key)18491849+{18501850+ enum xpc_retval ret = xpcSuccess;18511851+ struct xpc_notify *notify = NULL; // >>> to keep the compiler happy!!18521852+ s64 put, msg_number = msg->number;18531853+18541854+18551855+ DBUG_ON(notify_type == XPC_N_CALL && func == NULL);18561856+ DBUG_ON((((u64) msg - (u64) ch->local_msgqueue) / ch->msg_size) !=18571857+ msg_number % ch->local_nentries);18581858+ DBUG_ON(msg->flags & XPC_M_READY);18591859+18601860+ if (ch->flags & XPC_C_DISCONNECTING) {18611861+ /* drop the reference grabbed in xpc_allocate_msg() */18621862+ xpc_msgqueue_deref(ch);18631863+ return ch->reason;18641864+ }18651865+18661866+ if (notify_type != 0) {18671867+ /*18681868+ * Tell the remote side to send an ACK interrupt when the18691869+ * message has been delivered.18701870+ */18711871+ msg->flags |= XPC_M_INTERRUPT;18721872+18731873+ atomic_inc(&ch->n_to_notify);18741874+18751875+ notify = &ch->notify_queue[msg_number % ch->local_nentries];18761876+ notify->func = func;18771877+ notify->key = key;18781878+ (volatile u8) notify->type = notify_type;18791879+18801880+ // >>> is a mb() needed here?18811881+18821882+ if (ch->flags & XPC_C_DISCONNECTING) {18831883+ /*18841884+ * An error occurred between our last error check and18851885+ * this one. We will try to clear the type field from18861886+ * the notify entry. If we succeed then18871887+ * xpc_disconnect_channel() didn't already process18881888+ * the notify entry.18891889+ */18901890+ if (cmpxchg(¬ify->type, notify_type, 0) ==18911891+ notify_type) {18921892+ atomic_dec(&ch->n_to_notify);18931893+ ret = ch->reason;18941894+ }18951895+18961896+ /* drop the reference grabbed in xpc_allocate_msg() */18971897+ xpc_msgqueue_deref(ch);18981898+ return ret;18991899+ }19001900+ }19011901+19021902+ msg->flags |= XPC_M_READY;19031903+19041904+ /*19051905+ * The preceding store of msg->flags must occur before the following19061906+ * load of ch->local_GP->put.19071907+ */19081908+ mb();19091909+19101910+ /* see if the message is next in line to be sent, if so send it */19111911+19121912+ put = ch->local_GP->put;19131913+ if (put == msg_number) {19141914+ xpc_send_msgs(ch, put);19151915+ }19161916+19171917+ /* drop the reference grabbed in xpc_allocate_msg() */19181918+ xpc_msgqueue_deref(ch);19191919+ return ret;19201920+}19211921+19221922+19231923+/*19241924+ * Send a message previously allocated using xpc_initiate_allocate() on the19251925+ * specified channel connected to the specified partition.19261926+ *19271927+ * This routine will not wait for the message to be received, nor will19281928+ * notification be given when it does happen. Once this routine has returned19291929+ * the message entry allocated via xpc_initiate_allocate() is no longer19301930+ * accessable to the caller.19311931+ *19321932+ * This routine, although called by users, does not call xpc_part_ref() to19331933+ * ensure that the partition infrastructure is in place. It relies on the19341934+ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().19351935+ *19361936+ * Arguments:19371937+ *19381938+ * partid - ID of partition to which the channel is connected.19391939+ * ch_number - channel # to send message on.19401940+ * payload - pointer to the payload area allocated via19411941+ * xpc_initiate_allocate().19421942+ */19431943+enum xpc_retval19441944+xpc_initiate_send(partid_t partid, int ch_number, void *payload)19451945+{19461946+ struct xpc_partition *part = &xpc_partitions[partid];19471947+ struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);19481948+ enum xpc_retval ret;19491949+19501950+19511951+ dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,19521952+ partid, ch_number);19531953+19541954+ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);19551955+ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);19561956+ DBUG_ON(msg == NULL);19571957+19581958+ ret = xpc_send_msg(&part->channels[ch_number], msg, 0, NULL, NULL);19591959+19601960+ return ret;19611961+}19621962+19631963+19641964+/*19651965+ * Send a message previously allocated using xpc_initiate_allocate on the19661966+ * specified channel connected to the specified partition.19671967+ *19681968+ * This routine will not wait for the message to be sent. Once this routine19691969+ * has returned the message entry allocated via xpc_initiate_allocate() is no19701970+ * longer accessable to the caller.19711971+ *19721972+ * Once the remote end of the channel has received the message, the function19731973+ * passed as an argument to xpc_initiate_send_notify() will be called. This19741974+ * allows the sender to free up or re-use any buffers referenced by the19751975+ * message, but does NOT mean the message has been processed at the remote19761976+ * end by a receiver.19771977+ *19781978+ * If this routine returns an error, the caller's function will NOT be called.19791979+ *19801980+ * This routine, although called by users, does not call xpc_part_ref() to19811981+ * ensure that the partition infrastructure is in place. It relies on the19821982+ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().19831983+ *19841984+ * Arguments:19851985+ *19861986+ * partid - ID of partition to which the channel is connected.19871987+ * ch_number - channel # to send message on.19881988+ * payload - pointer to the payload area allocated via19891989+ * xpc_initiate_allocate().19901990+ * func - function to call with asynchronous notification of message19911991+ * receipt. THIS FUNCTION MUST BE NON-BLOCKING.19921992+ * key - user-defined key to be passed to the function when it's called.19931993+ */19941994+enum xpc_retval19951995+xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload,19961996+ xpc_notify_func func, void *key)19971997+{19981998+ struct xpc_partition *part = &xpc_partitions[partid];19991999+ struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);20002000+ enum xpc_retval ret;20012001+20022002+20032003+ dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,20042004+ partid, ch_number);20052005+20062006+ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);20072007+ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);20082008+ DBUG_ON(msg == NULL);20092009+ DBUG_ON(func == NULL);20102010+20112011+ ret = xpc_send_msg(&part->channels[ch_number], msg, XPC_N_CALL,20122012+ func, key);20132013+ return ret;20142014+}20152015+20162016+20172017+static struct xpc_msg *20182018+xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)20192019+{20202020+ struct xpc_partition *part = &xpc_partitions[ch->partid];20212021+ struct xpc_msg *remote_msg, *msg;20222022+ u32 msg_index, nmsgs;20232023+ u64 msg_offset;20242024+ enum xpc_retval ret;20252025+20262026+20272027+ if (down_interruptible(&ch->msg_to_pull_sema) != 0) {20282028+ /* we were interrupted by a signal */20292029+ return NULL;20302030+ }20312031+20322032+ while (get >= ch->next_msg_to_pull) {20332033+20342034+ /* pull as many messages as are ready and able to be pulled */20352035+20362036+ msg_index = ch->next_msg_to_pull % ch->remote_nentries;20372037+20382038+ DBUG_ON(ch->next_msg_to_pull >=20392039+ (volatile s64) ch->w_remote_GP.put);20402040+ nmsgs = (volatile s64) ch->w_remote_GP.put -20412041+ ch->next_msg_to_pull;20422042+ if (msg_index + nmsgs > ch->remote_nentries) {20432043+ /* ignore the ones that wrap the msg queue for now */20442044+ nmsgs = ch->remote_nentries - msg_index;20452045+ }20462046+20472047+ msg_offset = msg_index * ch->msg_size;20482048+ msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +20492049+ msg_offset);20502050+ remote_msg = (struct xpc_msg *) (ch->remote_msgqueue_pa +20512051+ msg_offset);20522052+20532053+ if ((ret = xpc_pull_remote_cachelines(part, msg, remote_msg,20542054+ nmsgs * ch->msg_size)) != xpcSuccess) {20552055+20562056+ dev_dbg(xpc_chan, "failed to pull %d msgs starting with"20572057+ " msg %ld from partition %d, channel=%d, "20582058+ "ret=%d\n", nmsgs, ch->next_msg_to_pull,20592059+ ch->partid, ch->number, ret);20602060+20612061+ XPC_DEACTIVATE_PARTITION(part, ret);20622062+20632063+ up(&ch->msg_to_pull_sema);20642064+ return NULL;20652065+ }20662066+20672067+ mb(); /* >>> this may not be needed, we're not sure */20682068+20692069+ ch->next_msg_to_pull += nmsgs;20702070+ }20712071+20722072+ up(&ch->msg_to_pull_sema);20732073+20742074+ /* return the message we were looking for */20752075+ msg_offset = (get % ch->remote_nentries) * ch->msg_size;20762076+ msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue + msg_offset);20772077+20782078+ return msg;20792079+}20802080+20812081+20822082+/*20832083+ * Get a message to be delivered.20842084+ */20852085+static struct xpc_msg *20862086+xpc_get_deliverable_msg(struct xpc_channel *ch)20872087+{20882088+ struct xpc_msg *msg = NULL;20892089+ s64 get;20902090+20912091+20922092+ do {20932093+ if ((volatile u32) ch->flags & XPC_C_DISCONNECTING) {20942094+ break;20952095+ }20962096+20972097+ get = (volatile s64) ch->w_local_GP.get;20982098+ if (get == (volatile s64) ch->w_remote_GP.put) {20992099+ break;21002100+ }21012101+21022102+ /* There are messages waiting to be pulled and delivered.21032103+ * We need to try to secure one for ourselves. We'll do this21042104+ * by trying to increment w_local_GP.get and hope that no one21052105+ * else beats us to it. If they do, we'll we'll simply have21062106+ * to try again for the next one.21072107+ */21082108+21092109+ if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {21102110+ /* we got the entry referenced by get */21112111+21122112+ dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "21132113+ "partid=%d, channel=%d\n", get + 1,21142114+ ch->partid, ch->number);21152115+21162116+ /* pull the message from the remote partition */21172117+21182118+ msg = xpc_pull_remote_msg(ch, get);21192119+21202120+ DBUG_ON(msg != NULL && msg->number != get);21212121+ DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));21222122+ DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));21232123+21242124+ break;21252125+ }21262126+21272127+ } while (1);21282128+21292129+ return msg;21302130+}21312131+21322132+21332133+/*21342134+ * Deliver a message to its intended recipient.21352135+ */21362136+void21372137+xpc_deliver_msg(struct xpc_channel *ch)21382138+{21392139+ struct xpc_msg *msg;21402140+21412141+21422142+ if ((msg = xpc_get_deliverable_msg(ch)) != NULL) {21432143+21442144+ /*21452145+ * This ref is taken to protect the payload itself from being21462146+ * freed before the user is finished with it, which the user21472147+ * indicates by calling xpc_initiate_received().21482148+ */21492149+ xpc_msgqueue_ref(ch);21502150+21512151+ atomic_inc(&ch->kthreads_active);21522152+21532153+ if (ch->func != NULL) {21542154+ dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, "21552155+ "msg_number=%ld, partid=%d, channel=%d\n",21562156+ (void *) msg, msg->number, ch->partid,21572157+ ch->number);21582158+21592159+ /* deliver the message to its intended recipient */21602160+ ch->func(xpcMsgReceived, ch->partid, ch->number,21612161+ &msg->payload, ch->key);21622162+21632163+ dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, "21642164+ "msg_number=%ld, partid=%d, channel=%d\n",21652165+ (void *) msg, msg->number, ch->partid,21662166+ ch->number);21672167+ }21682168+21692169+ atomic_dec(&ch->kthreads_active);21702170+ }21712171+}21722172+21732173+21742174+/*21752175+ * Now we actually acknowledge the messages that have been delivered and ack'd21762176+ * by advancing the cached remote message queue's Get value and if requested21772177+ * send an IPI to the message sender's partition.21782178+ */21792179+static void21802180+xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)21812181+{21822182+ struct xpc_msg *msg;21832183+ s64 get = initial_get + 1;21842184+ int send_IPI = 0;21852185+21862186+21872187+ while (1) {21882188+21892189+ while (1) {21902190+ if (get == (volatile s64) ch->w_local_GP.get) {21912191+ break;21922192+ }21932193+21942194+ msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +21952195+ (get % ch->remote_nentries) * ch->msg_size);21962196+21972197+ if (!(msg->flags & XPC_M_DONE)) {21982198+ break;21992199+ }22002200+22012201+ msg_flags |= msg->flags;22022202+ get++;22032203+ }22042204+22052205+ if (get == initial_get) {22062206+ /* nothing's changed */22072207+ break;22082208+ }22092209+22102210+ if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=22112211+ initial_get) {22122212+ /* someone else beat us to it */22132213+ DBUG_ON((volatile s64) ch->local_GP->get <=22142214+ initial_get);22152215+ break;22162216+ }22172217+22182218+ /* we just set the new value of local_GP->get */22192219+22202220+ dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "22212221+ "channel=%d\n", get, ch->partid, ch->number);22222222+22232223+ send_IPI = (msg_flags & XPC_M_INTERRUPT);22242224+22252225+ /*22262226+ * We need to ensure that the message referenced by22272227+ * local_GP->get is not XPC_M_DONE or that local_GP->get22282228+ * equals w_local_GP.get, so we'll go have a look.22292229+ */22302230+ initial_get = get;22312231+ }22322232+22332233+ if (send_IPI) {22342234+ xpc_IPI_send_msgrequest(ch);22352235+ }22362236+}22372237+22382238+22392239+/*22402240+ * Acknowledge receipt of a delivered message.22412241+ *22422242+ * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition22432243+ * that sent the message.22442244+ *22452245+ * This function, although called by users, does not call xpc_part_ref() to22462246+ * ensure that the partition infrastructure is in place. It relies on the22472247+ * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg().22482248+ *22492249+ * Arguments:22502250+ *22512251+ * partid - ID of partition to which the channel is connected.22522252+ * ch_number - channel # message received on.22532253+ * payload - pointer to the payload area allocated via22542254+ * xpc_initiate_allocate().22552255+ */22562256+void22572257+xpc_initiate_received(partid_t partid, int ch_number, void *payload)22582258+{22592259+ struct xpc_partition *part = &xpc_partitions[partid];22602260+ struct xpc_channel *ch;22612261+ struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);22622262+ s64 get, msg_number = msg->number;22632263+22642264+22652265+ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);22662266+ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);22672267+22682268+ ch = &part->channels[ch_number];22692269+22702270+ dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",22712271+ (void *) msg, msg_number, ch->partid, ch->number);22722272+22732273+ DBUG_ON((((u64) msg - (u64) ch->remote_msgqueue) / ch->msg_size) !=22742274+ msg_number % ch->remote_nentries);22752275+ DBUG_ON(msg->flags & XPC_M_DONE);22762276+22772277+ msg->flags |= XPC_M_DONE;22782278+22792279+ /*22802280+ * The preceding store of msg->flags must occur before the following22812281+ * load of ch->local_GP->get.22822282+ */22832283+ mb();22842284+22852285+ /*22862286+ * See if this message is next in line to be acknowledged as having22872287+ * been delivered.22882288+ */22892289+ get = ch->local_GP->get;22902290+ if (get == msg_number) {22912291+ xpc_acknowledge_msgs(ch, get, msg->flags);22922292+ }22932293+22942294+ /* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg() */22952295+ xpc_msgqueue_deref(ch);22962296+}22972297+
+1064
arch/ia64/sn/kernel/xpc_main.c
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.77+ */88+99+1010+/*1111+ * Cross Partition Communication (XPC) support - standard version.1212+ *1313+ * XPC provides a message passing capability that crosses partition1414+ * boundaries. This module is made up of two parts:1515+ *1616+ * partition This part detects the presence/absence of other1717+ * partitions. It provides a heartbeat and monitors1818+ * the heartbeats of other partitions.1919+ *2020+ * channel This part manages the channels and sends/receives2121+ * messages across them to/from other partitions.2222+ *2323+ * There are a couple of additional functions residing in XP, which2424+ * provide an interface to XPC for its users.2525+ *2626+ *2727+ * Caveats:2828+ *2929+ * . We currently have no way to determine which nasid an IPI came3030+ * from. Thus, xpc_IPI_send() does a remote AMO write followed by3131+ * an IPI. The AMO indicates where data is to be pulled from, so3232+ * after the IPI arrives, the remote partition checks the AMO word.3333+ * The IPI can actually arrive before the AMO however, so other code3434+ * must periodically check for this case. Also, remote AMO operations3535+ * do not reliably time out. Thus we do a remote PIO read solely to3636+ * know whether the remote partition is down and whether we should3737+ * stop sending IPIs to it. This remote PIO read operation is set up3838+ * in a special nofault region so SAL knows to ignore (and cleanup)3939+ * any errors due to the remote AMO write, PIO read, and/or PIO4040+ * write operations.4141+ *4242+ * If/when new hardware solves this IPI problem, we should abandon4343+ * the current approach.4444+ *4545+ */4646+4747+4848+#include <linux/kernel.h>4949+#include <linux/module.h>5050+#include <linux/init.h>5151+#include <linux/sched.h>5252+#include <linux/syscalls.h>5353+#include <linux/cache.h>5454+#include <linux/interrupt.h>5555+#include <linux/slab.h>5656+#include <asm/sn/intr.h>5757+#include <asm/sn/sn_sal.h>5858+#include <asm/uaccess.h>5959+#include "xpc.h"6060+6161+6262+/* define two XPC debug device structures to be used with dev_dbg() et al */6363+6464+struct device_driver xpc_dbg_name = {6565+ .name = "xpc"6666+};6767+6868+struct device xpc_part_dbg_subname = {6969+ .bus_id = {0}, /* set to "part" at xpc_init() time */7070+ .driver = &xpc_dbg_name7171+};7272+7373+struct device xpc_chan_dbg_subname = {7474+ .bus_id = {0}, /* set to "chan" at xpc_init() time */7575+ .driver = &xpc_dbg_name7676+};7777+7878+struct device *xpc_part = &xpc_part_dbg_subname;7979+struct device *xpc_chan = &xpc_chan_dbg_subname;8080+8181+8282+/* systune related variables for /proc/sys directories */8383+8484+static int xpc_hb_min = 1;8585+static int xpc_hb_max = 10;8686+8787+static int xpc_hb_check_min = 10;8888+static int xpc_hb_check_max = 120;8989+9090+static ctl_table xpc_sys_xpc_hb_dir[] = {9191+ {9292+ 1,9393+ "hb_interval",9494+ &xpc_hb_interval,9595+ sizeof(int),9696+ 0644,9797+ NULL,9898+ &proc_dointvec_minmax,9999+ &sysctl_intvec,100100+ NULL,101101+ &xpc_hb_min, &xpc_hb_max102102+ },103103+ {104104+ 2,105105+ "hb_check_interval",106106+ &xpc_hb_check_interval,107107+ sizeof(int),108108+ 0644,109109+ NULL,110110+ &proc_dointvec_minmax,111111+ &sysctl_intvec,112112+ NULL,113113+ &xpc_hb_check_min, &xpc_hb_check_max114114+ },115115+ {0}116116+};117117+static ctl_table xpc_sys_xpc_dir[] = {118118+ {119119+ 1,120120+ "hb",121121+ NULL,122122+ 0,123123+ 0555,124124+ xpc_sys_xpc_hb_dir125125+ },126126+ {0}127127+};128128+static ctl_table xpc_sys_dir[] = {129129+ {130130+ 1,131131+ "xpc",132132+ NULL,133133+ 0,134134+ 0555,135135+ xpc_sys_xpc_dir136136+ },137137+ {0}138138+};139139+static struct ctl_table_header *xpc_sysctl;140140+141141+142142+/* #of IRQs received */143143+static atomic_t xpc_act_IRQ_rcvd;144144+145145+/* IRQ handler notifies this wait queue on receipt of an IRQ */146146+static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);147147+148148+static unsigned long xpc_hb_check_timeout;149149+150150+/* xpc_hb_checker thread exited notification */151151+static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);152152+153153+/* xpc_discovery thread exited notification */154154+static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);155155+156156+157157+static struct timer_list xpc_hb_timer;158158+159159+160160+static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);161161+162162+163163+/*164164+ * Notify the heartbeat check thread that an IRQ has been received.165165+ */166166+static irqreturn_t167167+xpc_act_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)168168+{169169+ atomic_inc(&xpc_act_IRQ_rcvd);170170+ wake_up_interruptible(&xpc_act_IRQ_wq);171171+ return IRQ_HANDLED;172172+}173173+174174+175175+/*176176+ * Timer to produce the heartbeat. The timer structures function is177177+ * already set when this is initially called. A tunable is used to178178+ * specify when the next timeout should occur.179179+ */180180+static void181181+xpc_hb_beater(unsigned long dummy)182182+{183183+ xpc_vars->heartbeat++;184184+185185+ if (jiffies >= xpc_hb_check_timeout) {186186+ wake_up_interruptible(&xpc_act_IRQ_wq);187187+ }188188+189189+ xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);190190+ add_timer(&xpc_hb_timer);191191+}192192+193193+194194+/*195195+ * This thread is responsible for nearly all of the partition196196+ * activation/deactivation.197197+ */198198+static int199199+xpc_hb_checker(void *ignore)200200+{201201+ int last_IRQ_count = 0;202202+ int new_IRQ_count;203203+ int force_IRQ=0;204204+205205+206206+ /* this thread was marked active by xpc_hb_init() */207207+208208+ daemonize(XPC_HB_CHECK_THREAD_NAME);209209+210210+ set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));211211+212212+ xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);213213+214214+ while (!(volatile int) xpc_exiting) {215215+216216+ /* wait for IRQ or timeout */217217+ (void) wait_event_interruptible(xpc_act_IRQ_wq,218218+ (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||219219+ jiffies >= xpc_hb_check_timeout ||220220+ (volatile int) xpc_exiting));221221+222222+ dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "223223+ "been received\n",224224+ (int) (xpc_hb_check_timeout - jiffies),225225+ atomic_read(&xpc_act_IRQ_rcvd) - last_IRQ_count);226226+227227+228228+ /* checking of remote heartbeats is skewed by IRQ handling */229229+ if (jiffies >= xpc_hb_check_timeout) {230230+ dev_dbg(xpc_part, "checking remote heartbeats\n");231231+ xpc_check_remote_hb();232232+233233+ /*234234+ * We need to periodically recheck to ensure no235235+ * IPI/AMO pairs have been missed. That check236236+ * must always reset xpc_hb_check_timeout.237237+ */238238+ force_IRQ = 1;239239+ }240240+241241+242242+ new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);243243+ if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {244244+ force_IRQ = 0;245245+246246+ dev_dbg(xpc_part, "found an IRQ to process; will be "247247+ "resetting xpc_hb_check_timeout\n");248248+249249+ last_IRQ_count += xpc_identify_act_IRQ_sender();250250+ if (last_IRQ_count < new_IRQ_count) {251251+ /* retry once to help avoid missing AMO */252252+ (void) xpc_identify_act_IRQ_sender();253253+ }254254+ last_IRQ_count = new_IRQ_count;255255+256256+ xpc_hb_check_timeout = jiffies +257257+ (xpc_hb_check_interval * HZ);258258+ }259259+ }260260+261261+ dev_dbg(xpc_part, "heartbeat checker is exiting\n");262262+263263+264264+ /* mark this thread as inactive */265265+ up(&xpc_hb_checker_exited);266266+ return 0;267267+}268268+269269+270270+/*271271+ * This thread will attempt to discover other partitions to activate272272+ * based on info provided by SAL. This new thread is short lived and273273+ * will exit once discovery is complete.274274+ */275275+static int276276+xpc_initiate_discovery(void *ignore)277277+{278278+ daemonize(XPC_DISCOVERY_THREAD_NAME);279279+280280+ xpc_discovery();281281+282282+ dev_dbg(xpc_part, "discovery thread is exiting\n");283283+284284+ /* mark this thread as inactive */285285+ up(&xpc_discovery_exited);286286+ return 0;287287+}288288+289289+290290+/*291291+ * Establish first contact with the remote partititon. This involves pulling292292+ * the XPC per partition variables from the remote partition and waiting for293293+ * the remote partition to pull ours.294294+ */295295+static enum xpc_retval296296+xpc_make_first_contact(struct xpc_partition *part)297297+{298298+ enum xpc_retval ret;299299+300300+301301+ while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) {302302+ if (ret != xpcRetry) {303303+ XPC_DEACTIVATE_PARTITION(part, ret);304304+ return ret;305305+ }306306+307307+ dev_dbg(xpc_chan, "waiting to make first contact with "308308+ "partition %d\n", XPC_PARTID(part));309309+310310+ /* wait a 1/4 of a second or so */311311+ set_current_state(TASK_INTERRUPTIBLE);312312+ (void) schedule_timeout(0.25 * HZ);313313+314314+ if (part->act_state == XPC_P_DEACTIVATING) {315315+ return part->reason;316316+ }317317+ }318318+319319+ return xpc_mark_partition_active(part);320320+}321321+322322+323323+/*324324+ * The first kthread assigned to a newly activated partition is the one325325+ * created by XPC HB with which it calls xpc_partition_up(). XPC hangs on to326326+ * that kthread until the partition is brought down, at which time that kthread327327+ * returns back to XPC HB. (The return of that kthread will signify to XPC HB328328+ * that XPC has dismantled all communication infrastructure for the associated329329+ * partition.) This kthread becomes the channel manager for that partition.330330+ *331331+ * Each active partition has a channel manager, who, besides connecting and332332+ * disconnecting channels, will ensure that each of the partition's connected333333+ * channels has the required number of assigned kthreads to get the work done.334334+ */335335+static void336336+xpc_channel_mgr(struct xpc_partition *part)337337+{338338+ while (part->act_state != XPC_P_DEACTIVATING ||339339+ atomic_read(&part->nchannels_active) > 0) {340340+341341+ xpc_process_channel_activity(part);342342+343343+344344+ /*345345+ * Wait until we've been requested to activate kthreads or346346+ * all of the channel's message queues have been torn down or347347+ * a signal is pending.348348+ *349349+ * The channel_mgr_requests is set to 1 after being awakened,350350+ * This is done to prevent the channel mgr from making one pass351351+ * through the loop for each request, since he will352352+ * be servicing all the requests in one pass. The reason it's353353+ * set to 1 instead of 0 is so that other kthreads will know354354+ * that the channel mgr is running and won't bother trying to355355+ * wake him up.356356+ */357357+ atomic_dec(&part->channel_mgr_requests);358358+ (void) wait_event_interruptible(part->channel_mgr_wq,359359+ (atomic_read(&part->channel_mgr_requests) > 0 ||360360+ (volatile u64) part->local_IPI_amo != 0 ||361361+ ((volatile u8) part->act_state ==362362+ XPC_P_DEACTIVATING &&363363+ atomic_read(&part->nchannels_active) == 0)));364364+ atomic_set(&part->channel_mgr_requests, 1);365365+366366+ // >>> Does it need to wakeup periodically as well? In case we367367+ // >>> miscalculated the #of kthreads to wakeup or create?368368+ }369369+}370370+371371+372372+/*373373+ * When XPC HB determines that a partition has come up, it will create a new374374+ * kthread and that kthread will call this function to attempt to set up the375375+ * basic infrastructure used for Cross Partition Communication with the newly376376+ * upped partition.377377+ *378378+ * The kthread that was created by XPC HB and which setup the XPC379379+ * infrastructure will remain assigned to the partition until the partition380380+ * goes down. At which time the kthread will teardown the XPC infrastructure381381+ * and then exit.382382+ *383383+ * XPC HB will put the remote partition's XPC per partition specific variables384384+ * physical address into xpc_partitions[partid].remote_vars_part_pa prior to385385+ * calling xpc_partition_up().386386+ */387387+static void388388+xpc_partition_up(struct xpc_partition *part)389389+{390390+ DBUG_ON(part->channels != NULL);391391+392392+ dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part));393393+394394+ if (xpc_setup_infrastructure(part) != xpcSuccess) {395395+ return;396396+ }397397+398398+ /*399399+ * The kthread that XPC HB called us with will become the400400+ * channel manager for this partition. It will not return401401+ * back to XPC HB until the partition's XPC infrastructure402402+ * has been dismantled.403403+ */404404+405405+ (void) xpc_part_ref(part); /* this will always succeed */406406+407407+ if (xpc_make_first_contact(part) == xpcSuccess) {408408+ xpc_channel_mgr(part);409409+ }410410+411411+ xpc_part_deref(part);412412+413413+ xpc_teardown_infrastructure(part);414414+}415415+416416+417417+static int418418+xpc_activating(void *__partid)419419+{420420+ partid_t partid = (u64) __partid;421421+ struct xpc_partition *part = &xpc_partitions[partid];422422+ unsigned long irq_flags;423423+ struct sched_param param = { sched_priority: MAX_USER_RT_PRIO - 1 };424424+ int ret;425425+426426+427427+ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);428428+429429+ spin_lock_irqsave(&part->act_lock, irq_flags);430430+431431+ if (part->act_state == XPC_P_DEACTIVATING) {432432+ part->act_state = XPC_P_INACTIVE;433433+ spin_unlock_irqrestore(&part->act_lock, irq_flags);434434+ part->remote_rp_pa = 0;435435+ return 0;436436+ }437437+438438+ /* indicate the thread is activating */439439+ DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ);440440+ part->act_state = XPC_P_ACTIVATING;441441+442442+ XPC_SET_REASON(part, 0, 0);443443+ spin_unlock_irqrestore(&part->act_lock, irq_flags);444444+445445+ dev_dbg(xpc_part, "bringing partition %d up\n", partid);446446+447447+ daemonize("xpc%02d", partid);448448+449449+ /*450450+ * This thread needs to run at a realtime priority to prevent a451451+ * significant performance degradation.452452+ */453453+ ret = sched_setscheduler(current, SCHED_FIFO, ¶m);454454+ if (ret != 0) {455455+ dev_warn(xpc_part, "unable to set pid %d to a realtime "456456+ "priority, ret=%d\n", current->pid, ret);457457+ }458458+459459+ /* allow this thread and its children to run on any CPU */460460+ set_cpus_allowed(current, CPU_MASK_ALL);461461+462462+ /*463463+ * Register the remote partition's AMOs with SAL so it can handle464464+ * and cleanup errors within that address range should the remote465465+ * partition go down. We don't unregister this range because it is466466+ * difficult to tell when outstanding writes to the remote partition467467+ * are finished and thus when it is safe to unregister. This should468468+ * not result in wasted space in the SAL xp_addr_region table because469469+ * we should get the same page for remote_amos_page_pa after module470470+ * reloads and system reboots.471471+ */472472+ if (sn_register_xp_addr_region(part->remote_amos_page_pa,473473+ PAGE_SIZE, 1) < 0) {474474+ dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "475475+ "xp_addr region\n", partid);476476+477477+ spin_lock_irqsave(&part->act_lock, irq_flags);478478+ part->act_state = XPC_P_INACTIVE;479479+ XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__);480480+ spin_unlock_irqrestore(&part->act_lock, irq_flags);481481+ part->remote_rp_pa = 0;482482+ return 0;483483+ }484484+485485+ XPC_ALLOW_HB(partid, xpc_vars);486486+ xpc_IPI_send_activated(part);487487+488488+489489+ /*490490+ * xpc_partition_up() holds this thread and marks this partition as491491+ * XPC_P_ACTIVE by calling xpc_hb_mark_active().492492+ */493493+ (void) xpc_partition_up(part);494494+495495+ xpc_mark_partition_inactive(part);496496+497497+ if (part->reason == xpcReactivating) {498498+ /* interrupting ourselves results in activating partition */499499+ xpc_IPI_send_reactivate(part);500500+ }501501+502502+ return 0;503503+}504504+505505+506506+void507507+xpc_activate_partition(struct xpc_partition *part)508508+{509509+ partid_t partid = XPC_PARTID(part);510510+ unsigned long irq_flags;511511+ pid_t pid;512512+513513+514514+ spin_lock_irqsave(&part->act_lock, irq_flags);515515+516516+ pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);517517+518518+ DBUG_ON(part->act_state != XPC_P_INACTIVE);519519+520520+ if (pid > 0) {521521+ part->act_state = XPC_P_ACTIVATION_REQ;522522+ XPC_SET_REASON(part, xpcCloneKThread, __LINE__);523523+ } else {524524+ XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);525525+ }526526+527527+ spin_unlock_irqrestore(&part->act_lock, irq_flags);528528+}529529+530530+531531+/*532532+ * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified533533+ * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more534534+ * than one partition, we use an AMO_t structure per partition to indicate535535+ * whether a partition has sent an IPI or not. >>> If it has, then wake up the536536+ * associated kthread to handle it.537537+ *538538+ * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC539539+ * running on other partitions.540540+ *541541+ * Noteworthy Arguments:542542+ *543543+ * irq - Interrupt ReQuest number. NOT USED.544544+ *545545+ * dev_id - partid of IPI's potential sender.546546+ *547547+ * regs - processor's context before the processor entered548548+ * interrupt code. NOT USED.549549+ */550550+irqreturn_t551551+xpc_notify_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)552552+{553553+ partid_t partid = (partid_t) (u64) dev_id;554554+ struct xpc_partition *part = &xpc_partitions[partid];555555+556556+557557+ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);558558+559559+ if (xpc_part_ref(part)) {560560+ xpc_check_for_channel_activity(part);561561+562562+ xpc_part_deref(part);563563+ }564564+ return IRQ_HANDLED;565565+}566566+567567+568568+/*569569+ * Check to see if xpc_notify_IRQ_handler() dropped any IPIs on the floor570570+ * because the write to their associated IPI amo completed after the IRQ/IPI571571+ * was received.572572+ */573573+void574574+xpc_dropped_IPI_check(struct xpc_partition *part)575575+{576576+ if (xpc_part_ref(part)) {577577+ xpc_check_for_channel_activity(part);578578+579579+ part->dropped_IPI_timer.expires = jiffies +580580+ XPC_P_DROPPED_IPI_WAIT;581581+ add_timer(&part->dropped_IPI_timer);582582+ xpc_part_deref(part);583583+ }584584+}585585+586586+587587+void588588+xpc_activate_kthreads(struct xpc_channel *ch, int needed)589589+{590590+ int idle = atomic_read(&ch->kthreads_idle);591591+ int assigned = atomic_read(&ch->kthreads_assigned);592592+ int wakeup;593593+594594+595595+ DBUG_ON(needed <= 0);596596+597597+ if (idle > 0) {598598+ wakeup = (needed > idle) ? idle : needed;599599+ needed -= wakeup;600600+601601+ dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "602602+ "channel=%d\n", wakeup, ch->partid, ch->number);603603+604604+ /* only wakeup the requested number of kthreads */605605+ wake_up_nr(&ch->idle_wq, wakeup);606606+ }607607+608608+ if (needed <= 0) {609609+ return;610610+ }611611+612612+ if (needed + assigned > ch->kthreads_assigned_limit) {613613+ needed = ch->kthreads_assigned_limit - assigned;614614+ // >>>should never be less than 0615615+ if (needed <= 0) {616616+ return;617617+ }618618+ }619619+620620+ dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",621621+ needed, ch->partid, ch->number);622622+623623+ xpc_create_kthreads(ch, needed);624624+}625625+626626+627627+/*628628+ * This function is where XPC's kthreads wait for messages to deliver.629629+ */630630+static void631631+xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)632632+{633633+ do {634634+ /* deliver messages to their intended recipients */635635+636636+ while ((volatile s64) ch->w_local_GP.get <637637+ (volatile s64) ch->w_remote_GP.put &&638638+ !((volatile u32) ch->flags &639639+ XPC_C_DISCONNECTING)) {640640+ xpc_deliver_msg(ch);641641+ }642642+643643+ if (atomic_inc_return(&ch->kthreads_idle) >644644+ ch->kthreads_idle_limit) {645645+ /* too many idle kthreads on this channel */646646+ atomic_dec(&ch->kthreads_idle);647647+ break;648648+ }649649+650650+ dev_dbg(xpc_chan, "idle kthread calling "651651+ "wait_event_interruptible_exclusive()\n");652652+653653+ (void) wait_event_interruptible_exclusive(ch->idle_wq,654654+ ((volatile s64) ch->w_local_GP.get <655655+ (volatile s64) ch->w_remote_GP.put ||656656+ ((volatile u32) ch->flags &657657+ XPC_C_DISCONNECTING)));658658+659659+ atomic_dec(&ch->kthreads_idle);660660+661661+ } while (!((volatile u32) ch->flags & XPC_C_DISCONNECTING));662662+}663663+664664+665665+static int666666+xpc_daemonize_kthread(void *args)667667+{668668+ partid_t partid = XPC_UNPACK_ARG1(args);669669+ u16 ch_number = XPC_UNPACK_ARG2(args);670670+ struct xpc_partition *part = &xpc_partitions[partid];671671+ struct xpc_channel *ch;672672+ int n_needed;673673+674674+675675+ daemonize("xpc%02dc%d", partid, ch_number);676676+677677+ dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",678678+ partid, ch_number);679679+680680+ ch = &part->channels[ch_number];681681+682682+ if (!(ch->flags & XPC_C_DISCONNECTING)) {683683+ DBUG_ON(!(ch->flags & XPC_C_CONNECTED));684684+685685+ /* let registerer know that connection has been established */686686+687687+ if (atomic_read(&ch->kthreads_assigned) == 1) {688688+ xpc_connected_callout(ch);689689+690690+ /*691691+ * It is possible that while the callout was being692692+ * made that the remote partition sent some messages.693693+ * If that is the case, we may need to activate694694+ * additional kthreads to help deliver them. We only695695+ * need one less than total #of messages to deliver.696696+ */697697+ n_needed = ch->w_remote_GP.put - ch->w_local_GP.get - 1;698698+ if (n_needed > 0 &&699699+ !(ch->flags & XPC_C_DISCONNECTING)) {700700+ xpc_activate_kthreads(ch, n_needed);701701+ }702702+ }703703+704704+ xpc_kthread_waitmsgs(part, ch);705705+ }706706+707707+ if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&708708+ ((ch->flags & XPC_C_CONNECTCALLOUT) ||709709+ (ch->reason != xpcUnregistering &&710710+ ch->reason != xpcOtherUnregistering))) {711711+ xpc_disconnected_callout(ch);712712+ }713713+714714+715715+ xpc_msgqueue_deref(ch);716716+717717+ dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",718718+ partid, ch_number);719719+720720+ xpc_part_deref(part);721721+ return 0;722722+}723723+724724+725725+/*726726+ * For each partition that XPC has established communications with, there is727727+ * a minimum of one kernel thread assigned to perform any operation that728728+ * may potentially sleep or block (basically the callouts to the asynchronous729729+ * functions registered via xpc_connect()).730730+ *731731+ * Additional kthreads are created and destroyed by XPC as the workload732732+ * demands.733733+ *734734+ * A kthread is assigned to one of the active channels that exists for a given735735+ * partition.736736+ */737737+void738738+xpc_create_kthreads(struct xpc_channel *ch, int needed)739739+{740740+ unsigned long irq_flags;741741+ pid_t pid;742742+ u64 args = XPC_PACK_ARGS(ch->partid, ch->number);743743+744744+745745+ while (needed-- > 0) {746746+ pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);747747+ if (pid < 0) {748748+ /* the fork failed */749749+750750+ if (atomic_read(&ch->kthreads_assigned) <751751+ ch->kthreads_idle_limit) {752752+ /*753753+ * Flag this as an error only if we have an754754+ * insufficient #of kthreads for the channel755755+ * to function.756756+ *757757+ * No xpc_msgqueue_ref() is needed here since758758+ * the channel mgr is doing this.759759+ */760760+ spin_lock_irqsave(&ch->lock, irq_flags);761761+ XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,762762+ &irq_flags);763763+ spin_unlock_irqrestore(&ch->lock, irq_flags);764764+ }765765+ break;766766+ }767767+768768+ /*769769+ * The following is done on behalf of the newly created770770+ * kthread. That kthread is responsible for doing the771771+ * counterpart to the following before it exits.772772+ */773773+ (void) xpc_part_ref(&xpc_partitions[ch->partid]);774774+ xpc_msgqueue_ref(ch);775775+ atomic_inc(&ch->kthreads_assigned);776776+ ch->kthreads_created++; // >>> temporary debug only!!!777777+ }778778+}779779+780780+781781+void782782+xpc_disconnect_wait(int ch_number)783783+{784784+ partid_t partid;785785+ struct xpc_partition *part;786786+ struct xpc_channel *ch;787787+788788+789789+ /* now wait for all callouts to the caller's function to cease */790790+ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {791791+ part = &xpc_partitions[partid];792792+793793+ if (xpc_part_ref(part)) {794794+ ch = &part->channels[ch_number];795795+796796+// >>> how do we keep from falling into the window between our check and going797797+// >>> down and coming back up where sema is re-inited?798798+ if (ch->flags & XPC_C_SETUP) {799799+ (void) down(&ch->teardown_sema);800800+ }801801+802802+ xpc_part_deref(part);803803+ }804804+ }805805+}806806+807807+808808+static void809809+xpc_do_exit(void)810810+{811811+ partid_t partid;812812+ int active_part_count;813813+ struct xpc_partition *part;814814+815815+816816+ /* now it's time to eliminate our heartbeat */817817+ del_timer_sync(&xpc_hb_timer);818818+ xpc_vars->heartbeating_to_mask = 0;819819+820820+ /* indicate to others that our reserved page is uninitialized */821821+ xpc_rsvd_page->vars_pa = 0;822822+823823+ /*824824+ * Ignore all incoming interrupts. Without interupts the heartbeat825825+ * checker won't activate any new partitions that may come up.826826+ */827827+ free_irq(SGI_XPC_ACTIVATE, NULL);828828+829829+ /*830830+ * Cause the heartbeat checker and the discovery threads to exit.831831+ * We don't want them attempting to activate new partitions as we832832+ * try to deactivate the existing ones.833833+ */834834+ xpc_exiting = 1;835835+ wake_up_interruptible(&xpc_act_IRQ_wq);836836+837837+ /* wait for the heartbeat checker thread to mark itself inactive */838838+ down(&xpc_hb_checker_exited);839839+840840+ /* wait for the discovery thread to mark itself inactive */841841+ down(&xpc_discovery_exited);842842+843843+844844+ set_current_state(TASK_INTERRUPTIBLE);845845+ schedule_timeout(0.3 * HZ);846846+ set_current_state(TASK_RUNNING);847847+848848+849849+ /* wait for all partitions to become inactive */850850+851851+ do {852852+ active_part_count = 0;853853+854854+ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {855855+ part = &xpc_partitions[partid];856856+ if (part->act_state != XPC_P_INACTIVE) {857857+ active_part_count++;858858+859859+ XPC_DEACTIVATE_PARTITION(part, xpcUnloading);860860+ }861861+ }862862+863863+ if (active_part_count) {864864+ set_current_state(TASK_INTERRUPTIBLE);865865+ schedule_timeout(0.3 * HZ);866866+ set_current_state(TASK_RUNNING);867867+ }868868+869869+ } while (active_part_count > 0);870870+871871+872872+ /* close down protections for IPI operations */873873+ xpc_restrict_IPI_ops();874874+875875+876876+ /* clear the interface to XPC's functions */877877+ xpc_clear_interface();878878+879879+ if (xpc_sysctl) {880880+ unregister_sysctl_table(xpc_sysctl);881881+ }882882+}883883+884884+885885+int __init886886+xpc_init(void)887887+{888888+ int ret;889889+ partid_t partid;890890+ struct xpc_partition *part;891891+ pid_t pid;892892+893893+894894+ /*895895+ * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng896896+ * both a partition's reserved page and its XPC variables. Its size was897897+ * based on the size of a reserved page. So we need to ensure that the898898+ * XPC variables will fit as well.899899+ */900900+ if (XPC_VARS_ALIGNED_SIZE > XPC_RSVD_PAGE_ALIGNED_SIZE) {901901+ dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");902902+ return -EPERM;903903+ }904904+ DBUG_ON((u64) xpc_remote_copy_buffer !=905905+ L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer));906906+907907+ snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");908908+ snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");909909+910910+ xpc_sysctl = register_sysctl_table(xpc_sys_dir, 1);911911+912912+ /*913913+ * The first few fields of each entry of xpc_partitions[] need to914914+ * be initialized now so that calls to xpc_connect() and915915+ * xpc_disconnect() can be made prior to the activation of any remote916916+ * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE917917+ * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING918918+ * PARTITION HAS BEEN ACTIVATED.919919+ */920920+ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {921921+ part = &xpc_partitions[partid];922922+923923+ DBUG_ON((u64) part != L1_CACHE_ALIGN((u64) part));924924+925925+ part->act_IRQ_rcvd = 0;926926+ spin_lock_init(&part->act_lock);927927+ part->act_state = XPC_P_INACTIVE;928928+ XPC_SET_REASON(part, 0, 0);929929+ part->setup_state = XPC_P_UNSET;930930+ init_waitqueue_head(&part->teardown_wq);931931+ atomic_set(&part->references, 0);932932+ }933933+934934+ /*935935+ * Open up protections for IPI operations (and AMO operations on936936+ * Shub 1.1 systems).937937+ */938938+ xpc_allow_IPI_ops();939939+940940+ /*941941+ * Interrupts being processed will increment this atomic variable and942942+ * awaken the heartbeat thread which will process the interrupts.943943+ */944944+ atomic_set(&xpc_act_IRQ_rcvd, 0);945945+946946+ /*947947+ * This is safe to do before the xpc_hb_checker thread has started948948+ * because the handler releases a wait queue. If an interrupt is949949+ * received before the thread is waiting, it will not go to sleep,950950+ * but rather immediately process the interrupt.951951+ */952952+ ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,953953+ "xpc hb", NULL);954954+ if (ret != 0) {955955+ dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "956956+ "errno=%d\n", -ret);957957+958958+ xpc_restrict_IPI_ops();959959+960960+ if (xpc_sysctl) {961961+ unregister_sysctl_table(xpc_sysctl);962962+ }963963+ return -EBUSY;964964+ }965965+966966+ /*967967+ * Fill the partition reserved page with the information needed by968968+ * other partitions to discover we are alive and establish initial969969+ * communications.970970+ */971971+ xpc_rsvd_page = xpc_rsvd_page_init();972972+ if (xpc_rsvd_page == NULL) {973973+ dev_err(xpc_part, "could not setup our reserved page\n");974974+975975+ free_irq(SGI_XPC_ACTIVATE, NULL);976976+ xpc_restrict_IPI_ops();977977+978978+ if (xpc_sysctl) {979979+ unregister_sysctl_table(xpc_sysctl);980980+ }981981+ return -EBUSY;982982+ }983983+984984+985985+ /*986986+ * Set the beating to other partitions into motion. This is987987+ * the last requirement for other partitions' discovery to988988+ * initiate communications with us.989989+ */990990+ init_timer(&xpc_hb_timer);991991+ xpc_hb_timer.function = xpc_hb_beater;992992+ xpc_hb_beater(0);993993+994994+995995+ /*996996+ * The real work-horse behind xpc. This processes incoming997997+ * interrupts and monitors remote heartbeats.998998+ */999999+ pid = kernel_thread(xpc_hb_checker, NULL, 0);10001000+ if (pid < 0) {10011001+ dev_err(xpc_part, "failed while forking hb check thread\n");10021002+10031003+ /* indicate to others that our reserved page is uninitialized */10041004+ xpc_rsvd_page->vars_pa = 0;10051005+10061006+ del_timer_sync(&xpc_hb_timer);10071007+ free_irq(SGI_XPC_ACTIVATE, NULL);10081008+ xpc_restrict_IPI_ops();10091009+10101010+ if (xpc_sysctl) {10111011+ unregister_sysctl_table(xpc_sysctl);10121012+ }10131013+ return -EBUSY;10141014+ }10151015+10161016+10171017+ /*10181018+ * Startup a thread that will attempt to discover other partitions to10191019+ * activate based on info provided by SAL. This new thread is short10201020+ * lived and will exit once discovery is complete.10211021+ */10221022+ pid = kernel_thread(xpc_initiate_discovery, NULL, 0);10231023+ if (pid < 0) {10241024+ dev_err(xpc_part, "failed while forking discovery thread\n");10251025+10261026+ /* mark this new thread as a non-starter */10271027+ up(&xpc_discovery_exited);10281028+10291029+ xpc_do_exit();10301030+ return -EBUSY;10311031+ }10321032+10331033+10341034+ /* set the interface to point at XPC's functions */10351035+ xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,10361036+ xpc_initiate_allocate, xpc_initiate_send,10371037+ xpc_initiate_send_notify, xpc_initiate_received,10381038+ xpc_initiate_partid_to_nasids);10391039+10401040+ return 0;10411041+}10421042+module_init(xpc_init);10431043+10441044+10451045+void __exit10461046+xpc_exit(void)10471047+{10481048+ xpc_do_exit();10491049+}10501050+module_exit(xpc_exit);10511051+10521052+10531053+MODULE_AUTHOR("Silicon Graphics, Inc.");10541054+MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");10551055+MODULE_LICENSE("GPL");10561056+10571057+module_param(xpc_hb_interval, int, 0);10581058+MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "10591059+ "heartbeat increments.");10601060+10611061+module_param(xpc_hb_check_interval, int, 0);10621062+MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "10631063+ "heartbeat checks.");10641064+
+984
arch/ia64/sn/kernel/xpc_partition.c
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.77+ */88+99+1010+/*1111+ * Cross Partition Communication (XPC) partition support.1212+ *1313+ * This is the part of XPC that detects the presence/absence of1414+ * other partitions. It provides a heartbeat and monitors the1515+ * heartbeats of other partitions.1616+ *1717+ */1818+1919+2020+#include <linux/kernel.h>2121+#include <linux/sysctl.h>2222+#include <linux/cache.h>2323+#include <linux/mmzone.h>2424+#include <linux/nodemask.h>2525+#include <asm/sn/bte.h>2626+#include <asm/sn/intr.h>2727+#include <asm/sn/sn_sal.h>2828+#include <asm/sn/nodepda.h>2929+#include <asm/sn/addrs.h>3030+#include "xpc.h"3131+3232+3333+/* XPC is exiting flag */3434+int xpc_exiting;3535+3636+3737+/* SH_IPI_ACCESS shub register value on startup */3838+static u64 xpc_sh1_IPI_access;3939+static u64 xpc_sh2_IPI_access0;4040+static u64 xpc_sh2_IPI_access1;4141+static u64 xpc_sh2_IPI_access2;4242+static u64 xpc_sh2_IPI_access3;4343+4444+4545+/* original protection values for each node */4646+u64 xpc_prot_vec[MAX_COMPACT_NODES];4747+4848+4949+/* this partition's reserved page */5050+struct xpc_rsvd_page *xpc_rsvd_page;5151+5252+/* this partition's XPC variables (within the reserved page) */5353+struct xpc_vars *xpc_vars;5454+struct xpc_vars_part *xpc_vars_part;5555+5656+5757+/*5858+ * For performance reasons, each entry of xpc_partitions[] is cacheline5959+ * aligned. And xpc_partitions[] is padded with an additional entry at the6060+ * end so that the last legitimate entry doesn't share its cacheline with6161+ * another variable.6262+ */6363+struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];6464+6565+6666+/*6767+ * Generic buffer used to store a local copy of the remote partitions6868+ * reserved page or XPC variables.6969+ *7070+ * xpc_discovery runs only once and is a seperate thread that is7171+ * very likely going to be processing in parallel with receiving7272+ * interrupts.7373+ */7474+char ____cacheline_aligned7575+ xpc_remote_copy_buffer[XPC_RSVD_PAGE_ALIGNED_SIZE];7676+7777+7878+/* systune related variables */7979+int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;8080+int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_TIMEOUT;8181+8282+8383+/*8484+ * Given a nasid, get the physical address of the partition's reserved page8585+ * for that nasid. This function returns 0 on any error.8686+ */8787+static u648888+xpc_get_rsvd_page_pa(int nasid, u64 buf, u64 buf_size)8989+{9090+ bte_result_t bte_res;9191+ s64 status;9292+ u64 cookie = 0;9393+ u64 rp_pa = nasid; /* seed with nasid */9494+ u64 len = 0;9595+9696+9797+ while (1) {9898+9999+ status = sn_partition_reserved_page_pa(buf, &cookie, &rp_pa,100100+ &len);101101+102102+ dev_dbg(xpc_part, "SAL returned with status=%li, cookie="103103+ "0x%016lx, address=0x%016lx, len=0x%016lx\n",104104+ status, cookie, rp_pa, len);105105+106106+ if (status != SALRET_MORE_PASSES) {107107+ break;108108+ }109109+110110+ if (len > buf_size) {111111+ dev_err(xpc_part, "len (=0x%016lx) > buf_size\n", len);112112+ status = SALRET_ERROR;113113+ break;114114+ }115115+116116+ bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_size,117117+ (BTE_NOTIFY | BTE_WACQUIRE), NULL);118118+ if (bte_res != BTE_SUCCESS) {119119+ dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);120120+ status = SALRET_ERROR;121121+ break;122122+ }123123+ }124124+125125+ if (status != SALRET_OK) {126126+ rp_pa = 0;127127+ }128128+ dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);129129+ return rp_pa;130130+}131131+132132+133133+/*134134+ * Fill the partition reserved page with the information needed by135135+ * other partitions to discover we are alive and establish initial136136+ * communications.137137+ */138138+struct xpc_rsvd_page *139139+xpc_rsvd_page_init(void)140140+{141141+ struct xpc_rsvd_page *rp;142142+ AMO_t *amos_page;143143+ u64 rp_pa, next_cl, nasid_array = 0;144144+ int i, ret;145145+146146+147147+ /* get the local reserved page's address */148148+149149+ rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0),150150+ (u64) xpc_remote_copy_buffer,151151+ XPC_RSVD_PAGE_ALIGNED_SIZE);152152+ if (rp_pa == 0) {153153+ dev_err(xpc_part, "SAL failed to locate the reserved page\n");154154+ return NULL;155155+ }156156+ rp = (struct xpc_rsvd_page *) __va(rp_pa);157157+158158+ if (rp->partid != sn_partition_id) {159159+ dev_err(xpc_part, "the reserved page's partid of %d should be "160160+ "%d\n", rp->partid, sn_partition_id);161161+ return NULL;162162+ }163163+164164+ rp->version = XPC_RP_VERSION;165165+166166+ /*167167+ * Place the XPC variables on the cache line following the168168+ * reserved page structure.169169+ */170170+ next_cl = (u64) rp + XPC_RSVD_PAGE_ALIGNED_SIZE;171171+ xpc_vars = (struct xpc_vars *) next_cl;172172+173173+ /*174174+ * Before clearing xpc_vars, see if a page of AMOs had been previously175175+ * allocated. If not we'll need to allocate one and set permissions176176+ * so that cross-partition AMOs are allowed.177177+ *178178+ * The allocated AMO page needs MCA reporting to remain disabled after179179+ * XPC has unloaded. To make this work, we keep a copy of the pointer180180+ * to this page (i.e., amos_page) in the struct xpc_vars structure,181181+ * which is pointed to by the reserved page, and re-use that saved copy182182+ * on subsequent loads of XPC. This AMO page is never freed, and its183183+ * memory protections are never restricted.184184+ */185185+ if ((amos_page = xpc_vars->amos_page) == NULL) {186186+ amos_page = (AMO_t *) mspec_kalloc_page(0);187187+ if (amos_page == NULL) {188188+ dev_err(xpc_part, "can't allocate page of AMOs\n");189189+ return NULL;190190+ }191191+192192+ /*193193+ * Open up AMO-R/W to cpu. This is done for Shub 1.1 systems194194+ * when xpc_allow_IPI_ops() is called via xpc_hb_init().195195+ */196196+ if (!enable_shub_wars_1_1()) {197197+ ret = sn_change_memprotect(ia64_tpa((u64) amos_page),198198+ PAGE_SIZE, SN_MEMPROT_ACCESS_CLASS_1,199199+ &nasid_array);200200+ if (ret != 0) {201201+ dev_err(xpc_part, "can't change memory "202202+ "protections\n");203203+ mspec_kfree_page((unsigned long) amos_page);204204+ return NULL;205205+ }206206+ }207207+ } else if (!IS_AMO_ADDRESS((u64) amos_page)) {208208+ /*209209+ * EFI's XPBOOT can also set amos_page in the reserved page,210210+ * but it happens to leave it as an uncached physical address211211+ * and we need it to be an uncached virtual, so we'll have to212212+ * convert it.213213+ */214214+ if (!IS_AMO_PHYS_ADDRESS((u64) amos_page)) {215215+ dev_err(xpc_part, "previously used amos_page address "216216+ "is bad = 0x%p\n", (void *) amos_page);217217+ return NULL;218218+ }219219+ amos_page = (AMO_t *) TO_AMO((u64) amos_page);220220+ }221221+222222+ memset(xpc_vars, 0, sizeof(struct xpc_vars));223223+224224+ /*225225+ * Place the XPC per partition specific variables on the cache line226226+ * following the XPC variables structure.227227+ */228228+ next_cl += XPC_VARS_ALIGNED_SIZE;229229+ memset((u64 *) next_cl, 0, sizeof(struct xpc_vars_part) *230230+ XP_MAX_PARTITIONS);231231+ xpc_vars_part = (struct xpc_vars_part *) next_cl;232232+ xpc_vars->vars_part_pa = __pa(next_cl);233233+234234+ xpc_vars->version = XPC_V_VERSION;235235+ xpc_vars->act_nasid = cpuid_to_nasid(0);236236+ xpc_vars->act_phys_cpuid = cpu_physical_id(0);237237+ xpc_vars->amos_page = amos_page; /* save for next load of XPC */238238+239239+240240+ /*241241+ * Initialize the activation related AMO variables.242242+ */243243+ xpc_vars->act_amos = xpc_IPI_init(XP_MAX_PARTITIONS);244244+ for (i = 1; i < XP_NASID_MASK_WORDS; i++) {245245+ xpc_IPI_init(i + XP_MAX_PARTITIONS);246246+ }247247+ /* export AMO page's physical address to other partitions */248248+ xpc_vars->amos_page_pa = ia64_tpa((u64) xpc_vars->amos_page);249249+250250+ /*251251+ * This signifies to the remote partition that our reserved252252+ * page is initialized.253253+ */254254+ (volatile u64) rp->vars_pa = __pa(xpc_vars);255255+256256+ return rp;257257+}258258+259259+260260+/*261261+ * Change protections to allow IPI operations (and AMO operations on262262+ * Shub 1.1 systems).263263+ */264264+void265265+xpc_allow_IPI_ops(void)266266+{267267+ int node;268268+ int nasid;269269+270270+271271+ // >>> Change SH_IPI_ACCESS code to use SAL call once it is available.272272+273273+ if (is_shub2()) {274274+ xpc_sh2_IPI_access0 =275275+ (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));276276+ xpc_sh2_IPI_access1 =277277+ (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));278278+ xpc_sh2_IPI_access2 =279279+ (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));280280+ xpc_sh2_IPI_access3 =281281+ (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));282282+283283+ for_each_online_node(node) {284284+ nasid = cnodeid_to_nasid(node);285285+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),286286+ -1UL);287287+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),288288+ -1UL);289289+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),290290+ -1UL);291291+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),292292+ -1UL);293293+ }294294+295295+ } else {296296+ xpc_sh1_IPI_access =297297+ (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_IPI_ACCESS));298298+299299+ for_each_online_node(node) {300300+ nasid = cnodeid_to_nasid(node);301301+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),302302+ -1UL);303303+304304+ /*305305+ * Since the BIST collides with memory operations on306306+ * SHUB 1.1 sn_change_memprotect() cannot be used.307307+ */308308+ if (enable_shub_wars_1_1()) {309309+ /* open up everything */310310+ xpc_prot_vec[node] = (u64) HUB_L((u64 *)311311+ GLOBAL_MMR_ADDR(nasid,312312+ SH1_MD_DQLP_MMR_DIR_PRIVEC0));313313+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,314314+ SH1_MD_DQLP_MMR_DIR_PRIVEC0),315315+ -1UL);316316+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,317317+ SH1_MD_DQRP_MMR_DIR_PRIVEC0),318318+ -1UL);319319+ }320320+ }321321+ }322322+}323323+324324+325325+/*326326+ * Restrict protections to disallow IPI operations (and AMO operations on327327+ * Shub 1.1 systems).328328+ */329329+void330330+xpc_restrict_IPI_ops(void)331331+{332332+ int node;333333+ int nasid;334334+335335+336336+ // >>> Change SH_IPI_ACCESS code to use SAL call once it is available.337337+338338+ if (is_shub2()) {339339+340340+ for_each_online_node(node) {341341+ nasid = cnodeid_to_nasid(node);342342+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),343343+ xpc_sh2_IPI_access0);344344+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),345345+ xpc_sh2_IPI_access1);346346+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),347347+ xpc_sh2_IPI_access2);348348+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),349349+ xpc_sh2_IPI_access3);350350+ }351351+352352+ } else {353353+354354+ for_each_online_node(node) {355355+ nasid = cnodeid_to_nasid(node);356356+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),357357+ xpc_sh1_IPI_access);358358+359359+ if (enable_shub_wars_1_1()) {360360+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,361361+ SH1_MD_DQLP_MMR_DIR_PRIVEC0),362362+ xpc_prot_vec[node]);363363+ HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,364364+ SH1_MD_DQRP_MMR_DIR_PRIVEC0),365365+ xpc_prot_vec[node]);366366+ }367367+ }368368+ }369369+}370370+371371+372372+/*373373+ * At periodic intervals, scan through all active partitions and ensure374374+ * their heartbeat is still active. If not, the partition is deactivated.375375+ */376376+void377377+xpc_check_remote_hb(void)378378+{379379+ struct xpc_vars *remote_vars;380380+ struct xpc_partition *part;381381+ partid_t partid;382382+ bte_result_t bres;383383+384384+385385+ remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;386386+387387+ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {388388+ if (partid == sn_partition_id) {389389+ continue;390390+ }391391+392392+ part = &xpc_partitions[partid];393393+394394+ if (part->act_state == XPC_P_INACTIVE ||395395+ part->act_state == XPC_P_DEACTIVATING) {396396+ continue;397397+ }398398+399399+ /* pull the remote_hb cache line */400400+ bres = xp_bte_copy(part->remote_vars_pa,401401+ ia64_tpa((u64) remote_vars),402402+ XPC_VARS_ALIGNED_SIZE,403403+ (BTE_NOTIFY | BTE_WACQUIRE), NULL);404404+ if (bres != BTE_SUCCESS) {405405+ XPC_DEACTIVATE_PARTITION(part,406406+ xpc_map_bte_errors(bres));407407+ continue;408408+ }409409+410410+ dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"411411+ " = %ld, kdb_status = %ld, HB_mask = 0x%lx\n", partid,412412+ remote_vars->heartbeat, part->last_heartbeat,413413+ remote_vars->kdb_status,414414+ remote_vars->heartbeating_to_mask);415415+416416+ if (((remote_vars->heartbeat == part->last_heartbeat) &&417417+ (remote_vars->kdb_status == 0)) ||418418+ !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {419419+420420+ XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);421421+ continue;422422+ }423423+424424+ part->last_heartbeat = remote_vars->heartbeat;425425+ }426426+}427427+428428+429429+/*430430+ * Get a copy of the remote partition's rsvd page.431431+ *432432+ * remote_rp points to a buffer that is cacheline aligned for BTE copies and433433+ * assumed to be of size XPC_RSVD_PAGE_ALIGNED_SIZE.434434+ */435435+static enum xpc_retval436436+xpc_get_remote_rp(int nasid, u64 *discovered_nasids,437437+ struct xpc_rsvd_page *remote_rp, u64 *remote_rsvd_page_pa)438438+{439439+ int bres, i;440440+441441+442442+ /* get the reserved page's physical address */443443+444444+ *remote_rsvd_page_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp,445445+ XPC_RSVD_PAGE_ALIGNED_SIZE);446446+ if (*remote_rsvd_page_pa == 0) {447447+ return xpcNoRsvdPageAddr;448448+ }449449+450450+451451+ /* pull over the reserved page structure */452452+453453+ bres = xp_bte_copy(*remote_rsvd_page_pa, ia64_tpa((u64) remote_rp),454454+ XPC_RSVD_PAGE_ALIGNED_SIZE,455455+ (BTE_NOTIFY | BTE_WACQUIRE), NULL);456456+ if (bres != BTE_SUCCESS) {457457+ return xpc_map_bte_errors(bres);458458+ }459459+460460+461461+ if (discovered_nasids != NULL) {462462+ for (i = 0; i < XP_NASID_MASK_WORDS; i++) {463463+ discovered_nasids[i] |= remote_rp->part_nasids[i];464464+ }465465+ }466466+467467+468468+ /* check that the partid is for another partition */469469+470470+ if (remote_rp->partid < 1 ||471471+ remote_rp->partid > (XP_MAX_PARTITIONS - 1)) {472472+ return xpcInvalidPartid;473473+ }474474+475475+ if (remote_rp->partid == sn_partition_id) {476476+ return xpcLocalPartid;477477+ }478478+479479+480480+ if (XPC_VERSION_MAJOR(remote_rp->version) !=481481+ XPC_VERSION_MAJOR(XPC_RP_VERSION)) {482482+ return xpcBadVersion;483483+ }484484+485485+ return xpcSuccess;486486+}487487+488488+489489+/*490490+ * Get a copy of the remote partition's XPC variables.491491+ *492492+ * remote_vars points to a buffer that is cacheline aligned for BTE copies and493493+ * assumed to be of size XPC_VARS_ALIGNED_SIZE.494494+ */495495+static enum xpc_retval496496+xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)497497+{498498+ int bres;499499+500500+501501+ if (remote_vars_pa == 0) {502502+ return xpcVarsNotSet;503503+ }504504+505505+506506+ /* pull over the cross partition variables */507507+508508+ bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),509509+ XPC_VARS_ALIGNED_SIZE,510510+ (BTE_NOTIFY | BTE_WACQUIRE), NULL);511511+ if (bres != BTE_SUCCESS) {512512+ return xpc_map_bte_errors(bres);513513+ }514514+515515+ if (XPC_VERSION_MAJOR(remote_vars->version) !=516516+ XPC_VERSION_MAJOR(XPC_V_VERSION)) {517517+ return xpcBadVersion;518518+ }519519+520520+ return xpcSuccess;521521+}522522+523523+524524+/*525525+ * Prior code has determine the nasid which generated an IPI. Inspect526526+ * that nasid to determine if its partition needs to be activated or527527+ * deactivated.528528+ *529529+ * A partition is consider "awaiting activation" if our partition530530+ * flags indicate it is not active and it has a heartbeat. A531531+ * partition is considered "awaiting deactivation" if our partition532532+ * flags indicate it is active but it has no heartbeat or it is not533533+ * sending its heartbeat to us.534534+ *535535+ * To determine the heartbeat, the remote nasid must have a properly536536+ * initialized reserved page.537537+ */538538+static void539539+xpc_identify_act_IRQ_req(int nasid)540540+{541541+ struct xpc_rsvd_page *remote_rp;542542+ struct xpc_vars *remote_vars;543543+ u64 remote_rsvd_page_pa;544544+ u64 remote_vars_pa;545545+ partid_t partid;546546+ struct xpc_partition *part;547547+ enum xpc_retval ret;548548+549549+550550+ /* pull over the reserved page structure */551551+552552+ remote_rp = (struct xpc_rsvd_page *) xpc_remote_copy_buffer;553553+554554+ ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rsvd_page_pa);555555+ if (ret != xpcSuccess) {556556+ dev_warn(xpc_part, "unable to get reserved page from nasid %d, "557557+ "which sent interrupt, reason=%d\n", nasid, ret);558558+ return;559559+ }560560+561561+ remote_vars_pa = remote_rp->vars_pa;562562+ partid = remote_rp->partid;563563+ part = &xpc_partitions[partid];564564+565565+566566+ /* pull over the cross partition variables */567567+568568+ remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;569569+570570+ ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);571571+ if (ret != xpcSuccess) {572572+573573+ dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "574574+ "which sent interrupt, reason=%d\n", nasid, ret);575575+576576+ XPC_DEACTIVATE_PARTITION(part, ret);577577+ return;578578+ }579579+580580+581581+ part->act_IRQ_rcvd++;582582+583583+ dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "584584+ "%ld:0x%lx\n", (int) nasid, (int) partid, part->act_IRQ_rcvd,585585+ remote_vars->heartbeat, remote_vars->heartbeating_to_mask);586586+587587+588588+ if (part->act_state == XPC_P_INACTIVE) {589589+590590+ part->remote_rp_pa = remote_rsvd_page_pa;591591+ dev_dbg(xpc_part, " remote_rp_pa = 0x%016lx\n",592592+ part->remote_rp_pa);593593+594594+ part->remote_vars_pa = remote_vars_pa;595595+ dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",596596+ part->remote_vars_pa);597597+598598+ part->last_heartbeat = remote_vars->heartbeat;599599+ dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",600600+ part->last_heartbeat);601601+602602+ part->remote_vars_part_pa = remote_vars->vars_part_pa;603603+ dev_dbg(xpc_part, " remote_vars_part_pa = 0x%016lx\n",604604+ part->remote_vars_part_pa);605605+606606+ part->remote_act_nasid = remote_vars->act_nasid;607607+ dev_dbg(xpc_part, " remote_act_nasid = 0x%x\n",608608+ part->remote_act_nasid);609609+610610+ part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;611611+ dev_dbg(xpc_part, " remote_act_phys_cpuid = 0x%x\n",612612+ part->remote_act_phys_cpuid);613613+614614+ part->remote_amos_page_pa = remote_vars->amos_page_pa;615615+ dev_dbg(xpc_part, " remote_amos_page_pa = 0x%lx\n",616616+ part->remote_amos_page_pa);617617+618618+ xpc_activate_partition(part);619619+620620+ } else if (part->remote_amos_page_pa != remote_vars->amos_page_pa ||621621+ !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {622622+623623+ part->reactivate_nasid = nasid;624624+ XPC_DEACTIVATE_PARTITION(part, xpcReactivating);625625+ }626626+}627627+628628+629629+/*630630+ * Loop through the activation AMO variables and process any bits631631+ * which are set. Each bit indicates a nasid sending a partition632632+ * activation or deactivation request.633633+ *634634+ * Return #of IRQs detected.635635+ */636636+int637637+xpc_identify_act_IRQ_sender(void)638638+{639639+ int word, bit;640640+ u64 nasid_mask;641641+ u64 nasid; /* remote nasid */642642+ int n_IRQs_detected = 0;643643+ AMO_t *act_amos;644644+ struct xpc_rsvd_page *rp = (struct xpc_rsvd_page *) xpc_rsvd_page;645645+646646+647647+ act_amos = xpc_vars->act_amos;648648+649649+650650+ /* scan through act AMO variable looking for non-zero entries */651651+ for (word = 0; word < XP_NASID_MASK_WORDS; word++) {652652+653653+ nasid_mask = xpc_IPI_receive(&act_amos[word]);654654+ if (nasid_mask == 0) {655655+ /* no IRQs from nasids in this variable */656656+ continue;657657+ }658658+659659+ dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,660660+ nasid_mask);661661+662662+663663+ /*664664+ * If this nasid has been added to the machine since665665+ * our partition was reset, this will retain the666666+ * remote nasid in our reserved pages machine mask.667667+ * This is used in the event of module reload.668668+ */669669+ rp->mach_nasids[word] |= nasid_mask;670670+671671+672672+ /* locate the nasid(s) which sent interrupts */673673+674674+ for (bit = 0; bit < (8 * sizeof(u64)); bit++) {675675+ if (nasid_mask & (1UL << bit)) {676676+ n_IRQs_detected++;677677+ nasid = XPC_NASID_FROM_W_B(word, bit);678678+ dev_dbg(xpc_part, "interrupt from nasid %ld\n",679679+ nasid);680680+ xpc_identify_act_IRQ_req(nasid);681681+ }682682+ }683683+ }684684+ return n_IRQs_detected;685685+}686686+687687+688688+/*689689+ * Mark specified partition as active.690690+ */691691+enum xpc_retval692692+xpc_mark_partition_active(struct xpc_partition *part)693693+{694694+ unsigned long irq_flags;695695+ enum xpc_retval ret;696696+697697+698698+ dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));699699+700700+ spin_lock_irqsave(&part->act_lock, irq_flags);701701+ if (part->act_state == XPC_P_ACTIVATING) {702702+ part->act_state = XPC_P_ACTIVE;703703+ ret = xpcSuccess;704704+ } else {705705+ DBUG_ON(part->reason == xpcSuccess);706706+ ret = part->reason;707707+ }708708+ spin_unlock_irqrestore(&part->act_lock, irq_flags);709709+710710+ return ret;711711+}712712+713713+714714+/*715715+ * Notify XPC that the partition is down.716716+ */717717+void718718+xpc_deactivate_partition(const int line, struct xpc_partition *part,719719+ enum xpc_retval reason)720720+{721721+ unsigned long irq_flags;722722+ partid_t partid = XPC_PARTID(part);723723+724724+725725+ spin_lock_irqsave(&part->act_lock, irq_flags);726726+727727+ if (part->act_state == XPC_P_INACTIVE) {728728+ XPC_SET_REASON(part, reason, line);729729+ spin_unlock_irqrestore(&part->act_lock, irq_flags);730730+ if (reason == xpcReactivating) {731731+ /* we interrupt ourselves to reactivate partition */732732+ xpc_IPI_send_reactivate(part);733733+ }734734+ return;735735+ }736736+ if (part->act_state == XPC_P_DEACTIVATING) {737737+ if ((part->reason == xpcUnloading && reason != xpcUnloading) ||738738+ reason == xpcReactivating) {739739+ XPC_SET_REASON(part, reason, line);740740+ }741741+ spin_unlock_irqrestore(&part->act_lock, irq_flags);742742+ return;743743+ }744744+745745+ part->act_state = XPC_P_DEACTIVATING;746746+ XPC_SET_REASON(part, reason, line);747747+748748+ spin_unlock_irqrestore(&part->act_lock, irq_flags);749749+750750+ XPC_DISALLOW_HB(partid, xpc_vars);751751+752752+ dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n", partid,753753+ reason);754754+755755+ xpc_partition_down(part, reason);756756+}757757+758758+759759+/*760760+ * Mark specified partition as active.761761+ */762762+void763763+xpc_mark_partition_inactive(struct xpc_partition *part)764764+{765765+ unsigned long irq_flags;766766+767767+768768+ dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",769769+ XPC_PARTID(part));770770+771771+ spin_lock_irqsave(&part->act_lock, irq_flags);772772+ part->act_state = XPC_P_INACTIVE;773773+ spin_unlock_irqrestore(&part->act_lock, irq_flags);774774+ part->remote_rp_pa = 0;775775+}776776+777777+778778+/*779779+ * SAL has provided a partition and machine mask. The partition mask780780+ * contains a bit for each even nasid in our partition. The machine781781+ * mask contains a bit for each even nasid in the entire machine.782782+ *783783+ * Using those two bit arrays, we can determine which nasids are784784+ * known in the machine. Each should also have a reserved page785785+ * initialized if they are available for partitioning.786786+ */787787+void788788+xpc_discovery(void)789789+{790790+ void *remote_rp_base;791791+ struct xpc_rsvd_page *remote_rp;792792+ struct xpc_vars *remote_vars;793793+ u64 remote_rsvd_page_pa;794794+ u64 remote_vars_pa;795795+ int region;796796+ int max_regions;797797+ int nasid;798798+ struct xpc_rsvd_page *rp;799799+ partid_t partid;800800+ struct xpc_partition *part;801801+ u64 *discovered_nasids;802802+ enum xpc_retval ret;803803+804804+805805+ remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RSVD_PAGE_ALIGNED_SIZE,806806+ GFP_KERNEL, &remote_rp_base);807807+ if (remote_rp == NULL) {808808+ return;809809+ }810810+ remote_vars = (struct xpc_vars *) remote_rp;811811+812812+813813+ discovered_nasids = kmalloc(sizeof(u64) * XP_NASID_MASK_WORDS,814814+ GFP_KERNEL);815815+ if (discovered_nasids == NULL) {816816+ kfree(remote_rp_base);817817+ return;818818+ }819819+ memset(discovered_nasids, 0, sizeof(u64) * XP_NASID_MASK_WORDS);820820+821821+ rp = (struct xpc_rsvd_page *) xpc_rsvd_page;822822+823823+ /*824824+ * The term 'region' in this context refers to the minimum number of825825+ * nodes that can comprise an access protection grouping. The access826826+ * protection is in regards to memory, IOI and IPI.827827+ */828828+//>>> move the next two #defines into either include/asm-ia64/sn/arch.h or829829+//>>> include/asm-ia64/sn/addrs.h830830+#define SH1_MAX_REGIONS 64831831+#define SH2_MAX_REGIONS 256832832+ max_regions = is_shub2() ? SH2_MAX_REGIONS : SH1_MAX_REGIONS;833833+834834+ for (region = 0; region < max_regions; region++) {835835+836836+ if ((volatile int) xpc_exiting) {837837+ break;838838+ }839839+840840+ dev_dbg(xpc_part, "searching region %d\n", region);841841+842842+ for (nasid = (region * sn_region_size * 2);843843+ nasid < ((region + 1) * sn_region_size * 2);844844+ nasid += 2) {845845+846846+ if ((volatile int) xpc_exiting) {847847+ break;848848+ }849849+850850+ dev_dbg(xpc_part, "checking nasid %d\n", nasid);851851+852852+853853+ if (XPC_NASID_IN_ARRAY(nasid, rp->part_nasids)) {854854+ dev_dbg(xpc_part, "PROM indicates Nasid %d is "855855+ "part of the local partition; skipping "856856+ "region\n", nasid);857857+ break;858858+ }859859+860860+ if (!(XPC_NASID_IN_ARRAY(nasid, rp->mach_nasids))) {861861+ dev_dbg(xpc_part, "PROM indicates Nasid %d was "862862+ "not on Numa-Link network at reset\n",863863+ nasid);864864+ continue;865865+ }866866+867867+ if (XPC_NASID_IN_ARRAY(nasid, discovered_nasids)) {868868+ dev_dbg(xpc_part, "Nasid %d is part of a "869869+ "partition which was previously "870870+ "discovered\n", nasid);871871+ continue;872872+ }873873+874874+875875+ /* pull over the reserved page structure */876876+877877+ ret = xpc_get_remote_rp(nasid, discovered_nasids,878878+ remote_rp, &remote_rsvd_page_pa);879879+ if (ret != xpcSuccess) {880880+ dev_dbg(xpc_part, "unable to get reserved page "881881+ "from nasid %d, reason=%d\n", nasid,882882+ ret);883883+884884+ if (ret == xpcLocalPartid) {885885+ break;886886+ }887887+ continue;888888+ }889889+890890+ remote_vars_pa = remote_rp->vars_pa;891891+892892+ partid = remote_rp->partid;893893+ part = &xpc_partitions[partid];894894+895895+896896+ /* pull over the cross partition variables */897897+898898+ ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);899899+ if (ret != xpcSuccess) {900900+ dev_dbg(xpc_part, "unable to get XPC variables "901901+ "from nasid %d, reason=%d\n", nasid,902902+ ret);903903+904904+ XPC_DEACTIVATE_PARTITION(part, ret);905905+ continue;906906+ }907907+908908+ if (part->act_state != XPC_P_INACTIVE) {909909+ dev_dbg(xpc_part, "partition %d on nasid %d is "910910+ "already activating\n", partid, nasid);911911+ break;912912+ }913913+914914+ /*915915+ * Register the remote partition's AMOs with SAL so it916916+ * can handle and cleanup errors within that address917917+ * range should the remote partition go down. We don't918918+ * unregister this range because it is difficult to919919+ * tell when outstanding writes to the remote partition920920+ * are finished and thus when it is thus safe to921921+ * unregister. This should not result in wasted space922922+ * in the SAL xp_addr_region table because we should923923+ * get the same page for remote_act_amos_pa after924924+ * module reloads and system reboots.925925+ */926926+ if (sn_register_xp_addr_region(927927+ remote_vars->amos_page_pa,928928+ PAGE_SIZE, 1) < 0) {929929+ dev_dbg(xpc_part, "partition %d failed to "930930+ "register xp_addr region 0x%016lx\n",931931+ partid, remote_vars->amos_page_pa);932932+933933+ XPC_SET_REASON(part, xpcPhysAddrRegFailed,934934+ __LINE__);935935+ break;936936+ }937937+938938+ /*939939+ * The remote nasid is valid and available.940940+ * Send an interrupt to that nasid to notify941941+ * it that we are ready to begin activation.942942+ */943943+ dev_dbg(xpc_part, "sending an interrupt to AMO 0x%lx, "944944+ "nasid %d, phys_cpuid 0x%x\n",945945+ remote_vars->amos_page_pa,946946+ remote_vars->act_nasid,947947+ remote_vars->act_phys_cpuid);948948+949949+ xpc_IPI_send_activate(remote_vars);950950+ }951951+ }952952+953953+ kfree(discovered_nasids);954954+ kfree(remote_rp_base);955955+}956956+957957+958958+/*959959+ * Given a partid, get the nasids owned by that partition from the960960+ * remote partition's reserved page.961961+ */962962+enum xpc_retval963963+xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)964964+{965965+ struct xpc_partition *part;966966+ u64 part_nasid_pa;967967+ int bte_res;968968+969969+970970+ part = &xpc_partitions[partid];971971+ if (part->remote_rp_pa == 0) {972972+ return xpcPartitionDown;973973+ }974974+975975+ part_nasid_pa = part->remote_rp_pa +976976+ (u64) &((struct xpc_rsvd_page *) 0)->part_nasids;977977+978978+ bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),979979+ L1_CACHE_ALIGN(XP_NASID_MASK_BYTES),980980+ (BTE_NOTIFY | BTE_WACQUIRE), NULL);981981+982982+ return xpc_map_bte_errors(bte_res);983983+}984984+
+715
arch/ia64/sn/kernel/xpnet.c
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.77+ */88+99+1010+/*1111+ * Cross Partition Network Interface (XPNET) support1212+ *1313+ * XPNET provides a virtual network layered on top of the Cross1414+ * Partition communication layer.1515+ *1616+ * XPNET provides direct point-to-point and broadcast-like support1717+ * for an ethernet-like device. The ethernet broadcast medium is1818+ * replaced with a point-to-point message structure which passes1919+ * pointers to a DMA-capable block that a remote partition should2020+ * retrieve and pass to the upper level networking layer.2121+ *2222+ */2323+2424+2525+#include <linux/config.h>2626+#include <linux/module.h>2727+#include <linux/kernel.h>2828+#include <linux/pci.h>2929+#include <linux/init.h>3030+#include <linux/ioport.h>3131+#include <linux/netdevice.h>3232+#include <linux/etherdevice.h>3333+#include <linux/delay.h>3434+#include <linux/ethtool.h>3535+#include <linux/mii.h>3636+#include <linux/smp.h>3737+#include <linux/string.h>3838+#include <asm/sn/bte.h>3939+#include <asm/sn/io.h>4040+#include <asm/sn/sn_sal.h>4141+#include <asm/types.h>4242+#include <asm/atomic.h>4343+#include <asm/sn/xp.h>4444+4545+4646+/*4747+ * The message payload transferred by XPC.4848+ *4949+ * buf_pa is the physical address where the DMA should pull from.5050+ *5151+ * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a5252+ * cacheline boundary. To accomplish this, we record the number of5353+ * bytes from the beginning of the first cacheline to the first useful5454+ * byte of the skb (leadin_ignore) and the number of bytes from the5555+ * last useful byte of the skb to the end of the last cacheline5656+ * (tailout_ignore).5757+ *5858+ * size is the number of bytes to transfer which includes the skb->len5959+ * (useful bytes of the senders skb) plus the leadin and tailout6060+ */6161+struct xpnet_message {6262+ u16 version; /* Version for this message */6363+ u16 embedded_bytes; /* #of bytes embedded in XPC message */6464+ u32 magic; /* Special number indicating this is xpnet */6565+ u64 buf_pa; /* phys address of buffer to retrieve */6666+ u32 size; /* #of bytes in buffer */6767+ u8 leadin_ignore; /* #of bytes to ignore at the beginning */6868+ u8 tailout_ignore; /* #of bytes to ignore at the end */6969+ unsigned char data; /* body of small packets */7070+};7171+7272+/*7373+ * Determine the size of our message, the cacheline aligned size,7474+ * and then the number of message will request from XPC.7575+ *7676+ * XPC expects each message to exist in an individual cacheline.7777+ */7878+#define XPNET_MSG_SIZE (L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET)7979+#define XPNET_MSG_DATA_MAX \8080+ (XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data))8181+#define XPNET_MSG_ALIGNED_SIZE (L1_CACHE_ALIGN(XPNET_MSG_SIZE))8282+#define XPNET_MSG_NENTRIES (PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)8383+8484+8585+#define XPNET_MAX_KTHREADS (XPNET_MSG_NENTRIES + 1)8686+#define XPNET_MAX_IDLE_KTHREADS (XPNET_MSG_NENTRIES + 1)8787+8888+/*8989+ * Version number of XPNET implementation. XPNET can always talk to versions9090+ * with same major #, and never talk to versions with a different version.9191+ */9292+#define _XPNET_VERSION(_major, _minor) (((_major) << 4) | (_minor))9393+#define XPNET_VERSION_MAJOR(_v) ((_v) >> 4)9494+#define XPNET_VERSION_MINOR(_v) ((_v) & 0xf)9595+9696+#define XPNET_VERSION _XPNET_VERSION(1,0) /* version 1.0 */9797+#define XPNET_VERSION_EMBED _XPNET_VERSION(1,1) /* version 1.1 */9898+#define XPNET_MAGIC 0x88786984 /* "XNET" */9999+100100+#define XPNET_VALID_MSG(_m) \101101+ ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \102102+ && (msg->magic == XPNET_MAGIC))103103+104104+#define XPNET_DEVICE_NAME "xp0"105105+106106+107107+/*108108+ * When messages are queued with xpc_send_notify, a kmalloc'd buffer109109+ * of the following type is passed as a notification cookie. When the110110+ * notification function is called, we use the cookie to decide111111+ * whether all outstanding message sends have completed. The skb can112112+ * then be released.113113+ */114114+struct xpnet_pending_msg {115115+ struct list_head free_list;116116+ struct sk_buff *skb;117117+ atomic_t use_count;118118+};119119+120120+/* driver specific structure pointed to by the device structure */121121+struct xpnet_dev_private {122122+ struct net_device_stats stats;123123+};124124+125125+struct net_device *xpnet_device;126126+127127+/*128128+ * When we are notified of other partitions activating, we add them to129129+ * our bitmask of partitions to which we broadcast.130130+ */131131+static u64 xpnet_broadcast_partitions;132132+/* protect above */133133+static spinlock_t xpnet_broadcast_lock = SPIN_LOCK_UNLOCKED;134134+135135+/*136136+ * Since the Block Transfer Engine (BTE) is being used for the transfer137137+ * and it relies upon cache-line size transfers, we need to reserve at138138+ * least one cache-line for head and tail alignment. The BTE is139139+ * limited to 8MB transfers.140140+ *141141+ * Testing has shown that changing MTU to greater than 64KB has no effect142142+ * on TCP as the two sides negotiate a Max Segment Size that is limited143143+ * to 64K. Other protocols May use packets greater than this, but for144144+ * now, the default is 64KB.145145+ */146146+#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)147147+/* 32KB has been determined to be the ideal */148148+#define XPNET_DEF_MTU (0x8000UL)149149+150150+151151+/*152152+ * The partition id is encapsulated in the MAC address. The following153153+ * define locates the octet the partid is in.154154+ */155155+#define XPNET_PARTID_OCTET 1156156+#define XPNET_LICENSE_OCTET 2157157+158158+159159+/*160160+ * Define the XPNET debug device structure that is to be used with dev_dbg(),161161+ * dev_err(), dev_warn(), and dev_info().162162+ */163163+struct device_driver xpnet_dbg_name = {164164+ .name = "xpnet"165165+};166166+167167+struct device xpnet_dbg_subname = {168168+ .bus_id = {0}, /* set to "" */169169+ .driver = &xpnet_dbg_name170170+};171171+172172+struct device *xpnet = &xpnet_dbg_subname;173173+174174+/*175175+ * Packet was recevied by XPC and forwarded to us.176176+ */177177+static void178178+xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)179179+{180180+ struct sk_buff *skb;181181+ bte_result_t bret;182182+ struct xpnet_dev_private *priv =183183+ (struct xpnet_dev_private *) xpnet_device->priv;184184+185185+186186+ if (!XPNET_VALID_MSG(msg)) {187187+ /*188188+ * Packet with a different XPC version. Ignore.189189+ */190190+ xpc_received(partid, channel, (void *) msg);191191+192192+ priv->stats.rx_errors++;193193+194194+ return;195195+ }196196+ dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,197197+ msg->leadin_ignore, msg->tailout_ignore);198198+199199+200200+ /* reserve an extra cache line */201201+ skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);202202+ if (!skb) {203203+ dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",204204+ msg->size + L1_CACHE_BYTES);205205+206206+ xpc_received(partid, channel, (void *) msg);207207+208208+ priv->stats.rx_errors++;209209+210210+ return;211211+ }212212+213213+ /*214214+ * The allocated skb has some reserved space.215215+ * In order to use bte_copy, we need to get the216216+ * skb->data pointer moved forward.217217+ */218218+ skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &219219+ (L1_CACHE_BYTES - 1)) +220220+ msg->leadin_ignore));221221+222222+ /*223223+ * Update the tail pointer to indicate data actually224224+ * transferred.225225+ */226226+ skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));227227+228228+ /*229229+ * Move the data over from the the other side.230230+ */231231+ if ((XPNET_VERSION_MINOR(msg->version) == 1) &&232232+ (msg->embedded_bytes != 0)) {233233+ dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "234234+ "%lu)\n", skb->data, &msg->data,235235+ (size_t) msg->embedded_bytes);236236+237237+ memcpy(skb->data, &msg->data, (size_t) msg->embedded_bytes);238238+ } else {239239+ dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"240240+ "bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa,241241+ (void *)__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),242242+ msg->size);243243+244244+ bret = bte_copy(msg->buf_pa,245245+ __pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),246246+ msg->size, (BTE_NOTIFY | BTE_WACQUIRE), NULL);247247+248248+ if (bret != BTE_SUCCESS) {249249+ // >>> Need better way of cleaning skb. Currently skb250250+ // >>> appears in_use and we can't just call251251+ // >>> dev_kfree_skb.252252+ dev_err(xpnet, "bte_copy(0x%p, 0x%p, 0x%hx) returned "253253+ "error=0x%x\n", (void *)msg->buf_pa,254254+ (void *)__pa((u64)skb->data &255255+ ~(L1_CACHE_BYTES - 1)),256256+ msg->size, bret);257257+258258+ xpc_received(partid, channel, (void *) msg);259259+260260+ priv->stats.rx_errors++;261261+262262+ return;263263+ }264264+ }265265+266266+ dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "267267+ "skb->end=0x%p skb->len=%d\n", (void *) skb->head,268268+ (void *) skb->data, (void *) skb->tail, (void *) skb->end,269269+ skb->len);270270+271271+ skb->dev = xpnet_device;272272+ skb->protocol = eth_type_trans(skb, xpnet_device);273273+ skb->ip_summed = CHECKSUM_UNNECESSARY;274274+275275+ dev_dbg(xpnet, "passing skb to network layer; \n\tskb->head=0x%p "276276+ "skb->data=0x%p skb->tail=0x%p skb->end=0x%p skb->len=%d\n",277277+ (void *) skb->head, (void *) skb->data, (void *) skb->tail,278278+ (void *) skb->end, skb->len);279279+280280+281281+ xpnet_device->last_rx = jiffies;282282+ priv->stats.rx_packets++;283283+ priv->stats.rx_bytes += skb->len + ETH_HLEN;284284+285285+ netif_rx_ni(skb);286286+ xpc_received(partid, channel, (void *) msg);287287+}288288+289289+290290+/*291291+ * This is the handler which XPC calls during any sort of change in292292+ * state or message reception on a connection.293293+ */294294+static void295295+xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel,296296+ void *data, void *key)297297+{298298+ long bp;299299+300300+301301+ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);302302+ DBUG_ON(channel != XPC_NET_CHANNEL);303303+304304+ switch(reason) {305305+ case xpcMsgReceived: /* message received */306306+ DBUG_ON(data == NULL);307307+308308+ xpnet_receive(partid, channel, (struct xpnet_message *) data);309309+ break;310310+311311+ case xpcConnected: /* connection completed to a partition */312312+ spin_lock_bh(&xpnet_broadcast_lock);313313+ xpnet_broadcast_partitions |= 1UL << (partid -1 );314314+ bp = xpnet_broadcast_partitions;315315+ spin_unlock_bh(&xpnet_broadcast_lock);316316+317317+ netif_carrier_on(xpnet_device);318318+319319+ dev_dbg(xpnet, "%s connection created to partition %d; "320320+ "xpnet_broadcast_partitions=0x%lx\n",321321+ xpnet_device->name, partid, bp);322322+ break;323323+324324+ default:325325+ spin_lock_bh(&xpnet_broadcast_lock);326326+ xpnet_broadcast_partitions &= ~(1UL << (partid -1 ));327327+ bp = xpnet_broadcast_partitions;328328+ spin_unlock_bh(&xpnet_broadcast_lock);329329+330330+ if (bp == 0) {331331+ netif_carrier_off(xpnet_device);332332+ }333333+334334+ dev_dbg(xpnet, "%s disconnected from partition %d; "335335+ "xpnet_broadcast_partitions=0x%lx\n",336336+ xpnet_device->name, partid, bp);337337+ break;338338+339339+ }340340+}341341+342342+343343+static int344344+xpnet_dev_open(struct net_device *dev)345345+{346346+ enum xpc_retval ret;347347+348348+349349+ dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %d, "350350+ "%d)\n", XPC_NET_CHANNEL, xpnet_connection_activity,351351+ XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS,352352+ XPNET_MAX_IDLE_KTHREADS);353353+354354+ ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,355355+ XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,356356+ XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);357357+ if (ret != xpcSuccess) {358358+ dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "359359+ "ret=%d\n", dev->name, ret);360360+361361+ return -ENOMEM;362362+ }363363+364364+ dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);365365+366366+ return 0;367367+}368368+369369+370370+static int371371+xpnet_dev_stop(struct net_device *dev)372372+{373373+ xpc_disconnect(XPC_NET_CHANNEL);374374+375375+ dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);376376+377377+ return 0;378378+}379379+380380+381381+static int382382+xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)383383+{384384+ /* 68 comes from min TCP+IP+MAC header */385385+ if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {386386+ dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "387387+ "between 68 and %ld\n", dev->name, new_mtu,388388+ XPNET_MAX_MTU);389389+ return -EINVAL;390390+ }391391+392392+ dev->mtu = new_mtu;393393+ dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);394394+ return 0;395395+}396396+397397+398398+/*399399+ * Required for the net_device structure.400400+ */401401+static int402402+xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)403403+{404404+ return 0;405405+}406406+407407+408408+/*409409+ * Return statistics to the caller.410410+ */411411+static struct net_device_stats *412412+xpnet_dev_get_stats(struct net_device *dev)413413+{414414+ struct xpnet_dev_private *priv;415415+416416+417417+ priv = (struct xpnet_dev_private *) dev->priv;418418+419419+ return &priv->stats;420420+}421421+422422+423423+/*424424+ * Notification that the other end has received the message and425425+ * DMA'd the skb information. At this point, they are done with426426+ * our side. When all recipients are done processing, we427427+ * release the skb and then release our pending message structure.428428+ */429429+static void430430+xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel,431431+ void *__qm)432432+{433433+ struct xpnet_pending_msg *queued_msg =434434+ (struct xpnet_pending_msg *) __qm;435435+436436+437437+ DBUG_ON(queued_msg == NULL);438438+439439+ dev_dbg(xpnet, "message to %d notified with reason %d\n",440440+ partid, reason);441441+442442+ if (atomic_dec_return(&queued_msg->use_count) == 0) {443443+ dev_dbg(xpnet, "all acks for skb->head=-x%p\n",444444+ (void *) queued_msg->skb->head);445445+446446+ dev_kfree_skb_any(queued_msg->skb);447447+ kfree(queued_msg);448448+ }449449+}450450+451451+452452+/*453453+ * Network layer has formatted a packet (skb) and is ready to place it454454+ * "on the wire". Prepare and send an xpnet_message to all partitions455455+ * which have connected with us and are targets of this packet.456456+ *457457+ * MAC-NOTE: For the XPNET driver, the MAC address contains the458458+ * destination partition_id. If the destination partition id word459459+ * is 0xff, this packet is to broadcast to all partitions.460460+ */461461+static int462462+xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)463463+{464464+ struct xpnet_pending_msg *queued_msg;465465+ enum xpc_retval ret;466466+ struct xpnet_message *msg;467467+ u64 start_addr, end_addr;468468+ long dp;469469+ u8 second_mac_octet;470470+ partid_t dest_partid;471471+ struct xpnet_dev_private *priv;472472+ u16 embedded_bytes;473473+474474+475475+ priv = (struct xpnet_dev_private *) dev->priv;476476+477477+478478+ dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "479479+ "skb->end=0x%p skb->len=%d\n", (void *) skb->head,480480+ (void *) skb->data, (void *) skb->tail, (void *) skb->end,481481+ skb->len);482482+483483+484484+ /*485485+ * The xpnet_pending_msg tracks how many outstanding486486+ * xpc_send_notifies are relying on this skb. When none487487+ * remain, release the skb.488488+ */489489+ queued_msg = kmalloc(sizeof(struct xpnet_pending_msg), GFP_ATOMIC);490490+ if (queued_msg == NULL) {491491+ dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "492492+ "packet\n", sizeof(struct xpnet_pending_msg));493493+494494+ priv->stats.tx_errors++;495495+496496+ return -ENOMEM;497497+ }498498+499499+500500+ /* get the beginning of the first cacheline and end of last */501501+ start_addr = ((u64) skb->data & ~(L1_CACHE_BYTES - 1));502502+ end_addr = L1_CACHE_ALIGN((u64) skb->tail);503503+504504+ /* calculate how many bytes to embed in the XPC message */505505+ embedded_bytes = 0;506506+ if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {507507+ /* skb->data does fit so embed */508508+ embedded_bytes = skb->len;509509+ }510510+511511+512512+ /*513513+ * Since the send occurs asynchronously, we set the count to one514514+ * and begin sending. Any sends that happen to complete before515515+ * we are done sending will not free the skb. We will be left516516+ * with that task during exit. This also handles the case of517517+ * a packet destined for a partition which is no longer up.518518+ */519519+ atomic_set(&queued_msg->use_count, 1);520520+ queued_msg->skb = skb;521521+522522+523523+ second_mac_octet = skb->data[XPNET_PARTID_OCTET];524524+ if (second_mac_octet == 0xff) {525525+ /* we are being asked to broadcast to all partitions */526526+ dp = xpnet_broadcast_partitions;527527+ } else if (second_mac_octet != 0) {528528+ dp = xpnet_broadcast_partitions &529529+ (1UL << (second_mac_octet - 1));530530+ } else {531531+ /* 0 is an invalid partid. Ignore */532532+ dp = 0;533533+ }534534+ dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp);535535+536536+ /*537537+ * If we wanted to allow promiscous mode to work like an538538+ * unswitched network, this would be a good point to OR in a539539+ * mask of partitions which should be receiving all packets.540540+ */541541+542542+ /*543543+ * Main send loop.544544+ */545545+ for (dest_partid = 1; dp && dest_partid < XP_MAX_PARTITIONS;546546+ dest_partid++) {547547+548548+549549+ if (!(dp & (1UL << (dest_partid - 1)))) {550550+ /* not destined for this partition */551551+ continue;552552+ }553553+554554+ /* remove this partition from the destinations mask */555555+ dp &= ~(1UL << (dest_partid - 1));556556+557557+558558+ /* found a partition to send to */559559+560560+ ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL,561561+ XPC_NOWAIT, (void **)&msg);562562+ if (unlikely(ret != xpcSuccess)) {563563+ continue;564564+ }565565+566566+ msg->embedded_bytes = embedded_bytes;567567+ if (unlikely(embedded_bytes != 0)) {568568+ msg->version = XPNET_VERSION_EMBED;569569+ dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",570570+ &msg->data, skb->data, (size_t) embedded_bytes);571571+ memcpy(&msg->data, skb->data, (size_t) embedded_bytes);572572+ } else {573573+ msg->version = XPNET_VERSION;574574+ }575575+ msg->magic = XPNET_MAGIC;576576+ msg->size = end_addr - start_addr;577577+ msg->leadin_ignore = (u64) skb->data - start_addr;578578+ msg->tailout_ignore = end_addr - (u64) skb->tail;579579+ msg->buf_pa = __pa(start_addr);580580+581581+ dev_dbg(xpnet, "sending XPC message to %d:%d\nmsg->buf_pa="582582+ "0x%lx, msg->size=%u, msg->leadin_ignore=%u, "583583+ "msg->tailout_ignore=%u\n", dest_partid,584584+ XPC_NET_CHANNEL, msg->buf_pa, msg->size,585585+ msg->leadin_ignore, msg->tailout_ignore);586586+587587+588588+ atomic_inc(&queued_msg->use_count);589589+590590+ ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg,591591+ xpnet_send_completed, queued_msg);592592+ if (unlikely(ret != xpcSuccess)) {593593+ atomic_dec(&queued_msg->use_count);594594+ continue;595595+ }596596+597597+ }598598+599599+ if (atomic_dec_return(&queued_msg->use_count) == 0) {600600+ dev_dbg(xpnet, "no partitions to receive packet destined for "601601+ "%d\n", dest_partid);602602+603603+604604+ dev_kfree_skb(skb);605605+ kfree(queued_msg);606606+ }607607+608608+ priv->stats.tx_packets++;609609+ priv->stats.tx_bytes += skb->len;610610+611611+ return 0;612612+}613613+614614+615615+/*616616+ * Deal with transmit timeouts coming from the network layer.617617+ */618618+static void619619+xpnet_dev_tx_timeout (struct net_device *dev)620620+{621621+ struct xpnet_dev_private *priv;622622+623623+624624+ priv = (struct xpnet_dev_private *) dev->priv;625625+626626+ priv->stats.tx_errors++;627627+ return;628628+}629629+630630+631631+static int __init632632+xpnet_init(void)633633+{634634+ int i;635635+ u32 license_num;636636+ int result = -ENOMEM;637637+638638+639639+ dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);640640+641641+ /*642642+ * use ether_setup() to init the majority of our device643643+ * structure and then override the necessary pieces.644644+ */645645+ xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),646646+ XPNET_DEVICE_NAME, ether_setup);647647+ if (xpnet_device == NULL) {648648+ return -ENOMEM;649649+ }650650+651651+ netif_carrier_off(xpnet_device);652652+653653+ xpnet_device->mtu = XPNET_DEF_MTU;654654+ xpnet_device->change_mtu = xpnet_dev_change_mtu;655655+ xpnet_device->open = xpnet_dev_open;656656+ xpnet_device->get_stats = xpnet_dev_get_stats;657657+ xpnet_device->stop = xpnet_dev_stop;658658+ xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;659659+ xpnet_device->tx_timeout = xpnet_dev_tx_timeout;660660+ xpnet_device->set_config = xpnet_dev_set_config;661661+662662+ /*663663+ * Multicast assumes the LSB of the first octet is set for multicast664664+ * MAC addresses. We chose the first octet of the MAC to be unlikely665665+ * to collide with any vendor's officially issued MAC.666666+ */667667+ xpnet_device->dev_addr[0] = 0xfe;668668+ xpnet_device->dev_addr[XPNET_PARTID_OCTET] = sn_partition_id;669669+ license_num = sn_partition_serial_number_val();670670+ for (i = 3; i >= 0; i--) {671671+ xpnet_device->dev_addr[XPNET_LICENSE_OCTET + i] =672672+ license_num & 0xff;673673+ license_num = license_num >> 8;674674+ }675675+676676+ /*677677+ * ether_setup() sets this to a multicast device. We are678678+ * really not supporting multicast at this time.679679+ */680680+ xpnet_device->flags &= ~IFF_MULTICAST;681681+682682+ /*683683+ * No need to checksum as it is a DMA transfer. The BTE will684684+ * report an error if the data is not retrievable and the685685+ * packet will be dropped.686686+ */687687+ xpnet_device->features = NETIF_F_NO_CSUM;688688+689689+ result = register_netdev(xpnet_device);690690+ if (result != 0) {691691+ free_netdev(xpnet_device);692692+ }693693+694694+ return result;695695+}696696+module_init(xpnet_init);697697+698698+699699+static void __exit700700+xpnet_exit(void)701701+{702702+ dev_info(xpnet, "unregistering network device %s\n",703703+ xpnet_device[0].name);704704+705705+ unregister_netdev(xpnet_device);706706+707707+ free_netdev(xpnet_device);708708+}709709+module_exit(xpnet_exit);710710+711711+712712+MODULE_AUTHOR("Silicon Graphics, Inc.");713713+MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");714714+MODULE_LICENSE("GPL");715715+
···408408409409config SGI_MBCS410410 tristate "SGI FPGA Core Services driver support"411411- depends on (IA64_SGI_SN2 || IA64_GENERIC)411411+ depends on SGI_TIOCX412412 help413413 If you have an SGI Altix with an attached SABrick414414 say Y or M here, otherwise say N.
···55 *66 * SGI specific setup.77 *88- * Copyright (C) 1995-1997,1999,2001-2004 Silicon Graphics, Inc. All rights reserved.88+ * Copyright (C) 1995-1997,1999,2001-2005 Silicon Graphics, Inc. All rights reserved.99 * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)1010 */1111#ifndef _ASM_IA64_SN_ARCH_H···4646 */4747#define MAX_COMPACT_NODES 20484848#define CPUS_PER_NODE 44949+5050+5151+/*5252+ * Compact node ID to nasid mappings kept in the per-cpu data areas of each5353+ * cpu.5454+ */5555+DECLARE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]);5656+#define sn_cnodeid_to_nasid (&__get_cpu_var(__sn_cnodeid_to_nasid[0]))5757+5858+5959+6060+extern u8 sn_partition_id;6161+extern u8 sn_system_size;6262+extern u8 sn_sharing_domain_size;6363+extern u8 sn_region_size;49645065extern void sn_flush_all_caches(long addr, long bytes);5166
-85
include/asm-ia64/sn/fetchop.h
···11-/*22- *33- * This file is subject to the terms and conditions of the GNU General Public44- * License. See the file "COPYING" in the main directory of this archive55- * for more details.66- *77- * Copyright (c) 2001-2004 Silicon Graphics, Inc. All rights reserved.88- */99-1010-#ifndef _ASM_IA64_SN_FETCHOP_H1111-#define _ASM_IA64_SN_FETCHOP_H1212-1313-#include <linux/config.h>1414-1515-#define FETCHOP_BASENAME "sgi_fetchop"1616-#define FETCHOP_FULLNAME "/dev/sgi_fetchop"1717-1818-1919-2020-#define FETCHOP_VAR_SIZE 64 /* 64 byte per fetchop variable */2121-2222-#define FETCHOP_LOAD 02323-#define FETCHOP_INCREMENT 82424-#define FETCHOP_DECREMENT 162525-#define FETCHOP_CLEAR 242626-2727-#define FETCHOP_STORE 02828-#define FETCHOP_AND 242929-#define FETCHOP_OR 323030-3131-#define FETCHOP_CLEAR_CACHE 563232-3333-#define FETCHOP_LOAD_OP(addr, op) ( \3434- *(volatile long *)((char*) (addr) + (op)))3535-3636-#define FETCHOP_STORE_OP(addr, op, x) ( \3737- *(volatile long *)((char*) (addr) + (op)) = (long) (x))3838-3939-#ifdef __KERNEL__4040-4141-/*4242- * Convert a region 6 (kaddr) address to the address of the fetchop variable4343- */4444-#define FETCHOP_KADDR_TO_MSPEC_ADDR(kaddr) TO_MSPEC(kaddr)4545-4646-4747-/*4848- * Each Atomic Memory Operation (AMO formerly known as fetchop)4949- * variable is 64 bytes long. The first 8 bytes are used. The5050- * remaining 56 bytes are unaddressable due to the operation taking5151- * that portion of the address.5252- * 5353- * NOTE: The AMO_t _MUST_ be placed in either the first or second half5454- * of the cache line. The cache line _MUST NOT_ be used for anything5555- * other than additional AMO_t entries. This is because there are two5656- * addresses which reference the same physical cache line. One will5757- * be a cached entry with the memory type bits all set. This address5858- * may be loaded into processor cache. The AMO_t will be referenced5959- * uncached via the memory special memory type. If any portion of the6060- * cached cache-line is modified, when that line is flushed, it will6161- * overwrite the uncached value in physical memory and lead to6262- * inconsistency.6363- */6464-typedef struct {6565- u64 variable;6666- u64 unused[7];6767-} AMO_t;6868-6969-7070-/*7171- * The following APIs are externalized to the kernel to allocate/free pages of7272- * fetchop variables.7373- * fetchop_kalloc_page - Allocate/initialize 1 fetchop page on the7474- * specified cnode. 7575- * fetchop_kfree_page - Free a previously allocated fetchop page7676- */7777-7878-unsigned long fetchop_kalloc_page(int nid);7979-void fetchop_kfree_page(unsigned long maddr);8080-8181-8282-#endif /* __KERNEL__ */8383-8484-#endif /* _ASM_IA64_SN_FETCHOP_H */8585-
+2-1
include/asm-ia64/sn/l1.h
···2929#define L1_BRICKTYPE_CHI_CG 0x76 /* v */3030#define L1_BRICKTYPE_X 0x78 /* x */3131#define L1_BRICKTYPE_X2 0x79 /* y */3232-#define L1_BRICKTYPE_SA 0x5e /* ^ */ /* TIO bringup brick */3232+#define L1_BRICKTYPE_SA 0x5e /* ^ */3333#define L1_BRICKTYPE_PA 0x6a /* j */3434#define L1_BRICKTYPE_IA 0x6b /* k */3535+#define L1_BRICKTYPE_ATHENA 0x2b /* + */35363637#endif /* _ASM_IA64_SN_L1_H */
+6-9
include/asm-ia64/sn/nodepda.h
···1313#include <asm/irq.h>1414#include <asm/sn/arch.h>1515#include <asm/sn/intr.h>1616-#include <asm/sn/pda.h>1716#include <asm/sn/bte.h>18171918/*···6667 * The next set of definitions provides this.6768 * Routines are expected to use 6869 *6969- * nodepda -> to access node PDA for the node on which code is running7070- * subnodepda -> to access subnode PDA for the subnode on which code is running7171- *7272- * NODEPDA(cnode) -> to access node PDA for cnodeid 7373- * SUBNODEPDA(cnode,sn) -> to access subnode PDA for cnodeid/subnode7070+ * sn_nodepda - to access node PDA for the node on which code is running7171+ * NODEPDA(cnodeid) - to access node PDA for cnodeid7472 */75737676-#define nodepda pda->p_nodepda /* Ptr to this node's PDA */7777-#define NODEPDA(cnode) (nodepda->pernode_pdaindr[cnode])7474+DECLARE_PER_CPU(struct nodepda_s *, __sn_nodepda);7575+#define sn_nodepda (__get_cpu_var(__sn_nodepda))7676+#define NODEPDA(cnodeid) (sn_nodepda->pernode_pdaindr[cnodeid])78777978/*8079 * Check if given a compact node id the corresponding node has all the8180 * cpus disabled. 8281 */8383-#define is_headless_node(cnode) (nr_cpus_node(cnode) == 0)8282+#define is_headless_node(cnodeid) (nr_cpus_node(cnodeid) == 0)84838584#endif /* _ASM_IA64_SN_NODEPDA_H */
-9
include/asm-ia64/sn/pda.h
···24242525typedef struct pda_s {26262727- /* Having a pointer in the begining of PDA tends to increase2828- * the chance of having this pointer in cache. (Yes something2929- * else gets pushed out). Doing this reduces the number of memory3030- * access to all nodepda variables to be one3131- */3232- struct nodepda_s *p_nodepda; /* Pointer to Per node PDA */3333- struct subnodepda_s *p_subnodepda; /* Pointer to CPU subnode PDA */3434-3527 /*3628 * Support for SN LEDs3729 */···41494250 unsigned long sn_soft_irr[4];4351 unsigned long sn_in_service_ivecs[4];4444- short cnodeid_to_nasid_table[MAX_NUMNODES];4552 int sn_lb_int_war_ticks;4653 int sn_last_irq;4754 int sn_first_irq;
+24
include/asm-ia64/sn/shub_mmr.h
···385385#define SH_EVENT_OCCURRED_RTC3_INT_MASK 0x0000000004000000386386387387/* ==================================================================== */388388+/* Register "SH_IPI_ACCESS" */389389+/* CPU interrupt Access Permission Bits */390390+/* ==================================================================== */391391+392392+#define SH1_IPI_ACCESS 0x0000000110060480393393+#define SH2_IPI_ACCESS0 0x0000000010060c00394394+#define SH2_IPI_ACCESS1 0x0000000010060c80395395+#define SH2_IPI_ACCESS2 0x0000000010060d00396396+#define SH2_IPI_ACCESS3 0x0000000010060d80397397+398398+/* ==================================================================== */388399/* Register "SH_INT_CMPB" */389400/* RTC Compare Value for Processor B */390401/* ==================================================================== */···440429#define SH_INT_CMPD_REAL_TIME_CMPD_SHFT 0441430#define SH_INT_CMPD_REAL_TIME_CMPD_MASK 0x007fffffffffffff442431432432+/* ==================================================================== */433433+/* Register "SH_MD_DQLP_MMR_DIR_PRIVEC0" */434434+/* privilege vector for acc=0 */435435+/* ==================================================================== */436436+437437+#define SH1_MD_DQLP_MMR_DIR_PRIVEC0 0x0000000100030300438438+439439+/* ==================================================================== */440440+/* Register "SH_MD_DQRP_MMR_DIR_PRIVEC0" */441441+/* privilege vector for acc=0 */442442+/* ==================================================================== */443443+444444+#define SH1_MD_DQRP_MMR_DIR_PRIVEC0 0x0000000100050300443445444446/* ==================================================================== */445447/* Some MMRs are functionally identical (or close enough) on both SHUB1 */
+1462-1580
include/asm-ia64/sn/shubio.h
···33 * License. See the file "COPYING" in the main directory of this archive44 * for more details.55 *66- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.66+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.77 */8899#ifndef _ASM_IA64_SN_SHUBIO_H1010#define _ASM_IA64_SN_SHUBIO_H11111212-#define HUB_WIDGET_ID_MAX 0xf1313-#define IIO_NUM_ITTES 71414-#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)1212+#define HUB_WIDGET_ID_MAX 0xf1313+#define IIO_NUM_ITTES 71414+#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)15151616-#define IIO_WID 0x00400000 /* Crosstalk Widget Identification */1717- /* This register is also accessible from1818- * Crosstalk at address 0x0. */1919-#define IIO_WSTAT 0x00400008 /* Crosstalk Widget Status */2020-#define IIO_WCR 0x00400020 /* Crosstalk Widget Control Register */2121-#define IIO_ILAPR 0x00400100 /* IO Local Access Protection Register */2222-#define IIO_ILAPO 0x00400108 /* IO Local Access Protection Override */2323-#define IIO_IOWA 0x00400110 /* IO Outbound Widget Access */2424-#define IIO_IIWA 0x00400118 /* IO Inbound Widget Access */2525-#define IIO_IIDEM 0x00400120 /* IO Inbound Device Error Mask */2626-#define IIO_ILCSR 0x00400128 /* IO LLP Control and Status Register */2727-#define IIO_ILLR 0x00400130 /* IO LLP Log Register */2828-#define IIO_IIDSR 0x00400138 /* IO Interrupt Destination */1616+#define IIO_WID 0x00400000 /* Crosstalk Widget Identification */1717+ /* This register is also accessible from1818+ * Crosstalk at address 0x0. */1919+#define IIO_WSTAT 0x00400008 /* Crosstalk Widget Status */2020+#define IIO_WCR 0x00400020 /* Crosstalk Widget Control Register */2121+#define IIO_ILAPR 0x00400100 /* IO Local Access Protection Register */2222+#define IIO_ILAPO 0x00400108 /* IO Local Access Protection Override */2323+#define IIO_IOWA 0x00400110 /* IO Outbound Widget Access */2424+#define IIO_IIWA 0x00400118 /* IO Inbound Widget Access */2525+#define IIO_IIDEM 0x00400120 /* IO Inbound Device Error Mask */2626+#define IIO_ILCSR 0x00400128 /* IO LLP Control and Status Register */2727+#define IIO_ILLR 0x00400130 /* IO LLP Log Register */2828+#define IIO_IIDSR 0x00400138 /* IO Interrupt Destination */29293030-#define IIO_IGFX0 0x00400140 /* IO Graphics Node-Widget Map 0 */3131-#define IIO_IGFX1 0x00400148 /* IO Graphics Node-Widget Map 1 */3030+#define IIO_IGFX0 0x00400140 /* IO Graphics Node-Widget Map 0 */3131+#define IIO_IGFX1 0x00400148 /* IO Graphics Node-Widget Map 1 */32323333-#define IIO_ISCR0 0x00400150 /* IO Scratch Register 0 */3434-#define IIO_ISCR1 0x00400158 /* IO Scratch Register 1 */3333+#define IIO_ISCR0 0x00400150 /* IO Scratch Register 0 */3434+#define IIO_ISCR1 0x00400158 /* IO Scratch Register 1 */35353636-#define IIO_ITTE1 0x00400160 /* IO Translation Table Entry 1 */3737-#define IIO_ITTE2 0x00400168 /* IO Translation Table Entry 2 */3838-#define IIO_ITTE3 0x00400170 /* IO Translation Table Entry 3 */3939-#define IIO_ITTE4 0x00400178 /* IO Translation Table Entry 4 */4040-#define IIO_ITTE5 0x00400180 /* IO Translation Table Entry 5 */4141-#define IIO_ITTE6 0x00400188 /* IO Translation Table Entry 6 */4242-#define IIO_ITTE7 0x00400190 /* IO Translation Table Entry 7 */3636+#define IIO_ITTE1 0x00400160 /* IO Translation Table Entry 1 */3737+#define IIO_ITTE2 0x00400168 /* IO Translation Table Entry 2 */3838+#define IIO_ITTE3 0x00400170 /* IO Translation Table Entry 3 */3939+#define IIO_ITTE4 0x00400178 /* IO Translation Table Entry 4 */4040+#define IIO_ITTE5 0x00400180 /* IO Translation Table Entry 5 */4141+#define IIO_ITTE6 0x00400188 /* IO Translation Table Entry 6 */4242+#define IIO_ITTE7 0x00400190 /* IO Translation Table Entry 7 */43434444-#define IIO_IPRB0 0x00400198 /* IO PRB Entry 0 */4545-#define IIO_IPRB8 0x004001A0 /* IO PRB Entry 8 */4646-#define IIO_IPRB9 0x004001A8 /* IO PRB Entry 9 */4747-#define IIO_IPRBA 0x004001B0 /* IO PRB Entry A */4848-#define IIO_IPRBB 0x004001B8 /* IO PRB Entry B */4949-#define IIO_IPRBC 0x004001C0 /* IO PRB Entry C */5050-#define IIO_IPRBD 0x004001C8 /* IO PRB Entry D */5151-#define IIO_IPRBE 0x004001D0 /* IO PRB Entry E */5252-#define IIO_IPRBF 0x004001D8 /* IO PRB Entry F */4444+#define IIO_IPRB0 0x00400198 /* IO PRB Entry 0 */4545+#define IIO_IPRB8 0x004001A0 /* IO PRB Entry 8 */4646+#define IIO_IPRB9 0x004001A8 /* IO PRB Entry 9 */4747+#define IIO_IPRBA 0x004001B0 /* IO PRB Entry A */4848+#define IIO_IPRBB 0x004001B8 /* IO PRB Entry B */4949+#define IIO_IPRBC 0x004001C0 /* IO PRB Entry C */5050+#define IIO_IPRBD 0x004001C8 /* IO PRB Entry D */5151+#define IIO_IPRBE 0x004001D0 /* IO PRB Entry E */5252+#define IIO_IPRBF 0x004001D8 /* IO PRB Entry F */53535454-#define IIO_IXCC 0x004001E0 /* IO Crosstalk Credit Count Timeout */5555-#define IIO_IMEM 0x004001E8 /* IO Miscellaneous Error Mask */5656-#define IIO_IXTT 0x004001F0 /* IO Crosstalk Timeout Threshold */5757-#define IIO_IECLR 0x004001F8 /* IO Error Clear Register */5858-#define IIO_IBCR 0x00400200 /* IO BTE Control Register */5454+#define IIO_IXCC 0x004001E0 /* IO Crosstalk Credit Count Timeout */5555+#define IIO_IMEM 0x004001E8 /* IO Miscellaneous Error Mask */5656+#define IIO_IXTT 0x004001F0 /* IO Crosstalk Timeout Threshold */5757+#define IIO_IECLR 0x004001F8 /* IO Error Clear Register */5858+#define IIO_IBCR 0x00400200 /* IO BTE Control Register */59596060-#define IIO_IXSM 0x00400208 /* IO Crosstalk Spurious Message */6161-#define IIO_IXSS 0x00400210 /* IO Crosstalk Spurious Sideband */6060+#define IIO_IXSM 0x00400208 /* IO Crosstalk Spurious Message */6161+#define IIO_IXSS 0x00400210 /* IO Crosstalk Spurious Sideband */62626363-#define IIO_ILCT 0x00400218 /* IO LLP Channel Test */6363+#define IIO_ILCT 0x00400218 /* IO LLP Channel Test */64646565-#define IIO_IIEPH1 0x00400220 /* IO Incoming Error Packet Header, Part 1 */6666-#define IIO_IIEPH2 0x00400228 /* IO Incoming Error Packet Header, Part 2 */6565+#define IIO_IIEPH1 0x00400220 /* IO Incoming Error Packet Header, Part 1 */6666+#define IIO_IIEPH2 0x00400228 /* IO Incoming Error Packet Header, Part 2 */67676868+#define IIO_ISLAPR 0x00400230 /* IO SXB Local Access Protection Regster */6969+#define IIO_ISLAPO 0x00400238 /* IO SXB Local Access Protection Override */68706969-#define IIO_ISLAPR 0x00400230 /* IO SXB Local Access Protection Regster */7070-#define IIO_ISLAPO 0x00400238 /* IO SXB Local Access Protection Override */7171+#define IIO_IWI 0x00400240 /* IO Wrapper Interrupt Register */7272+#define IIO_IWEL 0x00400248 /* IO Wrapper Error Log Register */7373+#define IIO_IWC 0x00400250 /* IO Wrapper Control Register */7474+#define IIO_IWS 0x00400258 /* IO Wrapper Status Register */7575+#define IIO_IWEIM 0x00400260 /* IO Wrapper Error Interrupt Masking Register */71767272-#define IIO_IWI 0x00400240 /* IO Wrapper Interrupt Register */7373-#define IIO_IWEL 0x00400248 /* IO Wrapper Error Log Register */7474-#define IIO_IWC 0x00400250 /* IO Wrapper Control Register */7575-#define IIO_IWS 0x00400258 /* IO Wrapper Status Register */7676-#define IIO_IWEIM 0x00400260 /* IO Wrapper Error Interrupt Masking Register */7777+#define IIO_IPCA 0x00400300 /* IO PRB Counter Adjust */77787878-#define IIO_IPCA 0x00400300 /* IO PRB Counter Adjust */7979+#define IIO_IPRTE0_A 0x00400308 /* IO PIO Read Address Table Entry 0, Part A */8080+#define IIO_IPRTE1_A 0x00400310 /* IO PIO Read Address Table Entry 1, Part A */8181+#define IIO_IPRTE2_A 0x00400318 /* IO PIO Read Address Table Entry 2, Part A */8282+#define IIO_IPRTE3_A 0x00400320 /* IO PIO Read Address Table Entry 3, Part A */8383+#define IIO_IPRTE4_A 0x00400328 /* IO PIO Read Address Table Entry 4, Part A */8484+#define IIO_IPRTE5_A 0x00400330 /* IO PIO Read Address Table Entry 5, Part A */8585+#define IIO_IPRTE6_A 0x00400338 /* IO PIO Read Address Table Entry 6, Part A */8686+#define IIO_IPRTE7_A 0x00400340 /* IO PIO Read Address Table Entry 7, Part A */79878080-#define IIO_IPRTE0_A 0x00400308 /* IO PIO Read Address Table Entry 0, Part A */8181-#define IIO_IPRTE1_A 0x00400310 /* IO PIO Read Address Table Entry 1, Part A */8282-#define IIO_IPRTE2_A 0x00400318 /* IO PIO Read Address Table Entry 2, Part A */8383-#define IIO_IPRTE3_A 0x00400320 /* IO PIO Read Address Table Entry 3, Part A */8484-#define IIO_IPRTE4_A 0x00400328 /* IO PIO Read Address Table Entry 4, Part A */8585-#define IIO_IPRTE5_A 0x00400330 /* IO PIO Read Address Table Entry 5, Part A */8686-#define IIO_IPRTE6_A 0x00400338 /* IO PIO Read Address Table Entry 6, Part A */8787-#define IIO_IPRTE7_A 0x00400340 /* IO PIO Read Address Table Entry 7, Part A */8888+#define IIO_IPRTE0_B 0x00400348 /* IO PIO Read Address Table Entry 0, Part B */8989+#define IIO_IPRTE1_B 0x00400350 /* IO PIO Read Address Table Entry 1, Part B */9090+#define IIO_IPRTE2_B 0x00400358 /* IO PIO Read Address Table Entry 2, Part B */9191+#define IIO_IPRTE3_B 0x00400360 /* IO PIO Read Address Table Entry 3, Part B */9292+#define IIO_IPRTE4_B 0x00400368 /* IO PIO Read Address Table Entry 4, Part B */9393+#define IIO_IPRTE5_B 0x00400370 /* IO PIO Read Address Table Entry 5, Part B */9494+#define IIO_IPRTE6_B 0x00400378 /* IO PIO Read Address Table Entry 6, Part B */9595+#define IIO_IPRTE7_B 0x00400380 /* IO PIO Read Address Table Entry 7, Part B */88968989-#define IIO_IPRTE0_B 0x00400348 /* IO PIO Read Address Table Entry 0, Part B */9090-#define IIO_IPRTE1_B 0x00400350 /* IO PIO Read Address Table Entry 1, Part B */9191-#define IIO_IPRTE2_B 0x00400358 /* IO PIO Read Address Table Entry 2, Part B */9292-#define IIO_IPRTE3_B 0x00400360 /* IO PIO Read Address Table Entry 3, Part B */9393-#define IIO_IPRTE4_B 0x00400368 /* IO PIO Read Address Table Entry 4, Part B */9494-#define IIO_IPRTE5_B 0x00400370 /* IO PIO Read Address Table Entry 5, Part B */9595-#define IIO_IPRTE6_B 0x00400378 /* IO PIO Read Address Table Entry 6, Part B */9696-#define IIO_IPRTE7_B 0x00400380 /* IO PIO Read Address Table Entry 7, Part B */9797+#define IIO_IPDR 0x00400388 /* IO PIO Deallocation Register */9898+#define IIO_ICDR 0x00400390 /* IO CRB Entry Deallocation Register */9999+#define IIO_IFDR 0x00400398 /* IO IOQ FIFO Depth Register */100100+#define IIO_IIAP 0x004003A0 /* IO IIQ Arbitration Parameters */101101+#define IIO_ICMR 0x004003A8 /* IO CRB Management Register */102102+#define IIO_ICCR 0x004003B0 /* IO CRB Control Register */103103+#define IIO_ICTO 0x004003B8 /* IO CRB Timeout */104104+#define IIO_ICTP 0x004003C0 /* IO CRB Timeout Prescalar */971059898-#define IIO_IPDR 0x00400388 /* IO PIO Deallocation Register */9999-#define IIO_ICDR 0x00400390 /* IO CRB Entry Deallocation Register */100100-#define IIO_IFDR 0x00400398 /* IO IOQ FIFO Depth Register */101101-#define IIO_IIAP 0x004003A0 /* IO IIQ Arbitration Parameters */102102-#define IIO_ICMR 0x004003A8 /* IO CRB Management Register */103103-#define IIO_ICCR 0x004003B0 /* IO CRB Control Register */104104-#define IIO_ICTO 0x004003B8 /* IO CRB Timeout */105105-#define IIO_ICTP 0x004003C0 /* IO CRB Timeout Prescalar */106106+#define IIO_ICRB0_A 0x00400400 /* IO CRB Entry 0_A */107107+#define IIO_ICRB0_B 0x00400408 /* IO CRB Entry 0_B */108108+#define IIO_ICRB0_C 0x00400410 /* IO CRB Entry 0_C */109109+#define IIO_ICRB0_D 0x00400418 /* IO CRB Entry 0_D */110110+#define IIO_ICRB0_E 0x00400420 /* IO CRB Entry 0_E */106111107107-#define IIO_ICRB0_A 0x00400400 /* IO CRB Entry 0_A */108108-#define IIO_ICRB0_B 0x00400408 /* IO CRB Entry 0_B */109109-#define IIO_ICRB0_C 0x00400410 /* IO CRB Entry 0_C */110110-#define IIO_ICRB0_D 0x00400418 /* IO CRB Entry 0_D */111111-#define IIO_ICRB0_E 0x00400420 /* IO CRB Entry 0_E */112112+#define IIO_ICRB1_A 0x00400430 /* IO CRB Entry 1_A */113113+#define IIO_ICRB1_B 0x00400438 /* IO CRB Entry 1_B */114114+#define IIO_ICRB1_C 0x00400440 /* IO CRB Entry 1_C */115115+#define IIO_ICRB1_D 0x00400448 /* IO CRB Entry 1_D */116116+#define IIO_ICRB1_E 0x00400450 /* IO CRB Entry 1_E */112117113113-#define IIO_ICRB1_A 0x00400430 /* IO CRB Entry 1_A */114114-#define IIO_ICRB1_B 0x00400438 /* IO CRB Entry 1_B */115115-#define IIO_ICRB1_C 0x00400440 /* IO CRB Entry 1_C */116116-#define IIO_ICRB1_D 0x00400448 /* IO CRB Entry 1_D */117117-#define IIO_ICRB1_E 0x00400450 /* IO CRB Entry 1_E */118118+#define IIO_ICRB2_A 0x00400460 /* IO CRB Entry 2_A */119119+#define IIO_ICRB2_B 0x00400468 /* IO CRB Entry 2_B */120120+#define IIO_ICRB2_C 0x00400470 /* IO CRB Entry 2_C */121121+#define IIO_ICRB2_D 0x00400478 /* IO CRB Entry 2_D */122122+#define IIO_ICRB2_E 0x00400480 /* IO CRB Entry 2_E */118123119119-#define IIO_ICRB2_A 0x00400460 /* IO CRB Entry 2_A */120120-#define IIO_ICRB2_B 0x00400468 /* IO CRB Entry 2_B */121121-#define IIO_ICRB2_C 0x00400470 /* IO CRB Entry 2_C */122122-#define IIO_ICRB2_D 0x00400478 /* IO CRB Entry 2_D */123123-#define IIO_ICRB2_E 0x00400480 /* IO CRB Entry 2_E */124124+#define IIO_ICRB3_A 0x00400490 /* IO CRB Entry 3_A */125125+#define IIO_ICRB3_B 0x00400498 /* IO CRB Entry 3_B */126126+#define IIO_ICRB3_C 0x004004a0 /* IO CRB Entry 3_C */127127+#define IIO_ICRB3_D 0x004004a8 /* IO CRB Entry 3_D */128128+#define IIO_ICRB3_E 0x004004b0 /* IO CRB Entry 3_E */124129125125-#define IIO_ICRB3_A 0x00400490 /* IO CRB Entry 3_A */126126-#define IIO_ICRB3_B 0x00400498 /* IO CRB Entry 3_B */127127-#define IIO_ICRB3_C 0x004004a0 /* IO CRB Entry 3_C */128128-#define IIO_ICRB3_D 0x004004a8 /* IO CRB Entry 3_D */129129-#define IIO_ICRB3_E 0x004004b0 /* IO CRB Entry 3_E */130130+#define IIO_ICRB4_A 0x004004c0 /* IO CRB Entry 4_A */131131+#define IIO_ICRB4_B 0x004004c8 /* IO CRB Entry 4_B */132132+#define IIO_ICRB4_C 0x004004d0 /* IO CRB Entry 4_C */133133+#define IIO_ICRB4_D 0x004004d8 /* IO CRB Entry 4_D */134134+#define IIO_ICRB4_E 0x004004e0 /* IO CRB Entry 4_E */130135131131-#define IIO_ICRB4_A 0x004004c0 /* IO CRB Entry 4_A */132132-#define IIO_ICRB4_B 0x004004c8 /* IO CRB Entry 4_B */133133-#define IIO_ICRB4_C 0x004004d0 /* IO CRB Entry 4_C */134134-#define IIO_ICRB4_D 0x004004d8 /* IO CRB Entry 4_D */135135-#define IIO_ICRB4_E 0x004004e0 /* IO CRB Entry 4_E */136136+#define IIO_ICRB5_A 0x004004f0 /* IO CRB Entry 5_A */137137+#define IIO_ICRB5_B 0x004004f8 /* IO CRB Entry 5_B */138138+#define IIO_ICRB5_C 0x00400500 /* IO CRB Entry 5_C */139139+#define IIO_ICRB5_D 0x00400508 /* IO CRB Entry 5_D */140140+#define IIO_ICRB5_E 0x00400510 /* IO CRB Entry 5_E */136141137137-#define IIO_ICRB5_A 0x004004f0 /* IO CRB Entry 5_A */138138-#define IIO_ICRB5_B 0x004004f8 /* IO CRB Entry 5_B */139139-#define IIO_ICRB5_C 0x00400500 /* IO CRB Entry 5_C */140140-#define IIO_ICRB5_D 0x00400508 /* IO CRB Entry 5_D */141141-#define IIO_ICRB5_E 0x00400510 /* IO CRB Entry 5_E */142142+#define IIO_ICRB6_A 0x00400520 /* IO CRB Entry 6_A */143143+#define IIO_ICRB6_B 0x00400528 /* IO CRB Entry 6_B */144144+#define IIO_ICRB6_C 0x00400530 /* IO CRB Entry 6_C */145145+#define IIO_ICRB6_D 0x00400538 /* IO CRB Entry 6_D */146146+#define IIO_ICRB6_E 0x00400540 /* IO CRB Entry 6_E */142147143143-#define IIO_ICRB6_A 0x00400520 /* IO CRB Entry 6_A */144144-#define IIO_ICRB6_B 0x00400528 /* IO CRB Entry 6_B */145145-#define IIO_ICRB6_C 0x00400530 /* IO CRB Entry 6_C */146146-#define IIO_ICRB6_D 0x00400538 /* IO CRB Entry 6_D */147147-#define IIO_ICRB6_E 0x00400540 /* IO CRB Entry 6_E */148148+#define IIO_ICRB7_A 0x00400550 /* IO CRB Entry 7_A */149149+#define IIO_ICRB7_B 0x00400558 /* IO CRB Entry 7_B */150150+#define IIO_ICRB7_C 0x00400560 /* IO CRB Entry 7_C */151151+#define IIO_ICRB7_D 0x00400568 /* IO CRB Entry 7_D */152152+#define IIO_ICRB7_E 0x00400570 /* IO CRB Entry 7_E */148153149149-#define IIO_ICRB7_A 0x00400550 /* IO CRB Entry 7_A */150150-#define IIO_ICRB7_B 0x00400558 /* IO CRB Entry 7_B */151151-#define IIO_ICRB7_C 0x00400560 /* IO CRB Entry 7_C */152152-#define IIO_ICRB7_D 0x00400568 /* IO CRB Entry 7_D */153153-#define IIO_ICRB7_E 0x00400570 /* IO CRB Entry 7_E */154154+#define IIO_ICRB8_A 0x00400580 /* IO CRB Entry 8_A */155155+#define IIO_ICRB8_B 0x00400588 /* IO CRB Entry 8_B */156156+#define IIO_ICRB8_C 0x00400590 /* IO CRB Entry 8_C */157157+#define IIO_ICRB8_D 0x00400598 /* IO CRB Entry 8_D */158158+#define IIO_ICRB8_E 0x004005a0 /* IO CRB Entry 8_E */154159155155-#define IIO_ICRB8_A 0x00400580 /* IO CRB Entry 8_A */156156-#define IIO_ICRB8_B 0x00400588 /* IO CRB Entry 8_B */157157-#define IIO_ICRB8_C 0x00400590 /* IO CRB Entry 8_C */158158-#define IIO_ICRB8_D 0x00400598 /* IO CRB Entry 8_D */159159-#define IIO_ICRB8_E 0x004005a0 /* IO CRB Entry 8_E */160160+#define IIO_ICRB9_A 0x004005b0 /* IO CRB Entry 9_A */161161+#define IIO_ICRB9_B 0x004005b8 /* IO CRB Entry 9_B */162162+#define IIO_ICRB9_C 0x004005c0 /* IO CRB Entry 9_C */163163+#define IIO_ICRB9_D 0x004005c8 /* IO CRB Entry 9_D */164164+#define IIO_ICRB9_E 0x004005d0 /* IO CRB Entry 9_E */160165161161-#define IIO_ICRB9_A 0x004005b0 /* IO CRB Entry 9_A */162162-#define IIO_ICRB9_B 0x004005b8 /* IO CRB Entry 9_B */163163-#define IIO_ICRB9_C 0x004005c0 /* IO CRB Entry 9_C */164164-#define IIO_ICRB9_D 0x004005c8 /* IO CRB Entry 9_D */165165-#define IIO_ICRB9_E 0x004005d0 /* IO CRB Entry 9_E */166166+#define IIO_ICRBA_A 0x004005e0 /* IO CRB Entry A_A */167167+#define IIO_ICRBA_B 0x004005e8 /* IO CRB Entry A_B */168168+#define IIO_ICRBA_C 0x004005f0 /* IO CRB Entry A_C */169169+#define IIO_ICRBA_D 0x004005f8 /* IO CRB Entry A_D */170170+#define IIO_ICRBA_E 0x00400600 /* IO CRB Entry A_E */166171167167-#define IIO_ICRBA_A 0x004005e0 /* IO CRB Entry A_A */168168-#define IIO_ICRBA_B 0x004005e8 /* IO CRB Entry A_B */169169-#define IIO_ICRBA_C 0x004005f0 /* IO CRB Entry A_C */170170-#define IIO_ICRBA_D 0x004005f8 /* IO CRB Entry A_D */171171-#define IIO_ICRBA_E 0x00400600 /* IO CRB Entry A_E */172172+#define IIO_ICRBB_A 0x00400610 /* IO CRB Entry B_A */173173+#define IIO_ICRBB_B 0x00400618 /* IO CRB Entry B_B */174174+#define IIO_ICRBB_C 0x00400620 /* IO CRB Entry B_C */175175+#define IIO_ICRBB_D 0x00400628 /* IO CRB Entry B_D */176176+#define IIO_ICRBB_E 0x00400630 /* IO CRB Entry B_E */172177173173-#define IIO_ICRBB_A 0x00400610 /* IO CRB Entry B_A */174174-#define IIO_ICRBB_B 0x00400618 /* IO CRB Entry B_B */175175-#define IIO_ICRBB_C 0x00400620 /* IO CRB Entry B_C */176176-#define IIO_ICRBB_D 0x00400628 /* IO CRB Entry B_D */177177-#define IIO_ICRBB_E 0x00400630 /* IO CRB Entry B_E */178178+#define IIO_ICRBC_A 0x00400640 /* IO CRB Entry C_A */179179+#define IIO_ICRBC_B 0x00400648 /* IO CRB Entry C_B */180180+#define IIO_ICRBC_C 0x00400650 /* IO CRB Entry C_C */181181+#define IIO_ICRBC_D 0x00400658 /* IO CRB Entry C_D */182182+#define IIO_ICRBC_E 0x00400660 /* IO CRB Entry C_E */178183179179-#define IIO_ICRBC_A 0x00400640 /* IO CRB Entry C_A */180180-#define IIO_ICRBC_B 0x00400648 /* IO CRB Entry C_B */181181-#define IIO_ICRBC_C 0x00400650 /* IO CRB Entry C_C */182182-#define IIO_ICRBC_D 0x00400658 /* IO CRB Entry C_D */183183-#define IIO_ICRBC_E 0x00400660 /* IO CRB Entry C_E */184184+#define IIO_ICRBD_A 0x00400670 /* IO CRB Entry D_A */185185+#define IIO_ICRBD_B 0x00400678 /* IO CRB Entry D_B */186186+#define IIO_ICRBD_C 0x00400680 /* IO CRB Entry D_C */187187+#define IIO_ICRBD_D 0x00400688 /* IO CRB Entry D_D */188188+#define IIO_ICRBD_E 0x00400690 /* IO CRB Entry D_E */184189185185-#define IIO_ICRBD_A 0x00400670 /* IO CRB Entry D_A */186186-#define IIO_ICRBD_B 0x00400678 /* IO CRB Entry D_B */187187-#define IIO_ICRBD_C 0x00400680 /* IO CRB Entry D_C */188188-#define IIO_ICRBD_D 0x00400688 /* IO CRB Entry D_D */189189-#define IIO_ICRBD_E 0x00400690 /* IO CRB Entry D_E */190190+#define IIO_ICRBE_A 0x004006a0 /* IO CRB Entry E_A */191191+#define IIO_ICRBE_B 0x004006a8 /* IO CRB Entry E_B */192192+#define IIO_ICRBE_C 0x004006b0 /* IO CRB Entry E_C */193193+#define IIO_ICRBE_D 0x004006b8 /* IO CRB Entry E_D */194194+#define IIO_ICRBE_E 0x004006c0 /* IO CRB Entry E_E */190195191191-#define IIO_ICRBE_A 0x004006a0 /* IO CRB Entry E_A */192192-#define IIO_ICRBE_B 0x004006a8 /* IO CRB Entry E_B */193193-#define IIO_ICRBE_C 0x004006b0 /* IO CRB Entry E_C */194194-#define IIO_ICRBE_D 0x004006b8 /* IO CRB Entry E_D */195195-#define IIO_ICRBE_E 0x004006c0 /* IO CRB Entry E_E */196196+#define IIO_ICSML 0x00400700 /* IO CRB Spurious Message Low */197197+#define IIO_ICSMM 0x00400708 /* IO CRB Spurious Message Middle */198198+#define IIO_ICSMH 0x00400710 /* IO CRB Spurious Message High */196199197197-#define IIO_ICSML 0x00400700 /* IO CRB Spurious Message Low */198198-#define IIO_ICSMM 0x00400708 /* IO CRB Spurious Message Middle */199199-#define IIO_ICSMH 0x00400710 /* IO CRB Spurious Message High */200200+#define IIO_IDBSS 0x00400718 /* IO Debug Submenu Select */200201201201-#define IIO_IDBSS 0x00400718 /* IO Debug Submenu Select */202202+#define IIO_IBLS0 0x00410000 /* IO BTE Length Status 0 */203203+#define IIO_IBSA0 0x00410008 /* IO BTE Source Address 0 */204204+#define IIO_IBDA0 0x00410010 /* IO BTE Destination Address 0 */205205+#define IIO_IBCT0 0x00410018 /* IO BTE Control Terminate 0 */206206+#define IIO_IBNA0 0x00410020 /* IO BTE Notification Address 0 */207207+#define IIO_IBIA0 0x00410028 /* IO BTE Interrupt Address 0 */208208+#define IIO_IBLS1 0x00420000 /* IO BTE Length Status 1 */209209+#define IIO_IBSA1 0x00420008 /* IO BTE Source Address 1 */210210+#define IIO_IBDA1 0x00420010 /* IO BTE Destination Address 1 */211211+#define IIO_IBCT1 0x00420018 /* IO BTE Control Terminate 1 */212212+#define IIO_IBNA1 0x00420020 /* IO BTE Notification Address 1 */213213+#define IIO_IBIA1 0x00420028 /* IO BTE Interrupt Address 1 */202214203203-#define IIO_IBLS0 0x00410000 /* IO BTE Length Status 0 */204204-#define IIO_IBSA0 0x00410008 /* IO BTE Source Address 0 */205205-#define IIO_IBDA0 0x00410010 /* IO BTE Destination Address 0 */206206-#define IIO_IBCT0 0x00410018 /* IO BTE Control Terminate 0 */207207-#define IIO_IBNA0 0x00410020 /* IO BTE Notification Address 0 */208208-#define IIO_IBIA0 0x00410028 /* IO BTE Interrupt Address 0 */209209-#define IIO_IBLS1 0x00420000 /* IO BTE Length Status 1 */210210-#define IIO_IBSA1 0x00420008 /* IO BTE Source Address 1 */211211-#define IIO_IBDA1 0x00420010 /* IO BTE Destination Address 1 */212212-#define IIO_IBCT1 0x00420018 /* IO BTE Control Terminate 1 */213213-#define IIO_IBNA1 0x00420020 /* IO BTE Notification Address 1 */214214-#define IIO_IBIA1 0x00420028 /* IO BTE Interrupt Address 1 */215215-216216-#define IIO_IPCR 0x00430000 /* IO Performance Control */217217-#define IIO_IPPR 0x00430008 /* IO Performance Profiling */218218-215215+#define IIO_IPCR 0x00430000 /* IO Performance Control */216216+#define IIO_IPPR 0x00430008 /* IO Performance Profiling */219217220218/************************************************************************221221- * *219219+ * *222220 * Description: This register echoes some information from the *223221 * LB_REV_ID register. It is available through Crosstalk as described *224222 * above. The REV_NUM and MFG_NUM fields receive their values from *225223 * the REVISION and MANUFACTURER fields in the LB_REV_ID register. *226224 * The PART_NUM field's value is the Crosstalk device ID number that *227225 * Steve Miller assigned to the SHub chip. *228228- * *226226+ * *229227 ************************************************************************/230228231229typedef union ii_wid_u {232232- uint64_t ii_wid_regval;233233- struct {234234- uint64_t w_rsvd_1 : 1;235235- uint64_t w_mfg_num : 11;236236- uint64_t w_part_num : 16;237237- uint64_t w_rev_num : 4;238238- uint64_t w_rsvd : 32;230230+ uint64_t ii_wid_regval;231231+ struct {232232+ uint64_t w_rsvd_1:1;233233+ uint64_t w_mfg_num:11;234234+ uint64_t w_part_num:16;235235+ uint64_t w_rev_num:4;236236+ uint64_t w_rsvd:32;239237 } ii_wid_fld_s;240238} ii_wid_u_t;241239242242-243240/************************************************************************244244- * *241241+ * *245242 * The fields in this register are set upon detection of an error *246243 * and cleared by various mechanisms, as explained in the *247244 * description. *248248- * *245245+ * *249246 ************************************************************************/250247251248typedef union ii_wstat_u {252252- uint64_t ii_wstat_regval;253253- struct {254254- uint64_t w_pending : 4;255255- uint64_t w_xt_crd_to : 1;256256- uint64_t w_xt_tail_to : 1;257257- uint64_t w_rsvd_3 : 3;258258- uint64_t w_tx_mx_rty : 1;259259- uint64_t w_rsvd_2 : 6;260260- uint64_t w_llp_tx_cnt : 8;261261- uint64_t w_rsvd_1 : 8;262262- uint64_t w_crazy : 1;263263- uint64_t w_rsvd : 31;249249+ uint64_t ii_wstat_regval;250250+ struct {251251+ uint64_t w_pending:4;252252+ uint64_t w_xt_crd_to:1;253253+ uint64_t w_xt_tail_to:1;254254+ uint64_t w_rsvd_3:3;255255+ uint64_t w_tx_mx_rty:1;256256+ uint64_t w_rsvd_2:6;257257+ uint64_t w_llp_tx_cnt:8;258258+ uint64_t w_rsvd_1:8;259259+ uint64_t w_crazy:1;260260+ uint64_t w_rsvd:31;264261 } ii_wstat_fld_s;265262} ii_wstat_u_t;266263267267-268264/************************************************************************269269- * *265265+ * *270266 * Description: This is a read-write enabled register. It controls *271267 * various aspects of the Crosstalk flow control. *272272- * *268268+ * *273269 ************************************************************************/274270275271typedef union ii_wcr_u {276276- uint64_t ii_wcr_regval;277277- struct {278278- uint64_t w_wid : 4;279279- uint64_t w_tag : 1;280280- uint64_t w_rsvd_1 : 8;281281- uint64_t w_dst_crd : 3;282282- uint64_t w_f_bad_pkt : 1;283283- uint64_t w_dir_con : 1;284284- uint64_t w_e_thresh : 5;285285- uint64_t w_rsvd : 41;272272+ uint64_t ii_wcr_regval;273273+ struct {274274+ uint64_t w_wid:4;275275+ uint64_t w_tag:1;276276+ uint64_t w_rsvd_1:8;277277+ uint64_t w_dst_crd:3;278278+ uint64_t w_f_bad_pkt:1;279279+ uint64_t w_dir_con:1;280280+ uint64_t w_e_thresh:5;281281+ uint64_t w_rsvd:41;286282 } ii_wcr_fld_s;287283} ii_wcr_u_t;288284289289-290285/************************************************************************291291- * *286286+ * *292287 * Description: This register's value is a bit vector that guards *293288 * access to local registers within the II as well as to external *294289 * Crosstalk widgets. Each bit in the register corresponds to a *···306311 * region ID bits are enabled in this same register. It can also be *307312 * accessed through the IAlias space by the local processors. *308313 * The reset value of this register allows access by all nodes. *309309- * *314314+ * *310315 ************************************************************************/311316312317typedef union ii_ilapr_u {313313- uint64_t ii_ilapr_regval;314314- struct {315315- uint64_t i_region : 64;318318+ uint64_t ii_ilapr_regval;319319+ struct {320320+ uint64_t i_region:64;316321 } ii_ilapr_fld_s;317322} ii_ilapr_u_t;318323319319-320320-321321-322324/************************************************************************323323- * *325325+ * *324326 * Description: A write to this register of the 64-bit value *325327 * "SGIrules" in ASCII, will cause the bit in the ILAPR register *326328 * corresponding to the region of the requestor to be set (allow *···326334 * This register can also be accessed through the IAlias space. *327335 * However, this access will not change the access permissions in the *328336 * ILAPR. *329329- * *337337+ * *330338 ************************************************************************/331339332340typedef union ii_ilapo_u {333333- uint64_t ii_ilapo_regval;334334- struct {335335- uint64_t i_io_ovrride : 64;341341+ uint64_t ii_ilapo_regval;342342+ struct {343343+ uint64_t i_io_ovrride:64;336344 } ii_ilapo_fld_s;337345} ii_ilapo_u_t;338346339339-340340-341347/************************************************************************342342- * *348348+ * *343349 * This register qualifies all the PIO and Graphics writes launched *344350 * from the SHUB towards a widget. *345345- * *351351+ * *346352 ************************************************************************/347353348354typedef union ii_iowa_u {349349- uint64_t ii_iowa_regval;350350- struct {351351- uint64_t i_w0_oac : 1;352352- uint64_t i_rsvd_1 : 7;353353- uint64_t i_wx_oac : 8;354354- uint64_t i_rsvd : 48;355355+ uint64_t ii_iowa_regval;356356+ struct {357357+ uint64_t i_w0_oac:1;358358+ uint64_t i_rsvd_1:7;359359+ uint64_t i_wx_oac:8;360360+ uint64_t i_rsvd:48;355361 } ii_iowa_fld_s;356362} ii_iowa_u_t;357363358358-359364/************************************************************************360360- * *365365+ * *361366 * Description: This register qualifies all the requests launched *362367 * from a widget towards the Shub. This register is intended to be *363368 * used by software in case of misbehaving widgets. *364364- * *365365- * *369369+ * *370370+ * *366371 ************************************************************************/367372368373typedef union ii_iiwa_u {369369- uint64_t ii_iiwa_regval;370370- struct {371371- uint64_t i_w0_iac : 1;372372- uint64_t i_rsvd_1 : 7;373373- uint64_t i_wx_iac : 8;374374- uint64_t i_rsvd : 48;374374+ uint64_t ii_iiwa_regval;375375+ struct {376376+ uint64_t i_w0_iac:1;377377+ uint64_t i_rsvd_1:7;378378+ uint64_t i_wx_iac:8;379379+ uint64_t i_rsvd:48;375380 } ii_iiwa_fld_s;376381} ii_iiwa_u_t;377382378378-379379-380383/************************************************************************381381- * *384384+ * *382385 * Description: This register qualifies all the operations launched *383386 * from a widget towards the SHub. It allows individual access *384387 * control for up to 8 devices per widget. A device refers to *···388401 * The bits in this field are set by writing a 1 to them. Incoming *389402 * replies from Crosstalk are not subject to this access control *390403 * mechanism. *391391- * *404404+ * *392405 ************************************************************************/393406394407typedef union ii_iidem_u {395395- uint64_t ii_iidem_regval;396396- struct {397397- uint64_t i_w8_dxs : 8;398398- uint64_t i_w9_dxs : 8;399399- uint64_t i_wa_dxs : 8;400400- uint64_t i_wb_dxs : 8;401401- uint64_t i_wc_dxs : 8;402402- uint64_t i_wd_dxs : 8;403403- uint64_t i_we_dxs : 8;404404- uint64_t i_wf_dxs : 8;408408+ uint64_t ii_iidem_regval;409409+ struct {410410+ uint64_t i_w8_dxs:8;411411+ uint64_t i_w9_dxs:8;412412+ uint64_t i_wa_dxs:8;413413+ uint64_t i_wb_dxs:8;414414+ uint64_t i_wc_dxs:8;415415+ uint64_t i_wd_dxs:8;416416+ uint64_t i_we_dxs:8;417417+ uint64_t i_wf_dxs:8;405418 } ii_iidem_fld_s;406419} ii_iidem_u_t;407420408408-409421/************************************************************************410410- * *422422+ * *411423 * This register contains the various programmable fields necessary *412424 * for controlling and observing the LLP signals. *413413- * *425425+ * *414426 ************************************************************************/415427416428typedef union ii_ilcsr_u {417417- uint64_t ii_ilcsr_regval;418418- struct {419419- uint64_t i_nullto : 6;420420- uint64_t i_rsvd_4 : 2;421421- uint64_t i_wrmrst : 1;422422- uint64_t i_rsvd_3 : 1;423423- uint64_t i_llp_en : 1;424424- uint64_t i_bm8 : 1;425425- uint64_t i_llp_stat : 2;426426- uint64_t i_remote_power : 1;427427- uint64_t i_rsvd_2 : 1;428428- uint64_t i_maxrtry : 10;429429- uint64_t i_d_avail_sel : 2;430430- uint64_t i_rsvd_1 : 4;431431- uint64_t i_maxbrst : 10;432432- uint64_t i_rsvd : 22;429429+ uint64_t ii_ilcsr_regval;430430+ struct {431431+ uint64_t i_nullto:6;432432+ uint64_t i_rsvd_4:2;433433+ uint64_t i_wrmrst:1;434434+ uint64_t i_rsvd_3:1;435435+ uint64_t i_llp_en:1;436436+ uint64_t i_bm8:1;437437+ uint64_t i_llp_stat:2;438438+ uint64_t i_remote_power:1;439439+ uint64_t i_rsvd_2:1;440440+ uint64_t i_maxrtry:10;441441+ uint64_t i_d_avail_sel:2;442442+ uint64_t i_rsvd_1:4;443443+ uint64_t i_maxbrst:10;444444+ uint64_t i_rsvd:22;433445434446 } ii_ilcsr_fld_s;435447} ii_ilcsr_u_t;436448437437-438449/************************************************************************439439- * *450450+ * *440451 * This is simply a status registers that monitors the LLP error *441441- * rate. *442442- * *452452+ * rate. *453453+ * *443454 ************************************************************************/444455445456typedef union ii_illr_u {446446- uint64_t ii_illr_regval;447447- struct {448448- uint64_t i_sn_cnt : 16;449449- uint64_t i_cb_cnt : 16;450450- uint64_t i_rsvd : 32;457457+ uint64_t ii_illr_regval;458458+ struct {459459+ uint64_t i_sn_cnt:16;460460+ uint64_t i_cb_cnt:16;461461+ uint64_t i_rsvd:32;451462 } ii_illr_fld_s;452463} ii_illr_u_t;453464454454-455465/************************************************************************456456- * *466466+ * *457467 * Description: All II-detected non-BTE error interrupts are *458468 * specified via this register. *459469 * NOTE: The PI interrupt register address is hardcoded in the II. If *···460476 * PI_ID==1, then the II sends the interrupt request to address *461477 * offset 0x01A0_0090 within the local register address space of PI1 *462478 * on the node specified by the NODE field. *463463- * *479479+ * *464480 ************************************************************************/465481466482typedef union ii_iidsr_u {467467- uint64_t ii_iidsr_regval;468468- struct {469469- uint64_t i_level : 8;470470- uint64_t i_pi_id : 1;471471- uint64_t i_node : 11;472472- uint64_t i_rsvd_3 : 4;473473- uint64_t i_enable : 1;474474- uint64_t i_rsvd_2 : 3;475475- uint64_t i_int_sent : 2;476476- uint64_t i_rsvd_1 : 2;477477- uint64_t i_pi0_forward_int : 1;478478- uint64_t i_pi1_forward_int : 1;479479- uint64_t i_rsvd : 30;483483+ uint64_t ii_iidsr_regval;484484+ struct {485485+ uint64_t i_level:8;486486+ uint64_t i_pi_id:1;487487+ uint64_t i_node:11;488488+ uint64_t i_rsvd_3:4;489489+ uint64_t i_enable:1;490490+ uint64_t i_rsvd_2:3;491491+ uint64_t i_int_sent:2;492492+ uint64_t i_rsvd_1:2;493493+ uint64_t i_pi0_forward_int:1;494494+ uint64_t i_pi1_forward_int:1;495495+ uint64_t i_rsvd:30;480496 } ii_iidsr_fld_s;481497} ii_iidsr_u_t;482498483483-484484-485499/************************************************************************486486- * *500500+ * *487501 * There are two instances of this register. This register is used *488502 * for matching up the incoming responses from the graphics widget to *489503 * the processor that initiated the graphics operation. The *490504 * write-responses are converted to graphics credits and returned to *491505 * the processor so that the processor interface can manage the flow *492506 * control. *493493- * *507507+ * *494508 ************************************************************************/495509496510typedef union ii_igfx0_u {497497- uint64_t ii_igfx0_regval;498498- struct {499499- uint64_t i_w_num : 4;500500- uint64_t i_pi_id : 1;501501- uint64_t i_n_num : 12;502502- uint64_t i_p_num : 1;503503- uint64_t i_rsvd : 46;511511+ uint64_t ii_igfx0_regval;512512+ struct {513513+ uint64_t i_w_num:4;514514+ uint64_t i_pi_id:1;515515+ uint64_t i_n_num:12;516516+ uint64_t i_p_num:1;517517+ uint64_t i_rsvd:46;504518 } ii_igfx0_fld_s;505519} ii_igfx0_u_t;506520507507-508521/************************************************************************509509- * *522522+ * *510523 * There are two instances of this register. This register is used *511524 * for matching up the incoming responses from the graphics widget to *512525 * the processor that initiated the graphics operation. The *513526 * write-responses are converted to graphics credits and returned to *514527 * the processor so that the processor interface can manage the flow *515528 * control. *516516- * *529529+ * *517530 ************************************************************************/518531519532typedef union ii_igfx1_u {520520- uint64_t ii_igfx1_regval;521521- struct {522522- uint64_t i_w_num : 4;523523- uint64_t i_pi_id : 1;524524- uint64_t i_n_num : 12;525525- uint64_t i_p_num : 1;526526- uint64_t i_rsvd : 46;533533+ uint64_t ii_igfx1_regval;534534+ struct {535535+ uint64_t i_w_num:4;536536+ uint64_t i_pi_id:1;537537+ uint64_t i_n_num:12;538538+ uint64_t i_p_num:1;539539+ uint64_t i_rsvd:46;527540 } ii_igfx1_fld_s;528541} ii_igfx1_u_t;529542530530-531543/************************************************************************532532- * *544544+ * *533545 * There are two instances of this registers. These registers are *534546 * used as scratch registers for software use. *535535- * *547547+ * *536548 ************************************************************************/537549538550typedef union ii_iscr0_u {539539- uint64_t ii_iscr0_regval;540540- struct {541541- uint64_t i_scratch : 64;551551+ uint64_t ii_iscr0_regval;552552+ struct {553553+ uint64_t i_scratch:64;542554 } ii_iscr0_fld_s;543555} ii_iscr0_u_t;544556545545-546546-547557/************************************************************************548548- * *558558+ * *549559 * There are two instances of this registers. These registers are *550560 * used as scratch registers for software use. *551551- * *561561+ * *552562 ************************************************************************/553563554564typedef union ii_iscr1_u {555555- uint64_t ii_iscr1_regval;556556- struct {557557- uint64_t i_scratch : 64;565565+ uint64_t ii_iscr1_regval;566566+ struct {567567+ uint64_t i_scratch:64;558568 } ii_iscr1_fld_s;559569} ii_iscr1_u_t;560570561561-562571/************************************************************************563563- * *572572+ * *564573 * Description: There are seven instances of translation table entry *565574 * registers. Each register maps a Shub Big Window to a 48-bit *566575 * address on Crosstalk. *···576599 * Crosstalk space addressable by the Shub is thus the lower *577600 * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *578601 * of this space can be accessed. *579579- * *602602+ * *580603 ************************************************************************/581604582605typedef union ii_itte1_u {583583- uint64_t ii_itte1_regval;584584- struct {585585- uint64_t i_offset : 5;586586- uint64_t i_rsvd_1 : 3;587587- uint64_t i_w_num : 4;588588- uint64_t i_iosp : 1;589589- uint64_t i_rsvd : 51;606606+ uint64_t ii_itte1_regval;607607+ struct {608608+ uint64_t i_offset:5;609609+ uint64_t i_rsvd_1:3;610610+ uint64_t i_w_num:4;611611+ uint64_t i_iosp:1;612612+ uint64_t i_rsvd:51;590613 } ii_itte1_fld_s;591614} ii_itte1_u_t;592615593593-594616/************************************************************************595595- * *617617+ * *596618 * Description: There are seven instances of translation table entry *597619 * registers. Each register maps a Shub Big Window to a 48-bit *598620 * address on Crosstalk. *···614638 * Crosstalk space addressable by the Shub is thus the lower *615639 * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *616640 * of this space can be accessed. *617617- * *641641+ * *618642 ************************************************************************/619643620644typedef union ii_itte2_u {621621- uint64_t ii_itte2_regval;622622- struct {623623- uint64_t i_offset : 5;624624- uint64_t i_rsvd_1 : 3;625625- uint64_t i_w_num : 4;626626- uint64_t i_iosp : 1;627627- uint64_t i_rsvd : 51;645645+ uint64_t ii_itte2_regval;646646+ struct {647647+ uint64_t i_offset:5;648648+ uint64_t i_rsvd_1:3;649649+ uint64_t i_w_num:4;650650+ uint64_t i_iosp:1;651651+ uint64_t i_rsvd:51;628652 } ii_itte2_fld_s;629653} ii_itte2_u_t;630654631631-632655/************************************************************************633633- * *656656+ * *634657 * Description: There are seven instances of translation table entry *635658 * registers. Each register maps a Shub Big Window to a 48-bit *636659 * address on Crosstalk. *···652677 * Crosstalk space addressable by the SHub is thus the lower *653678 * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *654679 * of this space can be accessed. *655655- * *680680+ * *656681 ************************************************************************/657682658683typedef union ii_itte3_u {659659- uint64_t ii_itte3_regval;660660- struct {661661- uint64_t i_offset : 5;662662- uint64_t i_rsvd_1 : 3;663663- uint64_t i_w_num : 4;664664- uint64_t i_iosp : 1;665665- uint64_t i_rsvd : 51;684684+ uint64_t ii_itte3_regval;685685+ struct {686686+ uint64_t i_offset:5;687687+ uint64_t i_rsvd_1:3;688688+ uint64_t i_w_num:4;689689+ uint64_t i_iosp:1;690690+ uint64_t i_rsvd:51;666691 } ii_itte3_fld_s;667692} ii_itte3_u_t;668693669669-670694/************************************************************************671671- * *695695+ * *672696 * Description: There are seven instances of translation table entry *673697 * registers. Each register maps a SHub Big Window to a 48-bit *674698 * address on Crosstalk. *···690716 * Crosstalk space addressable by the SHub is thus the lower *691717 * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *692718 * of this space can be accessed. *693693- * *719719+ * *694720 ************************************************************************/695721696722typedef union ii_itte4_u {697697- uint64_t ii_itte4_regval;698698- struct {699699- uint64_t i_offset : 5;700700- uint64_t i_rsvd_1 : 3;701701- uint64_t i_w_num : 4;702702- uint64_t i_iosp : 1;703703- uint64_t i_rsvd : 51;723723+ uint64_t ii_itte4_regval;724724+ struct {725725+ uint64_t i_offset:5;726726+ uint64_t i_rsvd_1:3;727727+ uint64_t i_w_num:4;728728+ uint64_t i_iosp:1;729729+ uint64_t i_rsvd:51;704730 } ii_itte4_fld_s;705731} ii_itte4_u_t;706732707707-708733/************************************************************************709709- * *734734+ * *710735 * Description: There are seven instances of translation table entry *711736 * registers. Each register maps a SHub Big Window to a 48-bit *712737 * address on Crosstalk. *···728755 * Crosstalk space addressable by the Shub is thus the lower *729756 * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *730757 * of this space can be accessed. *731731- * *758758+ * *732759 ************************************************************************/733760734761typedef union ii_itte5_u {735735- uint64_t ii_itte5_regval;736736- struct {737737- uint64_t i_offset : 5;738738- uint64_t i_rsvd_1 : 3;739739- uint64_t i_w_num : 4;740740- uint64_t i_iosp : 1;741741- uint64_t i_rsvd : 51;762762+ uint64_t ii_itte5_regval;763763+ struct {764764+ uint64_t i_offset:5;765765+ uint64_t i_rsvd_1:3;766766+ uint64_t i_w_num:4;767767+ uint64_t i_iosp:1;768768+ uint64_t i_rsvd:51;742769 } ii_itte5_fld_s;743770} ii_itte5_u_t;744771745745-746772/************************************************************************747747- * *773773+ * *748774 * Description: There are seven instances of translation table entry *749775 * registers. Each register maps a Shub Big Window to a 48-bit *750776 * address on Crosstalk. *···766794 * Crosstalk space addressable by the Shub is thus the lower *767795 * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *768796 * of this space can be accessed. *769769- * *797797+ * *770798 ************************************************************************/771799772800typedef union ii_itte6_u {773773- uint64_t ii_itte6_regval;774774- struct {775775- uint64_t i_offset : 5;776776- uint64_t i_rsvd_1 : 3;777777- uint64_t i_w_num : 4;778778- uint64_t i_iosp : 1;779779- uint64_t i_rsvd : 51;801801+ uint64_t ii_itte6_regval;802802+ struct {803803+ uint64_t i_offset:5;804804+ uint64_t i_rsvd_1:3;805805+ uint64_t i_w_num:4;806806+ uint64_t i_iosp:1;807807+ uint64_t i_rsvd:51;780808 } ii_itte6_fld_s;781809} ii_itte6_u_t;782810783783-784811/************************************************************************785785- * *812812+ * *786813 * Description: There are seven instances of translation table entry *787814 * registers. Each register maps a Shub Big Window to a 48-bit *788815 * address on Crosstalk. *···804833 * Crosstalk space addressable by the SHub is thus the lower *805834 * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB> *806835 * of this space can be accessed. *807807- * *836836+ * *808837 ************************************************************************/809838810839typedef union ii_itte7_u {811811- uint64_t ii_itte7_regval;812812- struct {813813- uint64_t i_offset : 5;814814- uint64_t i_rsvd_1 : 3;815815- uint64_t i_w_num : 4;816816- uint64_t i_iosp : 1;817817- uint64_t i_rsvd : 51;840840+ uint64_t ii_itte7_regval;841841+ struct {842842+ uint64_t i_offset:5;843843+ uint64_t i_rsvd_1:3;844844+ uint64_t i_w_num:4;845845+ uint64_t i_iosp:1;846846+ uint64_t i_rsvd:51;818847 } ii_itte7_fld_s;819848} ii_itte7_u_t;820849821821-822850/************************************************************************823823- * *851851+ * *824852 * Description: There are 9 instances of this register, one per *825853 * actual widget in this implementation of SHub and Crossbow. *826854 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···838868 * register; the write will correct the C field and capture its new *839869 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *840870 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *841841- * . *842842- * *871871+ * . *872872+ * *843873 ************************************************************************/844874845875typedef union ii_iprb0_u {846846- uint64_t ii_iprb0_regval;847847- struct {848848- uint64_t i_c : 8;849849- uint64_t i_na : 14;850850- uint64_t i_rsvd_2 : 2;851851- uint64_t i_nb : 14;852852- uint64_t i_rsvd_1 : 2;853853- uint64_t i_m : 2;854854- uint64_t i_f : 1;855855- uint64_t i_of_cnt : 5;856856- uint64_t i_error : 1;857857- uint64_t i_rd_to : 1;858858- uint64_t i_spur_wr : 1;859859- uint64_t i_spur_rd : 1;860860- uint64_t i_rsvd : 11;861861- uint64_t i_mult_err : 1;876876+ uint64_t ii_iprb0_regval;877877+ struct {878878+ uint64_t i_c:8;879879+ uint64_t i_na:14;880880+ uint64_t i_rsvd_2:2;881881+ uint64_t i_nb:14;882882+ uint64_t i_rsvd_1:2;883883+ uint64_t i_m:2;884884+ uint64_t i_f:1;885885+ uint64_t i_of_cnt:5;886886+ uint64_t i_error:1;887887+ uint64_t i_rd_to:1;888888+ uint64_t i_spur_wr:1;889889+ uint64_t i_spur_rd:1;890890+ uint64_t i_rsvd:11;891891+ uint64_t i_mult_err:1;862892 } ii_iprb0_fld_s;863893} ii_iprb0_u_t;864894865865-866895/************************************************************************867867- * *896896+ * *868897 * Description: There are 9 instances of this register, one per *869898 * actual widget in this implementation of SHub and Crossbow. *870899 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···882913 * register; the write will correct the C field and capture its new *883914 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *884915 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *885885- * . *886886- * *916916+ * . *917917+ * *887918 ************************************************************************/888919889920typedef union ii_iprb8_u {890890- uint64_t ii_iprb8_regval;891891- struct {892892- uint64_t i_c : 8;893893- uint64_t i_na : 14;894894- uint64_t i_rsvd_2 : 2;895895- uint64_t i_nb : 14;896896- uint64_t i_rsvd_1 : 2;897897- uint64_t i_m : 2;898898- uint64_t i_f : 1;899899- uint64_t i_of_cnt : 5;900900- uint64_t i_error : 1;901901- uint64_t i_rd_to : 1;902902- uint64_t i_spur_wr : 1;903903- uint64_t i_spur_rd : 1;904904- uint64_t i_rsvd : 11;905905- uint64_t i_mult_err : 1;921921+ uint64_t ii_iprb8_regval;922922+ struct {923923+ uint64_t i_c:8;924924+ uint64_t i_na:14;925925+ uint64_t i_rsvd_2:2;926926+ uint64_t i_nb:14;927927+ uint64_t i_rsvd_1:2;928928+ uint64_t i_m:2;929929+ uint64_t i_f:1;930930+ uint64_t i_of_cnt:5;931931+ uint64_t i_error:1;932932+ uint64_t i_rd_to:1;933933+ uint64_t i_spur_wr:1;934934+ uint64_t i_spur_rd:1;935935+ uint64_t i_rsvd:11;936936+ uint64_t i_mult_err:1;906937 } ii_iprb8_fld_s;907938} ii_iprb8_u_t;908939909909-910940/************************************************************************911911- * *941941+ * *912942 * Description: There are 9 instances of this register, one per *913943 * actual widget in this implementation of SHub and Crossbow. *914944 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···926958 * register; the write will correct the C field and capture its new *927959 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *928960 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *929929- * . *930930- * *961961+ * . *962962+ * *931963 ************************************************************************/932964933965typedef union ii_iprb9_u {934934- uint64_t ii_iprb9_regval;935935- struct {936936- uint64_t i_c : 8;937937- uint64_t i_na : 14;938938- uint64_t i_rsvd_2 : 2;939939- uint64_t i_nb : 14;940940- uint64_t i_rsvd_1 : 2;941941- uint64_t i_m : 2;942942- uint64_t i_f : 1;943943- uint64_t i_of_cnt : 5;944944- uint64_t i_error : 1;945945- uint64_t i_rd_to : 1;946946- uint64_t i_spur_wr : 1;947947- uint64_t i_spur_rd : 1;948948- uint64_t i_rsvd : 11;949949- uint64_t i_mult_err : 1;966966+ uint64_t ii_iprb9_regval;967967+ struct {968968+ uint64_t i_c:8;969969+ uint64_t i_na:14;970970+ uint64_t i_rsvd_2:2;971971+ uint64_t i_nb:14;972972+ uint64_t i_rsvd_1:2;973973+ uint64_t i_m:2;974974+ uint64_t i_f:1;975975+ uint64_t i_of_cnt:5;976976+ uint64_t i_error:1;977977+ uint64_t i_rd_to:1;978978+ uint64_t i_spur_wr:1;979979+ uint64_t i_spur_rd:1;980980+ uint64_t i_rsvd:11;981981+ uint64_t i_mult_err:1;950982 } ii_iprb9_fld_s;951983} ii_iprb9_u_t;952984953953-954985/************************************************************************955955- * *986986+ * *956987 * Description: There are 9 instances of this register, one per *957988 * actual widget in this implementation of SHub and Crossbow. *958989 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···9701003 * register; the write will correct the C field and capture its new *9711004 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *9721005 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *973973- * *974974- * *10061006+ * *10071007+ * *9751008 ************************************************************************/97610099771010typedef union ii_iprba_u {978978- uint64_t ii_iprba_regval;979979- struct {980980- uint64_t i_c : 8;981981- uint64_t i_na : 14;982982- uint64_t i_rsvd_2 : 2;983983- uint64_t i_nb : 14;984984- uint64_t i_rsvd_1 : 2;985985- uint64_t i_m : 2;986986- uint64_t i_f : 1;987987- uint64_t i_of_cnt : 5;988988- uint64_t i_error : 1;989989- uint64_t i_rd_to : 1;990990- uint64_t i_spur_wr : 1;991991- uint64_t i_spur_rd : 1;992992- uint64_t i_rsvd : 11;993993- uint64_t i_mult_err : 1;10111011+ uint64_t ii_iprba_regval;10121012+ struct {10131013+ uint64_t i_c:8;10141014+ uint64_t i_na:14;10151015+ uint64_t i_rsvd_2:2;10161016+ uint64_t i_nb:14;10171017+ uint64_t i_rsvd_1:2;10181018+ uint64_t i_m:2;10191019+ uint64_t i_f:1;10201020+ uint64_t i_of_cnt:5;10211021+ uint64_t i_error:1;10221022+ uint64_t i_rd_to:1;10231023+ uint64_t i_spur_wr:1;10241024+ uint64_t i_spur_rd:1;10251025+ uint64_t i_rsvd:11;10261026+ uint64_t i_mult_err:1;9941027 } ii_iprba_fld_s;9951028} ii_iprba_u_t;9961029997997-9981030/************************************************************************999999- * *10311031+ * *10001032 * Description: There are 9 instances of this register, one per *10011033 * actual widget in this implementation of SHub and Crossbow. *10021034 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···10141048 * register; the write will correct the C field and capture its new *10151049 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *10161050 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *10171017- * . *10181018- * *10511051+ * . *10521052+ * *10191053 ************************************************************************/1020105410211055typedef union ii_iprbb_u {10221022- uint64_t ii_iprbb_regval;10231023- struct {10241024- uint64_t i_c : 8;10251025- uint64_t i_na : 14;10261026- uint64_t i_rsvd_2 : 2;10271027- uint64_t i_nb : 14;10281028- uint64_t i_rsvd_1 : 2;10291029- uint64_t i_m : 2;10301030- uint64_t i_f : 1;10311031- uint64_t i_of_cnt : 5;10321032- uint64_t i_error : 1;10331033- uint64_t i_rd_to : 1;10341034- uint64_t i_spur_wr : 1;10351035- uint64_t i_spur_rd : 1;10361036- uint64_t i_rsvd : 11;10371037- uint64_t i_mult_err : 1;10561056+ uint64_t ii_iprbb_regval;10571057+ struct {10581058+ uint64_t i_c:8;10591059+ uint64_t i_na:14;10601060+ uint64_t i_rsvd_2:2;10611061+ uint64_t i_nb:14;10621062+ uint64_t i_rsvd_1:2;10631063+ uint64_t i_m:2;10641064+ uint64_t i_f:1;10651065+ uint64_t i_of_cnt:5;10661066+ uint64_t i_error:1;10671067+ uint64_t i_rd_to:1;10681068+ uint64_t i_spur_wr:1;10691069+ uint64_t i_spur_rd:1;10701070+ uint64_t i_rsvd:11;10711071+ uint64_t i_mult_err:1;10381072 } ii_iprbb_fld_s;10391073} ii_iprbb_u_t;1040107410411041-10421075/************************************************************************10431043- * *10761076+ * *10441077 * Description: There are 9 instances of this register, one per *10451078 * actual widget in this implementation of SHub and Crossbow. *10461079 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···10581093 * register; the write will correct the C field and capture its new *10591094 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *10601095 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *10611061- * . *10621062- * *10961096+ * . *10971097+ * *10631098 ************************************************************************/1064109910651100typedef union ii_iprbc_u {10661066- uint64_t ii_iprbc_regval;10671067- struct {10681068- uint64_t i_c : 8;10691069- uint64_t i_na : 14;10701070- uint64_t i_rsvd_2 : 2;10711071- uint64_t i_nb : 14;10721072- uint64_t i_rsvd_1 : 2;10731073- uint64_t i_m : 2;10741074- uint64_t i_f : 1;10751075- uint64_t i_of_cnt : 5;10761076- uint64_t i_error : 1;10771077- uint64_t i_rd_to : 1;10781078- uint64_t i_spur_wr : 1;10791079- uint64_t i_spur_rd : 1;10801080- uint64_t i_rsvd : 11;10811081- uint64_t i_mult_err : 1;11011101+ uint64_t ii_iprbc_regval;11021102+ struct {11031103+ uint64_t i_c:8;11041104+ uint64_t i_na:14;11051105+ uint64_t i_rsvd_2:2;11061106+ uint64_t i_nb:14;11071107+ uint64_t i_rsvd_1:2;11081108+ uint64_t i_m:2;11091109+ uint64_t i_f:1;11101110+ uint64_t i_of_cnt:5;11111111+ uint64_t i_error:1;11121112+ uint64_t i_rd_to:1;11131113+ uint64_t i_spur_wr:1;11141114+ uint64_t i_spur_rd:1;11151115+ uint64_t i_rsvd:11;11161116+ uint64_t i_mult_err:1;10821117 } ii_iprbc_fld_s;10831118} ii_iprbc_u_t;1084111910851085-10861120/************************************************************************10871087- * *11211121+ * *10881122 * Description: There are 9 instances of this register, one per *10891123 * actual widget in this implementation of SHub and Crossbow. *10901124 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···11021138 * register; the write will correct the C field and capture its new *11031139 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *11041140 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *11051105- * . *11061106- * *11411141+ * . *11421142+ * *11071143 ************************************************************************/1108114411091145typedef union ii_iprbd_u {11101110- uint64_t ii_iprbd_regval;11111111- struct {11121112- uint64_t i_c : 8;11131113- uint64_t i_na : 14;11141114- uint64_t i_rsvd_2 : 2;11151115- uint64_t i_nb : 14;11161116- uint64_t i_rsvd_1 : 2;11171117- uint64_t i_m : 2;11181118- uint64_t i_f : 1;11191119- uint64_t i_of_cnt : 5;11201120- uint64_t i_error : 1;11211121- uint64_t i_rd_to : 1;11221122- uint64_t i_spur_wr : 1;11231123- uint64_t i_spur_rd : 1;11241124- uint64_t i_rsvd : 11;11251125- uint64_t i_mult_err : 1;11461146+ uint64_t ii_iprbd_regval;11471147+ struct {11481148+ uint64_t i_c:8;11491149+ uint64_t i_na:14;11501150+ uint64_t i_rsvd_2:2;11511151+ uint64_t i_nb:14;11521152+ uint64_t i_rsvd_1:2;11531153+ uint64_t i_m:2;11541154+ uint64_t i_f:1;11551155+ uint64_t i_of_cnt:5;11561156+ uint64_t i_error:1;11571157+ uint64_t i_rd_to:1;11581158+ uint64_t i_spur_wr:1;11591159+ uint64_t i_spur_rd:1;11601160+ uint64_t i_rsvd:11;11611161+ uint64_t i_mult_err:1;11261162 } ii_iprbd_fld_s;11271163} ii_iprbd_u_t;1128116411291129-11301165/************************************************************************11311131- * *11661166+ * *11321167 * Description: There are 9 instances of this register, one per *11331168 * actual widget in this implementation of SHub and Crossbow. *11341169 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···11461183 * register; the write will correct the C field and capture its new *11471184 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *11481185 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *11491149- * . *11501150- * *11861186+ * . *11871187+ * *11511188 ************************************************************************/1152118911531190typedef union ii_iprbe_u {11541154- uint64_t ii_iprbe_regval;11551155- struct {11561156- uint64_t i_c : 8;11571157- uint64_t i_na : 14;11581158- uint64_t i_rsvd_2 : 2;11591159- uint64_t i_nb : 14;11601160- uint64_t i_rsvd_1 : 2;11611161- uint64_t i_m : 2;11621162- uint64_t i_f : 1;11631163- uint64_t i_of_cnt : 5;11641164- uint64_t i_error : 1;11651165- uint64_t i_rd_to : 1;11661166- uint64_t i_spur_wr : 1;11671167- uint64_t i_spur_rd : 1;11681168- uint64_t i_rsvd : 11;11691169- uint64_t i_mult_err : 1;11911191+ uint64_t ii_iprbe_regval;11921192+ struct {11931193+ uint64_t i_c:8;11941194+ uint64_t i_na:14;11951195+ uint64_t i_rsvd_2:2;11961196+ uint64_t i_nb:14;11971197+ uint64_t i_rsvd_1:2;11981198+ uint64_t i_m:2;11991199+ uint64_t i_f:1;12001200+ uint64_t i_of_cnt:5;12011201+ uint64_t i_error:1;12021202+ uint64_t i_rd_to:1;12031203+ uint64_t i_spur_wr:1;12041204+ uint64_t i_spur_rd:1;12051205+ uint64_t i_rsvd:11;12061206+ uint64_t i_mult_err:1;11701207 } ii_iprbe_fld_s;11711208} ii_iprbe_u_t;1172120911731173-11741210/************************************************************************11751175- * *12111211+ * *11761212 * Description: There are 9 instances of this register, one per *11771213 * actual widget in this implementation of Shub and Crossbow. *11781214 * Note: Crossbow only has ports for Widgets 8 through F, widget 0 *···11901228 * register; the write will correct the C field and capture its new *11911229 * value in the internal register. Even if IECLR[E_PRB_x] is set, the *11921230 * SPUR_WR bit will persist if IPRBx hasn't yet been written. *11931193- * . *11941194- * *12311231+ * . *12321232+ * *11951233 ************************************************************************/1196123411971235typedef union ii_iprbf_u {11981198- uint64_t ii_iprbf_regval;11991199- struct {12001200- uint64_t i_c : 8;12011201- uint64_t i_na : 14;12021202- uint64_t i_rsvd_2 : 2;12031203- uint64_t i_nb : 14;12041204- uint64_t i_rsvd_1 : 2;12051205- uint64_t i_m : 2;12061206- uint64_t i_f : 1;12071207- uint64_t i_of_cnt : 5;12081208- uint64_t i_error : 1;12091209- uint64_t i_rd_to : 1;12101210- uint64_t i_spur_wr : 1;12111211- uint64_t i_spur_rd : 1;12121212- uint64_t i_rsvd : 11;12131213- uint64_t i_mult_err : 1;12141214- } ii_iprbe_fld_s;12361236+ uint64_t ii_iprbf_regval;12371237+ struct {12381238+ uint64_t i_c:8;12391239+ uint64_t i_na:14;12401240+ uint64_t i_rsvd_2:2;12411241+ uint64_t i_nb:14;12421242+ uint64_t i_rsvd_1:2;12431243+ uint64_t i_m:2;12441244+ uint64_t i_f:1;12451245+ uint64_t i_of_cnt:5;12461246+ uint64_t i_error:1;12471247+ uint64_t i_rd_to:1;12481248+ uint64_t i_spur_wr:1;12491249+ uint64_t i_spur_rd:1;12501250+ uint64_t i_rsvd:11;12511251+ uint64_t i_mult_err:1;12521252+ } ii_iprbe_fld_s;12151253} ii_iprbf_u_t;1216125412171217-12181255/************************************************************************12191219- * *12561256+ * *12201257 * This register specifies the timeout value to use for monitoring *12211258 * Crosstalk credits which are used outbound to Crosstalk. An *12221259 * internal counter called the Crosstalk Credit Timeout Counter *···12281267 * Crosstalk Credit Timeout has occurred. The internal counter is not *12291268 * readable from software, and stops counting at its maximum value, *12301269 * so it cannot cause more than one interrupt. *12311231- * *12701270+ * *12321271 ************************************************************************/1233127212341273typedef union ii_ixcc_u {12351235- uint64_t ii_ixcc_regval;12361236- struct {12371237- uint64_t i_time_out : 26;12381238- uint64_t i_rsvd : 38;12741274+ uint64_t ii_ixcc_regval;12751275+ struct {12761276+ uint64_t i_time_out:26;12771277+ uint64_t i_rsvd:38;12391278 } ii_ixcc_fld_s;12401279} ii_ixcc_u_t;1241128012421242-12431281/************************************************************************12441244- * *12821282+ * *12451283 * Description: This register qualifies all the PIO and DMA *12461284 * operations launched from widget 0 towards the SHub. In *12471285 * addition, it also qualifies accesses by the BTE streams. *···12521292 * the Wx_IAC field. The bits in this field are set by writing a 1 to *12531293 * them. Incoming replies from Crosstalk are not subject to this *12541294 * access control mechanism. *12551255- * *12951295+ * *12561296 ************************************************************************/1257129712581298typedef union ii_imem_u {12591259- uint64_t ii_imem_regval;12601260- struct {12611261- uint64_t i_w0_esd : 1;12621262- uint64_t i_rsvd_3 : 3;12631263- uint64_t i_b0_esd : 1;12641264- uint64_t i_rsvd_2 : 3;12651265- uint64_t i_b1_esd : 1;12661266- uint64_t i_rsvd_1 : 3;12671267- uint64_t i_clr_precise : 1;12681268- uint64_t i_rsvd : 51;12991299+ uint64_t ii_imem_regval;13001300+ struct {13011301+ uint64_t i_w0_esd:1;13021302+ uint64_t i_rsvd_3:3;13031303+ uint64_t i_b0_esd:1;13041304+ uint64_t i_rsvd_2:3;13051305+ uint64_t i_b1_esd:1;13061306+ uint64_t i_rsvd_1:3;13071307+ uint64_t i_clr_precise:1;13081308+ uint64_t i_rsvd:51;12691309 } ii_imem_fld_s;12701310} ii_imem_u_t;1271131112721272-12731273-12741312/************************************************************************12751275- * *13131313+ * *12761314 * Description: This register specifies the timeout value to use for *12771315 * monitoring Crosstalk tail flits coming into the Shub in the *12781316 * TAIL_TO field. An internal counter associated with this register *···12901332 * the value in the RRSP_TO field, a Read Response Timeout has *12911333 * occurred, and error handling occurs as described in the Error *12921334 * Handling section of this document. *12931293- * *13351335+ * *12941336 ************************************************************************/1295133712961338typedef union ii_ixtt_u {12971297- uint64_t ii_ixtt_regval;12981298- struct {12991299- uint64_t i_tail_to : 26;13001300- uint64_t i_rsvd_1 : 6;13011301- uint64_t i_rrsp_ps : 23;13021302- uint64_t i_rrsp_to : 5;13031303- uint64_t i_rsvd : 4;13391339+ uint64_t ii_ixtt_regval;13401340+ struct {13411341+ uint64_t i_tail_to:26;13421342+ uint64_t i_rsvd_1:6;13431343+ uint64_t i_rrsp_ps:23;13441344+ uint64_t i_rrsp_to:5;13451345+ uint64_t i_rsvd:4;13041346 } ii_ixtt_fld_s;13051347} ii_ixtt_u_t;1306134813071307-13081349/************************************************************************13091309- * *13501350+ * *13101351 * Writing a 1 to the fields of this register clears the appropriate *13111352 * error bits in other areas of SHub. Note that when the *13121353 * E_PRB_x bits are used to clear error bits in PRB registers, *13131354 * SPUR_RD and SPUR_WR may persist, because they require additional *13141355 * action to clear them. See the IPRBx and IXSS Register *13151356 * specifications. *13161316- * *13571357+ * *13171358 ************************************************************************/1318135913191360typedef union ii_ieclr_u {13201320- uint64_t ii_ieclr_regval;13211321- struct {13221322- uint64_t i_e_prb_0 : 1;13231323- uint64_t i_rsvd : 7;13241324- uint64_t i_e_prb_8 : 1;13251325- uint64_t i_e_prb_9 : 1;13261326- uint64_t i_e_prb_a : 1;13271327- uint64_t i_e_prb_b : 1;13281328- uint64_t i_e_prb_c : 1;13291329- uint64_t i_e_prb_d : 1;13301330- uint64_t i_e_prb_e : 1;13311331- uint64_t i_e_prb_f : 1;13321332- uint64_t i_e_crazy : 1;13331333- uint64_t i_e_bte_0 : 1;13341334- uint64_t i_e_bte_1 : 1;13351335- uint64_t i_reserved_1 : 10;13361336- uint64_t i_spur_rd_hdr : 1;13371337- uint64_t i_cam_intr_to : 1;13381338- uint64_t i_cam_overflow : 1;13391339- uint64_t i_cam_read_miss : 1;13401340- uint64_t i_ioq_rep_underflow : 1;13411341- uint64_t i_ioq_req_underflow : 1;13421342- uint64_t i_ioq_rep_overflow : 1;13431343- uint64_t i_ioq_req_overflow : 1;13441344- uint64_t i_iiq_rep_overflow : 1;13451345- uint64_t i_iiq_req_overflow : 1;13461346- uint64_t i_ii_xn_rep_cred_overflow : 1;13471347- uint64_t i_ii_xn_req_cred_overflow : 1;13481348- uint64_t i_ii_xn_invalid_cmd : 1;13491349- uint64_t i_xn_ii_invalid_cmd : 1;13501350- uint64_t i_reserved_2 : 21;13611361+ uint64_t ii_ieclr_regval;13621362+ struct {13631363+ uint64_t i_e_prb_0:1;13641364+ uint64_t i_rsvd:7;13651365+ uint64_t i_e_prb_8:1;13661366+ uint64_t i_e_prb_9:1;13671367+ uint64_t i_e_prb_a:1;13681368+ uint64_t i_e_prb_b:1;13691369+ uint64_t i_e_prb_c:1;13701370+ uint64_t i_e_prb_d:1;13711371+ uint64_t i_e_prb_e:1;13721372+ uint64_t i_e_prb_f:1;13731373+ uint64_t i_e_crazy:1;13741374+ uint64_t i_e_bte_0:1;13751375+ uint64_t i_e_bte_1:1;13761376+ uint64_t i_reserved_1:10;13771377+ uint64_t i_spur_rd_hdr:1;13781378+ uint64_t i_cam_intr_to:1;13791379+ uint64_t i_cam_overflow:1;13801380+ uint64_t i_cam_read_miss:1;13811381+ uint64_t i_ioq_rep_underflow:1;13821382+ uint64_t i_ioq_req_underflow:1;13831383+ uint64_t i_ioq_rep_overflow:1;13841384+ uint64_t i_ioq_req_overflow:1;13851385+ uint64_t i_iiq_rep_overflow:1;13861386+ uint64_t i_iiq_req_overflow:1;13871387+ uint64_t i_ii_xn_rep_cred_overflow:1;13881388+ uint64_t i_ii_xn_req_cred_overflow:1;13891389+ uint64_t i_ii_xn_invalid_cmd:1;13901390+ uint64_t i_xn_ii_invalid_cmd:1;13911391+ uint64_t i_reserved_2:21;13511392 } ii_ieclr_fld_s;13521393} ii_ieclr_u_t;1353139413541354-13551395/************************************************************************13561356- * *13961396+ * *13571397 * This register controls both BTEs. SOFT_RESET is intended for *13581398 * recovery after an error. COUNT controls the total number of CRBs *13591399 * that both BTEs (combined) can use, which affects total BTE *13601400 * bandwidth. *13611361- * *14011401+ * *13621402 ************************************************************************/1363140313641404typedef union ii_ibcr_u {13651365- uint64_t ii_ibcr_regval;13661366- struct {13671367- uint64_t i_count : 4;13681368- uint64_t i_rsvd_1 : 4;13691369- uint64_t i_soft_reset : 1;13701370- uint64_t i_rsvd : 55;14051405+ uint64_t ii_ibcr_regval;14061406+ struct {14071407+ uint64_t i_count:4;14081408+ uint64_t i_rsvd_1:4;14091409+ uint64_t i_soft_reset:1;14101410+ uint64_t i_rsvd:55;13711411 } ii_ibcr_fld_s;13721412} ii_ibcr_u_t;1373141313741374-13751414/************************************************************************13761376- * *14151415+ * *13771416 * This register contains the header of a spurious read response *13781417 * received from Crosstalk. A spurious read response is defined as a *13791418 * read response received by II from a widget for which (1) the SIDN *···13951440 * will be set. Any SPUR_RD bits in any other PRB registers indicate *13961441 * spurious messages from other widets which were detected after the *13971442 * header was captured.. *13981398- * *14431443+ * *13991444 ************************************************************************/1400144514011446typedef union ii_ixsm_u {14021402- uint64_t ii_ixsm_regval;14031403- struct {14041404- uint64_t i_byte_en : 32;14051405- uint64_t i_reserved : 1;14061406- uint64_t i_tag : 3;14071407- uint64_t i_alt_pactyp : 4;14081408- uint64_t i_bo : 1;14091409- uint64_t i_error : 1;14101410- uint64_t i_vbpm : 1;14111411- uint64_t i_gbr : 1;14121412- uint64_t i_ds : 2;14131413- uint64_t i_ct : 1;14141414- uint64_t i_tnum : 5;14151415- uint64_t i_pactyp : 4;14161416- uint64_t i_sidn : 4;14171417- uint64_t i_didn : 4;14471447+ uint64_t ii_ixsm_regval;14481448+ struct {14491449+ uint64_t i_byte_en:32;14501450+ uint64_t i_reserved:1;14511451+ uint64_t i_tag:3;14521452+ uint64_t i_alt_pactyp:4;14531453+ uint64_t i_bo:1;14541454+ uint64_t i_error:1;14551455+ uint64_t i_vbpm:1;14561456+ uint64_t i_gbr:1;14571457+ uint64_t i_ds:2;14581458+ uint64_t i_ct:1;14591459+ uint64_t i_tnum:5;14601460+ uint64_t i_pactyp:4;14611461+ uint64_t i_sidn:4;14621462+ uint64_t i_didn:4;14181463 } ii_ixsm_fld_s;14191464} ii_ixsm_u_t;1420146514211421-14221466/************************************************************************14231423- * *14671467+ * *14241468 * This register contains the sideband bits of a spurious read *14251469 * response received from Crosstalk. *14261426- * *14701470+ * *14271471 ************************************************************************/1428147214291473typedef union ii_ixss_u {14301430- uint64_t ii_ixss_regval;14311431- struct {14321432- uint64_t i_sideband : 8;14331433- uint64_t i_rsvd : 55;14341434- uint64_t i_valid : 1;14741474+ uint64_t ii_ixss_regval;14751475+ struct {14761476+ uint64_t i_sideband:8;14771477+ uint64_t i_rsvd:55;14781478+ uint64_t i_valid:1;14351479 } ii_ixss_fld_s;14361480} ii_ixss_u_t;1437148114381438-14391482/************************************************************************14401440- * *14831483+ * *14411484 * This register enables software to access the II LLP's test port. *14421485 * Refer to the LLP 2.5 documentation for an explanation of the test *14431486 * port. Software can write to this register to program the values *···14431490 * TestMask and TestSeed). Similarly, software can read from this *14441491 * register to obtain the values of the test port's status outputs *14451492 * (TestCBerr, TestValid and TestData). *14461446- * *14931493+ * *14471494 ************************************************************************/1448149514491496typedef union ii_ilct_u {14501450- uint64_t ii_ilct_regval;14511451- struct {14521452- uint64_t i_test_seed : 20;14531453- uint64_t i_test_mask : 8;14541454- uint64_t i_test_data : 20;14551455- uint64_t i_test_valid : 1;14561456- uint64_t i_test_cberr : 1;14571457- uint64_t i_test_flit : 3;14581458- uint64_t i_test_clear : 1;14591459- uint64_t i_test_err_capture : 1;14601460- uint64_t i_rsvd : 9;14971497+ uint64_t ii_ilct_regval;14981498+ struct {14991499+ uint64_t i_test_seed:20;15001500+ uint64_t i_test_mask:8;15011501+ uint64_t i_test_data:20;15021502+ uint64_t i_test_valid:1;15031503+ uint64_t i_test_cberr:1;15041504+ uint64_t i_test_flit:3;15051505+ uint64_t i_test_clear:1;15061506+ uint64_t i_test_err_capture:1;15071507+ uint64_t i_rsvd:9;14611508 } ii_ilct_fld_s;14621509} ii_ilct_u_t;1463151014641464-14651511/************************************************************************14661466- * *15121512+ * *14671513 * If the II detects an illegal incoming Duplonet packet (request or *14681514 * reply) when VALID==0 in the IIEPH1 register, then it saves the *14691515 * contents of the packet's header flit in the IIEPH1 and IIEPH2 *···14781526 * packet when VALID==1 in the IIEPH1 register, then it merely sets *14791527 * the OVERRUN bit to indicate that a subsequent error has happened, *14801528 * and does nothing further. *14811481- * *15291529+ * *14821530 ************************************************************************/1483153114841532typedef union ii_iieph1_u {14851485- uint64_t ii_iieph1_regval;14861486- struct {14871487- uint64_t i_command : 7;14881488- uint64_t i_rsvd_5 : 1;14891489- uint64_t i_suppl : 14;14901490- uint64_t i_rsvd_4 : 1;14911491- uint64_t i_source : 14;14921492- uint64_t i_rsvd_3 : 1;14931493- uint64_t i_err_type : 4;14941494- uint64_t i_rsvd_2 : 4;14951495- uint64_t i_overrun : 1;14961496- uint64_t i_rsvd_1 : 3;14971497- uint64_t i_valid : 1;14981498- uint64_t i_rsvd : 13;15331533+ uint64_t ii_iieph1_regval;15341534+ struct {15351535+ uint64_t i_command:7;15361536+ uint64_t i_rsvd_5:1;15371537+ uint64_t i_suppl:14;15381538+ uint64_t i_rsvd_4:1;15391539+ uint64_t i_source:14;15401540+ uint64_t i_rsvd_3:1;15411541+ uint64_t i_err_type:4;15421542+ uint64_t i_rsvd_2:4;15431543+ uint64_t i_overrun:1;15441544+ uint64_t i_rsvd_1:3;15451545+ uint64_t i_valid:1;15461546+ uint64_t i_rsvd:13;14991547 } ii_iieph1_fld_s;15001548} ii_iieph1_u_t;1501154915021502-15031550/************************************************************************15041504- * *15511551+ * *15051552 * This register holds the Address field from the header flit of an *15061553 * incoming erroneous Duplonet packet, along with the tail bit which *15071554 * accompanied this header flit. This register is essentially an *15081555 * extension of IIEPH1. Two registers were necessary because the 64 *15091556 * bits available in only a single register were insufficient to *15101557 * capture the entire header flit of an erroneous packet. *15111511- * *15581558+ * *15121559 ************************************************************************/1513156015141561typedef union ii_iieph2_u {15151515- uint64_t ii_iieph2_regval;15161516- struct {15171517- uint64_t i_rsvd_0 : 3;15181518- uint64_t i_address : 47;15191519- uint64_t i_rsvd_1 : 10;15201520- uint64_t i_tail : 1;15211521- uint64_t i_rsvd : 3;15621562+ uint64_t ii_iieph2_regval;15631563+ struct {15641564+ uint64_t i_rsvd_0:3;15651565+ uint64_t i_address:47;15661566+ uint64_t i_rsvd_1:10;15671567+ uint64_t i_tail:1;15681568+ uint64_t i_rsvd:3;15221569 } ii_iieph2_fld_s;15231570} ii_iieph2_u_t;1524157115251525-15261572/******************************/1527157315281528-15291529-15301574/************************************************************************15311531- * *15751575+ * *15321576 * This register's value is a bit vector that guards access from SXBs *15331577 * to local registers within the II as well as to external Crosstalk *15341578 * widgets *15351535- * *15791579+ * *15361580 ************************************************************************/1537158115381582typedef union ii_islapr_u {15391539- uint64_t ii_islapr_regval;15401540- struct {15411541- uint64_t i_region : 64;15831583+ uint64_t ii_islapr_regval;15841584+ struct {15851585+ uint64_t i_region:64;15421586 } ii_islapr_fld_s;15431587} ii_islapr_u_t;1544158815451545-15461589/************************************************************************15471547- * *15901590+ * *15481591 * A write to this register of the 56-bit value "Pup+Bun" will cause *15491592 * the bit in the ISLAPR register corresponding to the region of the *15501593 * requestor to be set (access allowed). (15511551- * *15941594+ * *15521595 ************************************************************************/1553159615541597typedef union ii_islapo_u {15551555- uint64_t ii_islapo_regval;15561556- struct {15571557- uint64_t i_io_sbx_ovrride : 56;15581558- uint64_t i_rsvd : 8;15981598+ uint64_t ii_islapo_regval;15991599+ struct {16001600+ uint64_t i_io_sbx_ovrride:56;16011601+ uint64_t i_rsvd:8;15591602 } ii_islapo_fld_s;15601603} ii_islapo_u_t;1561160415621605/************************************************************************15631563- * *16061606+ * *15641607 * Determines how long the wrapper will wait aftr an interrupt is *15651608 * initially issued from the II before it times out the outstanding *15661609 * interrupt and drops it from the interrupt queue. * 15671567- * *16101610+ * *15681611 ************************************************************************/1569161215701613typedef union ii_iwi_u {15711571- uint64_t ii_iwi_regval;15721572- struct {15731573- uint64_t i_prescale : 24;15741574- uint64_t i_rsvd : 8;15751575- uint64_t i_timeout : 8;15761576- uint64_t i_rsvd1 : 8;15771577- uint64_t i_intrpt_retry_period : 8;15781578- uint64_t i_rsvd2 : 8;16141614+ uint64_t ii_iwi_regval;16151615+ struct {16161616+ uint64_t i_prescale:24;16171617+ uint64_t i_rsvd:8;16181618+ uint64_t i_timeout:8;16191619+ uint64_t i_rsvd1:8;16201620+ uint64_t i_intrpt_retry_period:8;16211621+ uint64_t i_rsvd2:8;15791622 } ii_iwi_fld_s;15801623} ii_iwi_u_t;1581162415821625/************************************************************************15831583- * *16261626+ * *15841627 * Log errors which have occurred in the II wrapper. The errors are *15851628 * cleared by writing to the IECLR register. * 15861586- * *16291629+ * *15871630 ************************************************************************/1588163115891632typedef union ii_iwel_u {15901590- uint64_t ii_iwel_regval;15911591- struct {15921592- uint64_t i_intr_timed_out : 1;15931593- uint64_t i_rsvd : 7;15941594- uint64_t i_cam_overflow : 1;15951595- uint64_t i_cam_read_miss : 1;15961596- uint64_t i_rsvd1 : 2;15971597- uint64_t i_ioq_rep_underflow : 1;15981598- uint64_t i_ioq_req_underflow : 1;15991599- uint64_t i_ioq_rep_overflow : 1;16001600- uint64_t i_ioq_req_overflow : 1;16011601- uint64_t i_iiq_rep_overflow : 1;16021602- uint64_t i_iiq_req_overflow : 1;16031603- uint64_t i_rsvd2 : 6;16041604- uint64_t i_ii_xn_rep_cred_over_under: 1;16051605- uint64_t i_ii_xn_req_cred_over_under: 1;16061606- uint64_t i_rsvd3 : 6;16071607- uint64_t i_ii_xn_invalid_cmd : 1;16081608- uint64_t i_xn_ii_invalid_cmd : 1;16091609- uint64_t i_rsvd4 : 30;16331633+ uint64_t ii_iwel_regval;16341634+ struct {16351635+ uint64_t i_intr_timed_out:1;16361636+ uint64_t i_rsvd:7;16371637+ uint64_t i_cam_overflow:1;16381638+ uint64_t i_cam_read_miss:1;16391639+ uint64_t i_rsvd1:2;16401640+ uint64_t i_ioq_rep_underflow:1;16411641+ uint64_t i_ioq_req_underflow:1;16421642+ uint64_t i_ioq_rep_overflow:1;16431643+ uint64_t i_ioq_req_overflow:1;16441644+ uint64_t i_iiq_rep_overflow:1;16451645+ uint64_t i_iiq_req_overflow:1;16461646+ uint64_t i_rsvd2:6;16471647+ uint64_t i_ii_xn_rep_cred_over_under:1;16481648+ uint64_t i_ii_xn_req_cred_over_under:1;16491649+ uint64_t i_rsvd3:6;16501650+ uint64_t i_ii_xn_invalid_cmd:1;16511651+ uint64_t i_xn_ii_invalid_cmd:1;16521652+ uint64_t i_rsvd4:30;16101653 } ii_iwel_fld_s;16111654} ii_iwel_u_t;1612165516131656/************************************************************************16141614- * *16571657+ * *16151658 * Controls the II wrapper. * 16161616- * *16591659+ * *16171660 ************************************************************************/1618166116191662typedef union ii_iwc_u {16201620- uint64_t ii_iwc_regval;16211621- struct {16221622- uint64_t i_dma_byte_swap : 1;16231623- uint64_t i_rsvd : 3;16241624- uint64_t i_cam_read_lines_reset : 1;16251625- uint64_t i_rsvd1 : 3;16261626- uint64_t i_ii_xn_cred_over_under_log: 1;16271627- uint64_t i_rsvd2 : 19;16281628- uint64_t i_xn_rep_iq_depth : 5;16291629- uint64_t i_rsvd3 : 3;16301630- uint64_t i_xn_req_iq_depth : 5;16311631- uint64_t i_rsvd4 : 3;16321632- uint64_t i_iiq_depth : 6;16331633- uint64_t i_rsvd5 : 12;16341634- uint64_t i_force_rep_cred : 1;16351635- uint64_t i_force_req_cred : 1;16631663+ uint64_t ii_iwc_regval;16641664+ struct {16651665+ uint64_t i_dma_byte_swap:1;16661666+ uint64_t i_rsvd:3;16671667+ uint64_t i_cam_read_lines_reset:1;16681668+ uint64_t i_rsvd1:3;16691669+ uint64_t i_ii_xn_cred_over_under_log:1;16701670+ uint64_t i_rsvd2:19;16711671+ uint64_t i_xn_rep_iq_depth:5;16721672+ uint64_t i_rsvd3:3;16731673+ uint64_t i_xn_req_iq_depth:5;16741674+ uint64_t i_rsvd4:3;16751675+ uint64_t i_iiq_depth:6;16761676+ uint64_t i_rsvd5:12;16771677+ uint64_t i_force_rep_cred:1;16781678+ uint64_t i_force_req_cred:1;16361679 } ii_iwc_fld_s;16371680} ii_iwc_u_t;1638168116391682/************************************************************************16401640- * *16831683+ * *16411684 * Status in the II wrapper. * 16421642- * *16851685+ * *16431686 ************************************************************************/1644168716451688typedef union ii_iws_u {16461646- uint64_t ii_iws_regval;16471647- struct {16481648- uint64_t i_xn_rep_iq_credits : 5;16491649- uint64_t i_rsvd : 3;16501650- uint64_t i_xn_req_iq_credits : 5;16511651- uint64_t i_rsvd1 : 51;16891689+ uint64_t ii_iws_regval;16901690+ struct {16911691+ uint64_t i_xn_rep_iq_credits:5;16921692+ uint64_t i_rsvd:3;16931693+ uint64_t i_xn_req_iq_credits:5;16941694+ uint64_t i_rsvd1:51;16521695 } ii_iws_fld_s;16531696} ii_iws_u_t;1654169716551698/************************************************************************16561656- * *16991699+ * *16571700 * Masks errors in the IWEL register. *16581658- * *17011701+ * *16591702 ************************************************************************/1660170316611704typedef union ii_iweim_u {16621662- uint64_t ii_iweim_regval;16631663- struct {16641664- uint64_t i_intr_timed_out : 1;16651665- uint64_t i_rsvd : 7;16661666- uint64_t i_cam_overflow : 1;16671667- uint64_t i_cam_read_miss : 1;16681668- uint64_t i_rsvd1 : 2;16691669- uint64_t i_ioq_rep_underflow : 1;16701670- uint64_t i_ioq_req_underflow : 1;16711671- uint64_t i_ioq_rep_overflow : 1;16721672- uint64_t i_ioq_req_overflow : 1;16731673- uint64_t i_iiq_rep_overflow : 1;16741674- uint64_t i_iiq_req_overflow : 1;16751675- uint64_t i_rsvd2 : 6;16761676- uint64_t i_ii_xn_rep_cred_overflow : 1;16771677- uint64_t i_ii_xn_req_cred_overflow : 1;16781678- uint64_t i_rsvd3 : 6;16791679- uint64_t i_ii_xn_invalid_cmd : 1;16801680- uint64_t i_xn_ii_invalid_cmd : 1;16811681- uint64_t i_rsvd4 : 30;17051705+ uint64_t ii_iweim_regval;17061706+ struct {17071707+ uint64_t i_intr_timed_out:1;17081708+ uint64_t i_rsvd:7;17091709+ uint64_t i_cam_overflow:1;17101710+ uint64_t i_cam_read_miss:1;17111711+ uint64_t i_rsvd1:2;17121712+ uint64_t i_ioq_rep_underflow:1;17131713+ uint64_t i_ioq_req_underflow:1;17141714+ uint64_t i_ioq_rep_overflow:1;17151715+ uint64_t i_ioq_req_overflow:1;17161716+ uint64_t i_iiq_rep_overflow:1;17171717+ uint64_t i_iiq_req_overflow:1;17181718+ uint64_t i_rsvd2:6;17191719+ uint64_t i_ii_xn_rep_cred_overflow:1;17201720+ uint64_t i_ii_xn_req_cred_overflow:1;17211721+ uint64_t i_rsvd3:6;17221722+ uint64_t i_ii_xn_invalid_cmd:1;17231723+ uint64_t i_xn_ii_invalid_cmd:1;17241724+ uint64_t i_rsvd4:30;16821725 } ii_iweim_fld_s;16831726} ii_iweim_u_t;1684172716851685-16861728/************************************************************************16871687- * *17291729+ * *16881730 * A write to this register causes a particular field in the *16891731 * corresponding widget's PRB entry to be adjusted up or down by 1. *16901732 * This counter should be used when recovering from error and reset *16911733 * conditions. Note that software would be capable of causing *16921734 * inadvertent overflow or underflow of these counters. *16931693- * *17351735+ * *16941736 ************************************************************************/1695173716961738typedef union ii_ipca_u {16971697- uint64_t ii_ipca_regval;16981698- struct {16991699- uint64_t i_wid : 4;17001700- uint64_t i_adjust : 1;17011701- uint64_t i_rsvd_1 : 3;17021702- uint64_t i_field : 2;17031703- uint64_t i_rsvd : 54;17391739+ uint64_t ii_ipca_regval;17401740+ struct {17411741+ uint64_t i_wid:4;17421742+ uint64_t i_adjust:1;17431743+ uint64_t i_rsvd_1:3;17441744+ uint64_t i_field:2;17451745+ uint64_t i_rsvd:54;17041746 } ii_ipca_fld_s;17051747} ii_ipca_u_t;1706174817071707-17081749/************************************************************************17091709- * *17501750+ * *17101751 * There are 8 instances of this register. This register contains *17111752 * the information that the II has to remember once it has launched a *17121753 * PIO Read operation. The contents are used to form the correct *17131754 * Router Network packet and direct the Crosstalk reply to the *17141755 * appropriate processor. *17151715- * *17561756+ * *17161757 ************************************************************************/1717175817181718-17191759typedef union ii_iprte0a_u {17201720- uint64_t ii_iprte0a_regval;17211721- struct {17221722- uint64_t i_rsvd_1 : 54;17231723- uint64_t i_widget : 4;17241724- uint64_t i_to_cnt : 5;17251725- uint64_t i_vld : 1;17601760+ uint64_t ii_iprte0a_regval;17611761+ struct {17621762+ uint64_t i_rsvd_1:54;17631763+ uint64_t i_widget:4;17641764+ uint64_t i_to_cnt:5;17651765+ uint64_t i_vld:1;17261766 } ii_iprte0a_fld_s;17271767} ii_iprte0a_u_t;1728176817291729-17301769/************************************************************************17311731- * *17701770+ * *17321771 * There are 8 instances of this register. This register contains *17331772 * the information that the II has to remember once it has launched a *17341773 * PIO Read operation. The contents are used to form the correct *17351774 * Router Network packet and direct the Crosstalk reply to the *17361775 * appropriate processor. *17371737- * *17761776+ * *17381777 ************************************************************************/1739177817401779typedef union ii_iprte1a_u {17411741- uint64_t ii_iprte1a_regval;17421742- struct {17431743- uint64_t i_rsvd_1 : 54;17441744- uint64_t i_widget : 4;17451745- uint64_t i_to_cnt : 5;17461746- uint64_t i_vld : 1;17801780+ uint64_t ii_iprte1a_regval;17811781+ struct {17821782+ uint64_t i_rsvd_1:54;17831783+ uint64_t i_widget:4;17841784+ uint64_t i_to_cnt:5;17851785+ uint64_t i_vld:1;17471786 } ii_iprte1a_fld_s;17481787} ii_iprte1a_u_t;1749178817501750-17511789/************************************************************************17521752- * *17901790+ * *17531791 * There are 8 instances of this register. This register contains *17541792 * the information that the II has to remember once it has launched a *17551793 * PIO Read operation. The contents are used to form the correct *17561794 * Router Network packet and direct the Crosstalk reply to the *17571795 * appropriate processor. *17581758- * *17961796+ * *17591797 ************************************************************************/1760179817611799typedef union ii_iprte2a_u {17621762- uint64_t ii_iprte2a_regval;17631763- struct {17641764- uint64_t i_rsvd_1 : 54;17651765- uint64_t i_widget : 4;17661766- uint64_t i_to_cnt : 5;17671767- uint64_t i_vld : 1;18001800+ uint64_t ii_iprte2a_regval;18011801+ struct {18021802+ uint64_t i_rsvd_1:54;18031803+ uint64_t i_widget:4;18041804+ uint64_t i_to_cnt:5;18051805+ uint64_t i_vld:1;17681806 } ii_iprte2a_fld_s;17691807} ii_iprte2a_u_t;1770180817711771-17721809/************************************************************************17731773- * *18101810+ * *17741811 * There are 8 instances of this register. This register contains *17751812 * the information that the II has to remember once it has launched a *17761813 * PIO Read operation. The contents are used to form the correct *17771814 * Router Network packet and direct the Crosstalk reply to the *17781815 * appropriate processor. *17791779- * *18161816+ * *17801817 ************************************************************************/1781181817821819typedef union ii_iprte3a_u {17831783- uint64_t ii_iprte3a_regval;17841784- struct {17851785- uint64_t i_rsvd_1 : 54;17861786- uint64_t i_widget : 4;17871787- uint64_t i_to_cnt : 5;17881788- uint64_t i_vld : 1;18201820+ uint64_t ii_iprte3a_regval;18211821+ struct {18221822+ uint64_t i_rsvd_1:54;18231823+ uint64_t i_widget:4;18241824+ uint64_t i_to_cnt:5;18251825+ uint64_t i_vld:1;17891826 } ii_iprte3a_fld_s;17901827} ii_iprte3a_u_t;1791182817921792-17931829/************************************************************************17941794- * *18301830+ * *17951831 * There are 8 instances of this register. This register contains *17961832 * the information that the II has to remember once it has launched a *17971833 * PIO Read operation. The contents are used to form the correct *17981834 * Router Network packet and direct the Crosstalk reply to the *17991835 * appropriate processor. *18001800- * *18361836+ * *18011837 ************************************************************************/1802183818031839typedef union ii_iprte4a_u {18041804- uint64_t ii_iprte4a_regval;18051805- struct {18061806- uint64_t i_rsvd_1 : 54;18071807- uint64_t i_widget : 4;18081808- uint64_t i_to_cnt : 5;18091809- uint64_t i_vld : 1;18401840+ uint64_t ii_iprte4a_regval;18411841+ struct {18421842+ uint64_t i_rsvd_1:54;18431843+ uint64_t i_widget:4;18441844+ uint64_t i_to_cnt:5;18451845+ uint64_t i_vld:1;18101846 } ii_iprte4a_fld_s;18111847} ii_iprte4a_u_t;1812184818131813-18141849/************************************************************************18151815- * *18501850+ * *18161851 * There are 8 instances of this register. This register contains *18171852 * the information that the II has to remember once it has launched a *18181853 * PIO Read operation. The contents are used to form the correct *18191854 * Router Network packet and direct the Crosstalk reply to the *18201855 * appropriate processor. *18211821- * *18561856+ * *18221857 ************************************************************************/1823185818241859typedef union ii_iprte5a_u {18251825- uint64_t ii_iprte5a_regval;18261826- struct {18271827- uint64_t i_rsvd_1 : 54;18281828- uint64_t i_widget : 4;18291829- uint64_t i_to_cnt : 5;18301830- uint64_t i_vld : 1;18601860+ uint64_t ii_iprte5a_regval;18611861+ struct {18621862+ uint64_t i_rsvd_1:54;18631863+ uint64_t i_widget:4;18641864+ uint64_t i_to_cnt:5;18651865+ uint64_t i_vld:1;18311866 } ii_iprte5a_fld_s;18321867} ii_iprte5a_u_t;1833186818341834-18351869/************************************************************************18361836- * *18701870+ * *18371871 * There are 8 instances of this register. This register contains *18381872 * the information that the II has to remember once it has launched a *18391873 * PIO Read operation. The contents are used to form the correct *18401874 * Router Network packet and direct the Crosstalk reply to the *18411875 * appropriate processor. *18421842- * *18761876+ * *18431877 ************************************************************************/1844187818451879typedef union ii_iprte6a_u {18461846- uint64_t ii_iprte6a_regval;18471847- struct {18481848- uint64_t i_rsvd_1 : 54;18491849- uint64_t i_widget : 4;18501850- uint64_t i_to_cnt : 5;18511851- uint64_t i_vld : 1;18801880+ uint64_t ii_iprte6a_regval;18811881+ struct {18821882+ uint64_t i_rsvd_1:54;18831883+ uint64_t i_widget:4;18841884+ uint64_t i_to_cnt:5;18851885+ uint64_t i_vld:1;18521886 } ii_iprte6a_fld_s;18531887} ii_iprte6a_u_t;1854188818551855-18561889/************************************************************************18571857- * *18901890+ * *18581891 * There are 8 instances of this register. This register contains *18591892 * the information that the II has to remember once it has launched a *18601893 * PIO Read operation. The contents are used to form the correct *18611894 * Router Network packet and direct the Crosstalk reply to the *18621895 * appropriate processor. *18631863- * *18961896+ * *18641897 ************************************************************************/1865189818661899typedef union ii_iprte7a_u {18671867- uint64_t ii_iprte7a_regval;18681868- struct {18691869- uint64_t i_rsvd_1 : 54;18701870- uint64_t i_widget : 4;18711871- uint64_t i_to_cnt : 5;18721872- uint64_t i_vld : 1;18731873- } ii_iprtea7_fld_s;19001900+ uint64_t ii_iprte7a_regval;19011901+ struct {19021902+ uint64_t i_rsvd_1:54;19031903+ uint64_t i_widget:4;19041904+ uint64_t i_to_cnt:5;19051905+ uint64_t i_vld:1;19061906+ } ii_iprtea7_fld_s;18741907} ii_iprte7a_u_t;1875190818761876-18771877-18781909/************************************************************************18791879- * *19101910+ * *18801911 * There are 8 instances of this register. This register contains *18811912 * the information that the II has to remember once it has launched a *18821913 * PIO Read operation. The contents are used to form the correct *18831914 * Router Network packet and direct the Crosstalk reply to the *18841915 * appropriate processor. *18851885- * *19161916+ * *18861917 ************************************************************************/1887191818881888-18891919typedef union ii_iprte0b_u {18901890- uint64_t ii_iprte0b_regval;18911891- struct {18921892- uint64_t i_rsvd_1 : 3;18931893- uint64_t i_address : 47;18941894- uint64_t i_init : 3;18951895- uint64_t i_source : 11;19201920+ uint64_t ii_iprte0b_regval;19211921+ struct {19221922+ uint64_t i_rsvd_1:3;19231923+ uint64_t i_address:47;19241924+ uint64_t i_init:3;19251925+ uint64_t i_source:11;18961926 } ii_iprte0b_fld_s;18971927} ii_iprte0b_u_t;1898192818991899-19001929/************************************************************************19011901- * *19301930+ * *19021931 * There are 8 instances of this register. This register contains *19031932 * the information that the II has to remember once it has launched a *19041933 * PIO Read operation. The contents are used to form the correct *19051934 * Router Network packet and direct the Crosstalk reply to the *19061935 * appropriate processor. *19071907- * *19361936+ * *19081937 ************************************************************************/1909193819101939typedef union ii_iprte1b_u {19111911- uint64_t ii_iprte1b_regval;19121912- struct {19131913- uint64_t i_rsvd_1 : 3;19141914- uint64_t i_address : 47;19151915- uint64_t i_init : 3;19161916- uint64_t i_source : 11;19401940+ uint64_t ii_iprte1b_regval;19411941+ struct {19421942+ uint64_t i_rsvd_1:3;19431943+ uint64_t i_address:47;19441944+ uint64_t i_init:3;19451945+ uint64_t i_source:11;19171946 } ii_iprte1b_fld_s;19181947} ii_iprte1b_u_t;1919194819201920-19211949/************************************************************************19221922- * *19501950+ * *19231951 * There are 8 instances of this register. This register contains *19241952 * the information that the II has to remember once it has launched a *19251953 * PIO Read operation. The contents are used to form the correct *19261954 * Router Network packet and direct the Crosstalk reply to the *19271955 * appropriate processor. *19281928- * *19561956+ * *19291957 ************************************************************************/1930195819311959typedef union ii_iprte2b_u {19321932- uint64_t ii_iprte2b_regval;19331933- struct {19341934- uint64_t i_rsvd_1 : 3;19351935- uint64_t i_address : 47;19361936- uint64_t i_init : 3;19371937- uint64_t i_source : 11;19601960+ uint64_t ii_iprte2b_regval;19611961+ struct {19621962+ uint64_t i_rsvd_1:3;19631963+ uint64_t i_address:47;19641964+ uint64_t i_init:3;19651965+ uint64_t i_source:11;19381966 } ii_iprte2b_fld_s;19391967} ii_iprte2b_u_t;1940196819411941-19421969/************************************************************************19431943- * *19701970+ * *19441971 * There are 8 instances of this register. This register contains *19451972 * the information that the II has to remember once it has launched a *19461973 * PIO Read operation. The contents are used to form the correct *19471974 * Router Network packet and direct the Crosstalk reply to the *19481975 * appropriate processor. *19491949- * *19761976+ * *19501977 ************************************************************************/1951197819521979typedef union ii_iprte3b_u {19531953- uint64_t ii_iprte3b_regval;19541954- struct {19551955- uint64_t i_rsvd_1 : 3;19561956- uint64_t i_address : 47;19571957- uint64_t i_init : 3;19581958- uint64_t i_source : 11;19801980+ uint64_t ii_iprte3b_regval;19811981+ struct {19821982+ uint64_t i_rsvd_1:3;19831983+ uint64_t i_address:47;19841984+ uint64_t i_init:3;19851985+ uint64_t i_source:11;19591986 } ii_iprte3b_fld_s;19601987} ii_iprte3b_u_t;1961198819621962-19631989/************************************************************************19641964- * *19901990+ * *19651991 * There are 8 instances of this register. This register contains *19661992 * the information that the II has to remember once it has launched a *19671993 * PIO Read operation. The contents are used to form the correct *19681994 * Router Network packet and direct the Crosstalk reply to the *19691995 * appropriate processor. *19701970- * *19961996+ * *19711997 ************************************************************************/1972199819731999typedef union ii_iprte4b_u {19741974- uint64_t ii_iprte4b_regval;19751975- struct {19761976- uint64_t i_rsvd_1 : 3;19771977- uint64_t i_address : 47;19781978- uint64_t i_init : 3;19791979- uint64_t i_source : 11;20002000+ uint64_t ii_iprte4b_regval;20012001+ struct {20022002+ uint64_t i_rsvd_1:3;20032003+ uint64_t i_address:47;20042004+ uint64_t i_init:3;20052005+ uint64_t i_source:11;19802006 } ii_iprte4b_fld_s;19812007} ii_iprte4b_u_t;1982200819831983-19842009/************************************************************************19851985- * *20102010+ * *19862011 * There are 8 instances of this register. This register contains *19872012 * the information that the II has to remember once it has launched a *19882013 * PIO Read operation. The contents are used to form the correct *19892014 * Router Network packet and direct the Crosstalk reply to the *19902015 * appropriate processor. *19911991- * *20162016+ * *19922017 ************************************************************************/1993201819942019typedef union ii_iprte5b_u {19951995- uint64_t ii_iprte5b_regval;19961996- struct {19971997- uint64_t i_rsvd_1 : 3;19981998- uint64_t i_address : 47;19991999- uint64_t i_init : 3;20002000- uint64_t i_source : 11;20202020+ uint64_t ii_iprte5b_regval;20212021+ struct {20222022+ uint64_t i_rsvd_1:3;20232023+ uint64_t i_address:47;20242024+ uint64_t i_init:3;20252025+ uint64_t i_source:11;20012026 } ii_iprte5b_fld_s;20022027} ii_iprte5b_u_t;2003202820042004-20052029/************************************************************************20062006- * *20302030+ * *20072031 * There are 8 instances of this register. This register contains *20082032 * the information that the II has to remember once it has launched a *20092033 * PIO Read operation. The contents are used to form the correct *20102034 * Router Network packet and direct the Crosstalk reply to the *20112035 * appropriate processor. *20122012- * *20362036+ * *20132037 ************************************************************************/2014203820152039typedef union ii_iprte6b_u {20162016- uint64_t ii_iprte6b_regval;20172017- struct {20182018- uint64_t i_rsvd_1 : 3;20192019- uint64_t i_address : 47;20202020- uint64_t i_init : 3;20212021- uint64_t i_source : 11;20402040+ uint64_t ii_iprte6b_regval;20412041+ struct {20422042+ uint64_t i_rsvd_1:3;20432043+ uint64_t i_address:47;20442044+ uint64_t i_init:3;20452045+ uint64_t i_source:11;2022204620232047 } ii_iprte6b_fld_s;20242048} ii_iprte6b_u_t;2025204920262026-20272050/************************************************************************20282028- * *20512051+ * *20292052 * There are 8 instances of this register. This register contains *20302053 * the information that the II has to remember once it has launched a *20312054 * PIO Read operation. The contents are used to form the correct *20322055 * Router Network packet and direct the Crosstalk reply to the *20332056 * appropriate processor. *20342034- * *20572057+ * *20352058 ************************************************************************/2036205920372060typedef union ii_iprte7b_u {20382038- uint64_t ii_iprte7b_regval;20392039- struct {20402040- uint64_t i_rsvd_1 : 3;20412041- uint64_t i_address : 47;20422042- uint64_t i_init : 3;20432043- uint64_t i_source : 11;20442044- } ii_iprte7b_fld_s;20612061+ uint64_t ii_iprte7b_regval;20622062+ struct {20632063+ uint64_t i_rsvd_1:3;20642064+ uint64_t i_address:47;20652065+ uint64_t i_init:3;20662066+ uint64_t i_source:11;20672067+ } ii_iprte7b_fld_s;20452068} ii_iprte7b_u_t;2046206920472047-20482070/************************************************************************20492049- * *20712071+ * *20502072 * Description: SHub II contains a feature which did not exist in *20512073 * the Hub which automatically cleans up after a Read Response *20522074 * timeout, including deallocation of the IPRTE and recovery of IBuf *···20342108 * Note that this register does not affect the contents of the IPRTE *20352109 * registers. The Valid bits in those registers have to be *20362110 * specifically turned off by software. *20372037- * *21112111+ * *20382112 ************************************************************************/2039211320402114typedef union ii_ipdr_u {20412041- uint64_t ii_ipdr_regval;20422042- struct {20432043- uint64_t i_te : 3;20442044- uint64_t i_rsvd_1 : 1;20452045- uint64_t i_pnd : 1;20462046- uint64_t i_init_rpcnt : 1;20472047- uint64_t i_rsvd : 58;21152115+ uint64_t ii_ipdr_regval;21162116+ struct {21172117+ uint64_t i_te:3;21182118+ uint64_t i_rsvd_1:1;21192119+ uint64_t i_pnd:1;21202120+ uint64_t i_init_rpcnt:1;21212121+ uint64_t i_rsvd:58;20482122 } ii_ipdr_fld_s;20492123} ii_ipdr_u_t;2050212420512051-20522125/************************************************************************20532053- * *21262126+ * *20542127 * A write to this register causes a CRB entry to be returned to the *20552128 * queue of free CRBs. The entry should have previously been cleared *20562129 * (mark bit) via backdoor access to the pertinent CRB entry. This *···20622137 * software clears the mark bit, and finally 4) software writes to *20632138 * the ICDR register to return the CRB entry to the list of free CRB *20642139 * entries. *20652065- * *21402140+ * *20662141 ************************************************************************/2067214220682143typedef union ii_icdr_u {20692069- uint64_t ii_icdr_regval;20702070- struct {20712071- uint64_t i_crb_num : 4;20722072- uint64_t i_pnd : 1;20732073- uint64_t i_rsvd : 59;21442144+ uint64_t ii_icdr_regval;21452145+ struct {21462146+ uint64_t i_crb_num:4;21472147+ uint64_t i_pnd:1;21482148+ uint64_t i_rsvd:59;20742149 } ii_icdr_fld_s;20752150} ii_icdr_u_t;2076215120772077-20782152/************************************************************************20792079- * *21532153+ * *20802154 * This register provides debug access to two FIFOs inside of II. *20812155 * Both IOQ_MAX* fields of this register contain the instantaneous *20822156 * depth (in units of the number of available entries) of the *···20882164 * this register is written. If there are any active entries in any *20892165 * of these FIFOs when this register is written, the results are *20902166 * undefined. *20912091- * *21672167+ * *20922168 ************************************************************************/2093216920942170typedef union ii_ifdr_u {20952095- uint64_t ii_ifdr_regval;20962096- struct {20972097- uint64_t i_ioq_max_rq : 7;20982098- uint64_t i_set_ioq_rq : 1;20992099- uint64_t i_ioq_max_rp : 7;21002100- uint64_t i_set_ioq_rp : 1;21012101- uint64_t i_rsvd : 48;21712171+ uint64_t ii_ifdr_regval;21722172+ struct {21732173+ uint64_t i_ioq_max_rq:7;21742174+ uint64_t i_set_ioq_rq:1;21752175+ uint64_t i_ioq_max_rp:7;21762176+ uint64_t i_set_ioq_rp:1;21772177+ uint64_t i_rsvd:48;21022178 } ii_ifdr_fld_s;21032179} ii_ifdr_u_t;2104218021052105-21062181/************************************************************************21072107- * *21822182+ * *21082183 * This register allows the II to become sluggish in removing *21092184 * messages from its inbound queue (IIQ). This will cause messages to *21102185 * back up in either virtual channel. Disabling the "molasses" mode *21112186 * subsequently allows the II to be tested under stress. In the *21122187 * sluggish ("Molasses") mode, the localized effects of congestion *21132188 * can be observed. *21142114- * *21892189+ * *21152190 ************************************************************************/2116219121172192typedef union ii_iiap_u {21182118- uint64_t ii_iiap_regval;21192119- struct {21202120- uint64_t i_rq_mls : 6;21212121- uint64_t i_rsvd_1 : 2;21222122- uint64_t i_rp_mls : 6;21232123- uint64_t i_rsvd : 50;21242124- } ii_iiap_fld_s;21932193+ uint64_t ii_iiap_regval;21942194+ struct {21952195+ uint64_t i_rq_mls:6;21962196+ uint64_t i_rsvd_1:2;21972197+ uint64_t i_rp_mls:6;21982198+ uint64_t i_rsvd:50;21992199+ } ii_iiap_fld_s;21252200} ii_iiap_u_t;2126220121272127-21282202/************************************************************************21292129- * *22032203+ * *21302204 * This register allows several parameters of CRB operation to be *21312205 * set. Note that writing to this register can have catastrophic side *21322206 * effects, if the CRB is not quiescent, i.e. if the CRB is *21332207 * processing protocol messages when the write occurs. *21342134- * *22082208+ * *21352209 ************************************************************************/2136221021372211typedef union ii_icmr_u {21382138- uint64_t ii_icmr_regval;21392139- struct {21402140- uint64_t i_sp_msg : 1;21412141- uint64_t i_rd_hdr : 1;21422142- uint64_t i_rsvd_4 : 2;21432143- uint64_t i_c_cnt : 4;21442144- uint64_t i_rsvd_3 : 4;21452145- uint64_t i_clr_rqpd : 1;21462146- uint64_t i_clr_rppd : 1;21472147- uint64_t i_rsvd_2 : 2;21482148- uint64_t i_fc_cnt : 4;21492149- uint64_t i_crb_vld : 15;21502150- uint64_t i_crb_mark : 15;21512151- uint64_t i_rsvd_1 : 2;21522152- uint64_t i_precise : 1;21532153- uint64_t i_rsvd : 11;22122212+ uint64_t ii_icmr_regval;22132213+ struct {22142214+ uint64_t i_sp_msg:1;22152215+ uint64_t i_rd_hdr:1;22162216+ uint64_t i_rsvd_4:2;22172217+ uint64_t i_c_cnt:4;22182218+ uint64_t i_rsvd_3:4;22192219+ uint64_t i_clr_rqpd:1;22202220+ uint64_t i_clr_rppd:1;22212221+ uint64_t i_rsvd_2:2;22222222+ uint64_t i_fc_cnt:4;22232223+ uint64_t i_crb_vld:15;22242224+ uint64_t i_crb_mark:15;22252225+ uint64_t i_rsvd_1:2;22262226+ uint64_t i_precise:1;22272227+ uint64_t i_rsvd:11;21542228 } ii_icmr_fld_s;21552229} ii_icmr_u_t;2156223021572157-21582231/************************************************************************21592159- * *22322232+ * *21602233 * This register allows control of the table portion of the CRB *21612234 * logic via software. Control operations from this register have *21622235 * priority over all incoming Crosstalk or BTE requests. *21632163- * *22362236+ * *21642237 ************************************************************************/2165223821662239typedef union ii_iccr_u {21672167- uint64_t ii_iccr_regval;21682168- struct {21692169- uint64_t i_crb_num : 4;21702170- uint64_t i_rsvd_1 : 4;21712171- uint64_t i_cmd : 8;21722172- uint64_t i_pending : 1;21732173- uint64_t i_rsvd : 47;22402240+ uint64_t ii_iccr_regval;22412241+ struct {22422242+ uint64_t i_crb_num:4;22432243+ uint64_t i_rsvd_1:4;22442244+ uint64_t i_cmd:8;22452245+ uint64_t i_pending:1;22462246+ uint64_t i_rsvd:47;21742247 } ii_iccr_fld_s;21752248} ii_iccr_u_t;2176224921772177-21782250/************************************************************************21792179- * *22512251+ * *21802252 * This register allows the maximum timeout value to be programmed. *21812181- * *22532253+ * *21822254 ************************************************************************/2183225521842256typedef union ii_icto_u {21852185- uint64_t ii_icto_regval;21862186- struct {21872187- uint64_t i_timeout : 8;21882188- uint64_t i_rsvd : 56;22572257+ uint64_t ii_icto_regval;22582258+ struct {22592259+ uint64_t i_timeout:8;22602260+ uint64_t i_rsvd:56;21892261 } ii_icto_fld_s;21902262} ii_icto_u_t;2191226321922192-21932264/************************************************************************21942194- * *22652265+ * *21952266 * This register allows the timeout prescalar to be programmed. An *21962267 * internal counter is associated with this register. When the *21972268 * internal counter reaches the value of the PRESCALE field, the *21982269 * timer registers in all valid CRBs are incremented (CRBx_D[TIMEOUT] *21992270 * field). The internal counter resets to zero, and then continues *22002271 * counting. *22012201- * *22722272+ * *22022273 ************************************************************************/2203227422042275typedef union ii_ictp_u {22052205- uint64_t ii_ictp_regval;22062206- struct {22072207- uint64_t i_prescale : 24;22082208- uint64_t i_rsvd : 40;22762276+ uint64_t ii_ictp_regval;22772277+ struct {22782278+ uint64_t i_prescale:24;22792279+ uint64_t i_rsvd:40;22092280 } ii_ictp_fld_s;22102281} ii_ictp_u_t;2211228222122212-22132283/************************************************************************22142214- * *22842284+ * *22152285 * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *22162286 * used for Crosstalk operations (both cacheline and partial *22172287 * operations) or BTE/IO. Because the CRB entries are very wide, five *···22242306 * recovering any potential error state from before the reset). *22252307 * The following four tables summarize the format for the four *22262308 * registers that are used for each ICRB# Entry. *22272227- * *23092309+ * *22282310 ************************************************************************/2229231122302312typedef union ii_icrb0_a_u {22312231- uint64_t ii_icrb0_a_regval;22322232- struct {22332233- uint64_t ia_iow : 1;22342234- uint64_t ia_vld : 1;22352235- uint64_t ia_addr : 47;22362236- uint64_t ia_tnum : 5;22372237- uint64_t ia_sidn : 4;22382238- uint64_t ia_rsvd : 6;23132313+ uint64_t ii_icrb0_a_regval;23142314+ struct {23152315+ uint64_t ia_iow:1;23162316+ uint64_t ia_vld:1;23172317+ uint64_t ia_addr:47;23182318+ uint64_t ia_tnum:5;23192319+ uint64_t ia_sidn:4;23202320+ uint64_t ia_rsvd:6;22392321 } ii_icrb0_a_fld_s;22402322} ii_icrb0_a_u_t;2241232322422242-22432324/************************************************************************22442244- * *23252325+ * *22452326 * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *22462327 * used for Crosstalk operations (both cacheline and partial *22472328 * operations) or BTE/IO. Because the CRB entries are very wide, five *22482329 * registers (_A to _E) are required to read and write each entry. *22492249- * *23302330+ * *22502331 ************************************************************************/2251233222522333typedef union ii_icrb0_b_u {22532253- uint64_t ii_icrb0_b_regval;22542254- struct {22552255- uint64_t ib_xt_err : 1;22562256- uint64_t ib_mark : 1;22572257- uint64_t ib_ln_uce : 1;22582258- uint64_t ib_errcode : 3;22592259- uint64_t ib_error : 1;22602260- uint64_t ib_stall__bte_1 : 1;22612261- uint64_t ib_stall__bte_0 : 1;22622262- uint64_t ib_stall__intr : 1;22632263- uint64_t ib_stall_ib : 1;22642264- uint64_t ib_intvn : 1;22652265- uint64_t ib_wb : 1;22662266- uint64_t ib_hold : 1;22672267- uint64_t ib_ack : 1;22682268- uint64_t ib_resp : 1;22692269- uint64_t ib_ack_cnt : 11;22702270- uint64_t ib_rsvd : 7;22712271- uint64_t ib_exc : 5;22722272- uint64_t ib_init : 3;22732273- uint64_t ib_imsg : 8;22742274- uint64_t ib_imsgtype : 2;22752275- uint64_t ib_use_old : 1;22762276- uint64_t ib_rsvd_1 : 11;23342334+ uint64_t ii_icrb0_b_regval;23352335+ struct {23362336+ uint64_t ib_xt_err:1;23372337+ uint64_t ib_mark:1;23382338+ uint64_t ib_ln_uce:1;23392339+ uint64_t ib_errcode:3;23402340+ uint64_t ib_error:1;23412341+ uint64_t ib_stall__bte_1:1;23422342+ uint64_t ib_stall__bte_0:1;23432343+ uint64_t ib_stall__intr:1;23442344+ uint64_t ib_stall_ib:1;23452345+ uint64_t ib_intvn:1;23462346+ uint64_t ib_wb:1;23472347+ uint64_t ib_hold:1;23482348+ uint64_t ib_ack:1;23492349+ uint64_t ib_resp:1;23502350+ uint64_t ib_ack_cnt:11;23512351+ uint64_t ib_rsvd:7;23522352+ uint64_t ib_exc:5;23532353+ uint64_t ib_init:3;23542354+ uint64_t ib_imsg:8;23552355+ uint64_t ib_imsgtype:2;23562356+ uint64_t ib_use_old:1;23572357+ uint64_t ib_rsvd_1:11;22772358 } ii_icrb0_b_fld_s;22782359} ii_icrb0_b_u_t;2279236022802280-22812361/************************************************************************22822282- * *23622362+ * *22832363 * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *22842364 * used for Crosstalk operations (both cacheline and partial *22852365 * operations) or BTE/IO. Because the CRB entries are very wide, five *22862366 * registers (_A to _E) are required to read and write each entry. *22872287- * *23672367+ * *22882368 ************************************************************************/2289236922902370typedef union ii_icrb0_c_u {22912291- uint64_t ii_icrb0_c_regval;22922292- struct {22932293- uint64_t ic_source : 15;22942294- uint64_t ic_size : 2;22952295- uint64_t ic_ct : 1;22962296- uint64_t ic_bte_num : 1;22972297- uint64_t ic_gbr : 1;22982298- uint64_t ic_resprqd : 1;22992299- uint64_t ic_bo : 1;23002300- uint64_t ic_suppl : 15;23012301- uint64_t ic_rsvd : 27;23712371+ uint64_t ii_icrb0_c_regval;23722372+ struct {23732373+ uint64_t ic_source:15;23742374+ uint64_t ic_size:2;23752375+ uint64_t ic_ct:1;23762376+ uint64_t ic_bte_num:1;23772377+ uint64_t ic_gbr:1;23782378+ uint64_t ic_resprqd:1;23792379+ uint64_t ic_bo:1;23802380+ uint64_t ic_suppl:15;23812381+ uint64_t ic_rsvd:27;23022382 } ii_icrb0_c_fld_s;23032383} ii_icrb0_c_u_t;2304238423052305-23062385/************************************************************************23072307- * *23862386+ * *23082387 * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *23092388 * used for Crosstalk operations (both cacheline and partial *23102389 * operations) or BTE/IO. Because the CRB entries are very wide, five *23112390 * registers (_A to _E) are required to read and write each entry. *23122312- * *23912391+ * *23132392 ************************************************************************/2314239323152394typedef union ii_icrb0_d_u {23162316- uint64_t ii_icrb0_d_regval;23172317- struct {23182318- uint64_t id_pa_be : 43;23192319- uint64_t id_bte_op : 1;23202320- uint64_t id_pr_psc : 4;23212321- uint64_t id_pr_cnt : 4;23222322- uint64_t id_sleep : 1;23232323- uint64_t id_rsvd : 11;23952395+ uint64_t ii_icrb0_d_regval;23962396+ struct {23972397+ uint64_t id_pa_be:43;23982398+ uint64_t id_bte_op:1;23992399+ uint64_t id_pr_psc:4;24002400+ uint64_t id_pr_cnt:4;24012401+ uint64_t id_sleep:1;24022402+ uint64_t id_rsvd:11;23242403 } ii_icrb0_d_fld_s;23252404} ii_icrb0_d_u_t;2326240523272327-23282406/************************************************************************23292329- * *24072407+ * *23302408 * Description: There are 15 CRB Entries (ICRB0 to ICRBE) that are *23312409 * used for Crosstalk operations (both cacheline and partial *23322410 * operations) or BTE/IO. Because the CRB entries are very wide, five *23332411 * registers (_A to _E) are required to read and write each entry. *23342334- * *24122412+ * *23352413 ************************************************************************/2336241423372415typedef union ii_icrb0_e_u {23382338- uint64_t ii_icrb0_e_regval;23392339- struct {23402340- uint64_t ie_timeout : 8;23412341- uint64_t ie_context : 15;23422342- uint64_t ie_rsvd : 1;23432343- uint64_t ie_tvld : 1;23442344- uint64_t ie_cvld : 1;23452345- uint64_t ie_rsvd_0 : 38;24162416+ uint64_t ii_icrb0_e_regval;24172417+ struct {24182418+ uint64_t ie_timeout:8;24192419+ uint64_t ie_context:15;24202420+ uint64_t ie_rsvd:1;24212421+ uint64_t ie_tvld:1;24222422+ uint64_t ie_cvld:1;24232423+ uint64_t ie_rsvd_0:38;23462424 } ii_icrb0_e_fld_s;23472425} ii_icrb0_e_u_t;2348242623492349-23502427/************************************************************************23512351- * *24282428+ * *23522429 * This register contains the lower 64 bits of the header of the *23532430 * spurious message captured by II. Valid when the SP_MSG bit in ICMR *23542431 * register is set. *23552355- * *24322432+ * *23562433 ************************************************************************/2357243423582435typedef union ii_icsml_u {23592359- uint64_t ii_icsml_regval;23602360- struct {23612361- uint64_t i_tt_addr : 47;23622362- uint64_t i_newsuppl_ex : 14;23632363- uint64_t i_reserved : 2;23642364- uint64_t i_overflow : 1;24362436+ uint64_t ii_icsml_regval;24372437+ struct {24382438+ uint64_t i_tt_addr:47;24392439+ uint64_t i_newsuppl_ex:14;24402440+ uint64_t i_reserved:2;24412441+ uint64_t i_overflow:1;23652442 } ii_icsml_fld_s;23662443} ii_icsml_u_t;2367244423682368-23692445/************************************************************************23702370- * *24462446+ * *23712447 * This register contains the middle 64 bits of the header of the *23722448 * spurious message captured by II. Valid when the SP_MSG bit in ICMR *23732449 * register is set. *23742374- * *24502450+ * *23752451 ************************************************************************/2376245223772453typedef union ii_icsmm_u {23782378- uint64_t ii_icsmm_regval;23792379- struct {23802380- uint64_t i_tt_ack_cnt : 11;23812381- uint64_t i_reserved : 53;24542454+ uint64_t ii_icsmm_regval;24552455+ struct {24562456+ uint64_t i_tt_ack_cnt:11;24572457+ uint64_t i_reserved:53;23822458 } ii_icsmm_fld_s;23832459} ii_icsmm_u_t;2384246023852385-23862461/************************************************************************23872387- * *24622462+ * *23882463 * This register contains the microscopic state, all the inputs to *23892464 * the protocol table, captured with the spurious message. Valid when *23902465 * the SP_MSG bit in the ICMR register is set. *23912391- * *24662466+ * *23922467 ************************************************************************/2393246823942469typedef union ii_icsmh_u {23952395- uint64_t ii_icsmh_regval;23962396- struct {23972397- uint64_t i_tt_vld : 1;23982398- uint64_t i_xerr : 1;23992399- uint64_t i_ft_cwact_o : 1;24002400- uint64_t i_ft_wact_o : 1;24012401- uint64_t i_ft_active_o : 1;24022402- uint64_t i_sync : 1;24032403- uint64_t i_mnusg : 1;24042404- uint64_t i_mnusz : 1;24052405- uint64_t i_plusz : 1;24062406- uint64_t i_plusg : 1;24072407- uint64_t i_tt_exc : 5;24082408- uint64_t i_tt_wb : 1;24092409- uint64_t i_tt_hold : 1;24102410- uint64_t i_tt_ack : 1;24112411- uint64_t i_tt_resp : 1;24122412- uint64_t i_tt_intvn : 1;24132413- uint64_t i_g_stall_bte1 : 1;24142414- uint64_t i_g_stall_bte0 : 1;24152415- uint64_t i_g_stall_il : 1;24162416- uint64_t i_g_stall_ib : 1;24172417- uint64_t i_tt_imsg : 8;24182418- uint64_t i_tt_imsgtype : 2;24192419- uint64_t i_tt_use_old : 1;24202420- uint64_t i_tt_respreqd : 1;24212421- uint64_t i_tt_bte_num : 1;24222422- uint64_t i_cbn : 1;24232423- uint64_t i_match : 1;24242424- uint64_t i_rpcnt_lt_34 : 1;24252425- uint64_t i_rpcnt_ge_34 : 1;24262426- uint64_t i_rpcnt_lt_18 : 1;24272427- uint64_t i_rpcnt_ge_18 : 1;24282428- uint64_t i_rpcnt_lt_2 : 1;24292429- uint64_t i_rpcnt_ge_2 : 1;24302430- uint64_t i_rqcnt_lt_18 : 1;24312431- uint64_t i_rqcnt_ge_18 : 1;24322432- uint64_t i_rqcnt_lt_2 : 1;24332433- uint64_t i_rqcnt_ge_2 : 1;24342434- uint64_t i_tt_device : 7;24352435- uint64_t i_tt_init : 3;24362436- uint64_t i_reserved : 5;24702470+ uint64_t ii_icsmh_regval;24712471+ struct {24722472+ uint64_t i_tt_vld:1;24732473+ uint64_t i_xerr:1;24742474+ uint64_t i_ft_cwact_o:1;24752475+ uint64_t i_ft_wact_o:1;24762476+ uint64_t i_ft_active_o:1;24772477+ uint64_t i_sync:1;24782478+ uint64_t i_mnusg:1;24792479+ uint64_t i_mnusz:1;24802480+ uint64_t i_plusz:1;24812481+ uint64_t i_plusg:1;24822482+ uint64_t i_tt_exc:5;24832483+ uint64_t i_tt_wb:1;24842484+ uint64_t i_tt_hold:1;24852485+ uint64_t i_tt_ack:1;24862486+ uint64_t i_tt_resp:1;24872487+ uint64_t i_tt_intvn:1;24882488+ uint64_t i_g_stall_bte1:1;24892489+ uint64_t i_g_stall_bte0:1;24902490+ uint64_t i_g_stall_il:1;24912491+ uint64_t i_g_stall_ib:1;24922492+ uint64_t i_tt_imsg:8;24932493+ uint64_t i_tt_imsgtype:2;24942494+ uint64_t i_tt_use_old:1;24952495+ uint64_t i_tt_respreqd:1;24962496+ uint64_t i_tt_bte_num:1;24972497+ uint64_t i_cbn:1;24982498+ uint64_t i_match:1;24992499+ uint64_t i_rpcnt_lt_34:1;25002500+ uint64_t i_rpcnt_ge_34:1;25012501+ uint64_t i_rpcnt_lt_18:1;25022502+ uint64_t i_rpcnt_ge_18:1;25032503+ uint64_t i_rpcnt_lt_2:1;25042504+ uint64_t i_rpcnt_ge_2:1;25052505+ uint64_t i_rqcnt_lt_18:1;25062506+ uint64_t i_rqcnt_ge_18:1;25072507+ uint64_t i_rqcnt_lt_2:1;25082508+ uint64_t i_rqcnt_ge_2:1;25092509+ uint64_t i_tt_device:7;25102510+ uint64_t i_tt_init:3;25112511+ uint64_t i_reserved:5;24372512 } ii_icsmh_fld_s;24382513} ii_icsmh_u_t;2439251424402440-24412515/************************************************************************24422442- * *25162516+ * *24432517 * The Shub DEBUG unit provides a 3-bit selection signal to the *24442518 * II core and a 3-bit selection signal to the fsbclk domain in the II *24452519 * wrapper. *24462446- * *25202520+ * *24472521 ************************************************************************/2448252224492523typedef union ii_idbss_u {24502450- uint64_t ii_idbss_regval;24512451- struct {24522452- uint64_t i_iioclk_core_submenu : 3;24532453- uint64_t i_rsvd : 5;24542454- uint64_t i_fsbclk_wrapper_submenu : 3;24552455- uint64_t i_rsvd_1 : 5;24562456- uint64_t i_iioclk_menu : 5;24572457- uint64_t i_rsvd_2 : 43;25242524+ uint64_t ii_idbss_regval;25252525+ struct {25262526+ uint64_t i_iioclk_core_submenu:3;25272527+ uint64_t i_rsvd:5;25282528+ uint64_t i_fsbclk_wrapper_submenu:3;25292529+ uint64_t i_rsvd_1:5;25302530+ uint64_t i_iioclk_menu:5;25312531+ uint64_t i_rsvd_2:43;24582532 } ii_idbss_fld_s;24592533} ii_idbss_u_t;2460253424612461-24622535/************************************************************************24632463- * *25362536+ * *24642537 * Description: This register is used to set up the length for a *24652538 * transfer and then to monitor the progress of that transfer. This *24662539 * register needs to be initialized before a transfer is started. A *···24622553 * transfer completes, hardware will clear the Busy bit. The length *24632554 * field will also contain the number of cache lines left to be *24642555 * transferred. *24652465- * *25562556+ * *24662557 ************************************************************************/2467255824682559typedef union ii_ibls0_u {24692469- uint64_t ii_ibls0_regval;24702470- struct {24712471- uint64_t i_length : 16;24722472- uint64_t i_error : 1;24732473- uint64_t i_rsvd_1 : 3;24742474- uint64_t i_busy : 1;24752475- uint64_t i_rsvd : 43;25602560+ uint64_t ii_ibls0_regval;25612561+ struct {25622562+ uint64_t i_length:16;25632563+ uint64_t i_error:1;25642564+ uint64_t i_rsvd_1:3;25652565+ uint64_t i_busy:1;25662566+ uint64_t i_rsvd:43;24762567 } ii_ibls0_fld_s;24772568} ii_ibls0_u_t;2478256924792479-24802570/************************************************************************24812481- * *25712571+ * *24822572 * This register should be loaded before a transfer is started. The *24832573 * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *24842574 * address as described in Section 1.3, Figure2 and Figure3. Since *24852575 * the bottom 7 bits of the address are always taken to be zero, BTE *24862576 * transfers are always cacheline-aligned. *24872487- * *25772577+ * *24882578 ************************************************************************/2489257924902580typedef union ii_ibsa0_u {24912491- uint64_t ii_ibsa0_regval;24922492- struct {24932493- uint64_t i_rsvd_1 : 7;24942494- uint64_t i_addr : 42;24952495- uint64_t i_rsvd : 15;25812581+ uint64_t ii_ibsa0_regval;25822582+ struct {25832583+ uint64_t i_rsvd_1:7;25842584+ uint64_t i_addr:42;25852585+ uint64_t i_rsvd:15;24962586 } ii_ibsa0_fld_s;24972587} ii_ibsa0_u_t;2498258824992499-25002589/************************************************************************25012501- * *25902590+ * *25022591 * This register should be loaded before a transfer is started. The *25032592 * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *25042593 * address as described in Section 1.3, Figure2 and Figure3. Since *25052594 * the bottom 7 bits of the address are always taken to be zero, BTE *25062595 * transfers are always cacheline-aligned. *25072507- * *25962596+ * *25082597 ************************************************************************/2509259825102599typedef union ii_ibda0_u {25112511- uint64_t ii_ibda0_regval;25122512- struct {25132513- uint64_t i_rsvd_1 : 7;25142514- uint64_t i_addr : 42;25152515- uint64_t i_rsvd : 15;26002600+ uint64_t ii_ibda0_regval;26012601+ struct {26022602+ uint64_t i_rsvd_1:7;26032603+ uint64_t i_addr:42;26042604+ uint64_t i_rsvd:15;25162605 } ii_ibda0_fld_s;25172606} ii_ibda0_u_t;2518260725192519-25202608/************************************************************************25212521- * *26092609+ * *25222610 * Writing to this register sets up the attributes of the transfer *25232611 * and initiates the transfer operation. Reading this register has *25242612 * the side effect of terminating any transfer in progress. Note: *···25232617 * other BTE. If a BTE stream has to be stopped (due to error *25242618 * handling for example), both BTE streams should be stopped and *25252619 * their transfers discarded. *25262526- * *26202620+ * *25272621 ************************************************************************/2528262225292623typedef union ii_ibct0_u {25302530- uint64_t ii_ibct0_regval;25312531- struct {25322532- uint64_t i_zerofill : 1;25332533- uint64_t i_rsvd_2 : 3;25342534- uint64_t i_notify : 1;25352535- uint64_t i_rsvd_1 : 3;25362536- uint64_t i_poison : 1;25372537- uint64_t i_rsvd : 55;26242624+ uint64_t ii_ibct0_regval;26252625+ struct {26262626+ uint64_t i_zerofill:1;26272627+ uint64_t i_rsvd_2:3;26282628+ uint64_t i_notify:1;26292629+ uint64_t i_rsvd_1:3;26302630+ uint64_t i_poison:1;26312631+ uint64_t i_rsvd:55;25382632 } ii_ibct0_fld_s;25392633} ii_ibct0_u_t;2540263425412541-25422635/************************************************************************25432543- * *26362636+ * *25442637 * This register contains the address to which the WINV is sent. *25452638 * This address has to be cache line aligned. *25462546- * *26392639+ * *25472640 ************************************************************************/2548264125492642typedef union ii_ibna0_u {25502550- uint64_t ii_ibna0_regval;25512551- struct {25522552- uint64_t i_rsvd_1 : 7;25532553- uint64_t i_addr : 42;25542554- uint64_t i_rsvd : 15;26432643+ uint64_t ii_ibna0_regval;26442644+ struct {26452645+ uint64_t i_rsvd_1:7;26462646+ uint64_t i_addr:42;26472647+ uint64_t i_rsvd:15;25552648 } ii_ibna0_fld_s;25562649} ii_ibna0_u_t;2557265025582558-25592651/************************************************************************25602560- * *26522652+ * *25612653 * This register contains the programmable level as well as the node *25622654 * ID and PI unit of the processor to which the interrupt will be *25632563- * sent. *25642564- * *26552655+ * sent. *26562656+ * *25652657 ************************************************************************/2566265825672659typedef union ii_ibia0_u {25682568- uint64_t ii_ibia0_regval;25692569- struct {25702570- uint64_t i_rsvd_2 : 1;25712571- uint64_t i_node_id : 11;25722572- uint64_t i_rsvd_1 : 4;25732573- uint64_t i_level : 7;25742574- uint64_t i_rsvd : 41;26602660+ uint64_t ii_ibia0_regval;26612661+ struct {26622662+ uint64_t i_rsvd_2:1;26632663+ uint64_t i_node_id:11;26642664+ uint64_t i_rsvd_1:4;26652665+ uint64_t i_level:7;26662666+ uint64_t i_rsvd:41;25752667 } ii_ibia0_fld_s;25762668} ii_ibia0_u_t;2577266925782578-25792670/************************************************************************25802580- * *26712671+ * *25812672 * Description: This register is used to set up the length for a *25822673 * transfer and then to monitor the progress of that transfer. This *25832674 * register needs to be initialized before a transfer is started. A *···25852682 * transfer completes, hardware will clear the Busy bit. The length *25862683 * field will also contain the number of cache lines left to be *25872684 * transferred. *25882588- * *26852685+ * *25892686 ************************************************************************/2590268725912688typedef union ii_ibls1_u {25922592- uint64_t ii_ibls1_regval;25932593- struct {25942594- uint64_t i_length : 16;25952595- uint64_t i_error : 1;25962596- uint64_t i_rsvd_1 : 3;25972597- uint64_t i_busy : 1;25982598- uint64_t i_rsvd : 43;26892689+ uint64_t ii_ibls1_regval;26902690+ struct {26912691+ uint64_t i_length:16;26922692+ uint64_t i_error:1;26932693+ uint64_t i_rsvd_1:3;26942694+ uint64_t i_busy:1;26952695+ uint64_t i_rsvd:43;25992696 } ii_ibls1_fld_s;26002697} ii_ibls1_u_t;2601269826022602-26032699/************************************************************************26042604- * *27002700+ * *26052701 * This register should be loaded before a transfer is started. The *26062702 * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *26072703 * address as described in Section 1.3, Figure2 and Figure3. Since *26082704 * the bottom 7 bits of the address are always taken to be zero, BTE *26092705 * transfers are always cacheline-aligned. *26102610- * *27062706+ * *26112707 ************************************************************************/2612270826132709typedef union ii_ibsa1_u {26142614- uint64_t ii_ibsa1_regval;26152615- struct {26162616- uint64_t i_rsvd_1 : 7;26172617- uint64_t i_addr : 33;26182618- uint64_t i_rsvd : 24;27102710+ uint64_t ii_ibsa1_regval;27112711+ struct {27122712+ uint64_t i_rsvd_1:7;27132713+ uint64_t i_addr:33;27142714+ uint64_t i_rsvd:24;26192715 } ii_ibsa1_fld_s;26202716} ii_ibsa1_u_t;2621271726222622-26232718/************************************************************************26242624- * *27192719+ * *26252720 * This register should be loaded before a transfer is started. The *26262721 * address to be loaded in bits 39:0 is the 40-bit TRex+ physical *26272722 * address as described in Section 1.3, Figure2 and Figure3. Since *26282723 * the bottom 7 bits of the address are always taken to be zero, BTE *26292724 * transfers are always cacheline-aligned. *26302630- * *27252725+ * *26312726 ************************************************************************/2632272726332728typedef union ii_ibda1_u {26342634- uint64_t ii_ibda1_regval;26352635- struct {26362636- uint64_t i_rsvd_1 : 7;26372637- uint64_t i_addr : 33;26382638- uint64_t i_rsvd : 24;27292729+ uint64_t ii_ibda1_regval;27302730+ struct {27312731+ uint64_t i_rsvd_1:7;27322732+ uint64_t i_addr:33;27332733+ uint64_t i_rsvd:24;26392734 } ii_ibda1_fld_s;26402735} ii_ibda1_u_t;2641273626422642-26432737/************************************************************************26442644- * *27382738+ * *26452739 * Writing to this register sets up the attributes of the transfer *26462740 * and initiates the transfer operation. Reading this register has *26472741 * the side effect of terminating any transfer in progress. Note: *···26462746 * other BTE. If a BTE stream has to be stopped (due to error *26472747 * handling for example), both BTE streams should be stopped and *26482748 * their transfers discarded. *26492649- * *27492749+ * *26502750 ************************************************************************/2651275126522752typedef union ii_ibct1_u {26532653- uint64_t ii_ibct1_regval;26542654- struct {26552655- uint64_t i_zerofill : 1;26562656- uint64_t i_rsvd_2 : 3;26572657- uint64_t i_notify : 1;26582658- uint64_t i_rsvd_1 : 3;26592659- uint64_t i_poison : 1;26602660- uint64_t i_rsvd : 55;27532753+ uint64_t ii_ibct1_regval;27542754+ struct {27552755+ uint64_t i_zerofill:1;27562756+ uint64_t i_rsvd_2:3;27572757+ uint64_t i_notify:1;27582758+ uint64_t i_rsvd_1:3;27592759+ uint64_t i_poison:1;27602760+ uint64_t i_rsvd:55;26612761 } ii_ibct1_fld_s;26622762} ii_ibct1_u_t;2663276326642664-26652764/************************************************************************26662666- * *27652765+ * *26672766 * This register contains the address to which the WINV is sent. *26682767 * This address has to be cache line aligned. *26692669- * *27682768+ * *26702769 ************************************************************************/2671277026722771typedef union ii_ibna1_u {26732673- uint64_t ii_ibna1_regval;26742674- struct {26752675- uint64_t i_rsvd_1 : 7;26762676- uint64_t i_addr : 33;26772677- uint64_t i_rsvd : 24;27722772+ uint64_t ii_ibna1_regval;27732773+ struct {27742774+ uint64_t i_rsvd_1:7;27752775+ uint64_t i_addr:33;27762776+ uint64_t i_rsvd:24;26782777 } ii_ibna1_fld_s;26792778} ii_ibna1_u_t;2680277926812681-26822780/************************************************************************26832683- * *27812781+ * *26842782 * This register contains the programmable level as well as the node *26852783 * ID and PI unit of the processor to which the interrupt will be *26862686- * sent. *26872687- * *27842784+ * sent. *27852785+ * *26882786 ************************************************************************/2689278726902788typedef union ii_ibia1_u {26912691- uint64_t ii_ibia1_regval;26922692- struct {26932693- uint64_t i_pi_id : 1;26942694- uint64_t i_node_id : 8;26952695- uint64_t i_rsvd_1 : 7;26962696- uint64_t i_level : 7;26972697- uint64_t i_rsvd : 41;27892789+ uint64_t ii_ibia1_regval;27902790+ struct {27912791+ uint64_t i_pi_id:1;27922792+ uint64_t i_node_id:8;27932793+ uint64_t i_rsvd_1:7;27942794+ uint64_t i_level:7;27952795+ uint64_t i_rsvd:41;26982796 } ii_ibia1_fld_s;26992797} ii_ibia1_u_t;2700279827012701-27022799/************************************************************************27032703- * *28002800+ * *27042801 * This register defines the resources that feed information into *27052802 * the two performance counters located in the IO Performance *27062803 * Profiling Register. There are 17 different quantities that can be *···27082811 * other is available from the other performance counter. Hence, the *27092812 * II supports all 17*16=272 possible combinations of quantities to *27102813 * measure. *27112711- * *28142814+ * *27122815 ************************************************************************/2713281627142817typedef union ii_ipcr_u {27152715- uint64_t ii_ipcr_regval;27162716- struct {27172717- uint64_t i_ippr0_c : 4;27182718- uint64_t i_ippr1_c : 4;27192719- uint64_t i_icct : 8;27202720- uint64_t i_rsvd : 48;28182818+ uint64_t ii_ipcr_regval;28192819+ struct {28202820+ uint64_t i_ippr0_c:4;28212821+ uint64_t i_ippr1_c:4;28222822+ uint64_t i_icct:8;28232823+ uint64_t i_rsvd:48;27212824 } ii_ipcr_fld_s;27222825} ii_ipcr_u_t;2723282627242724-27252827/************************************************************************27262726- * *27272727- * *27282728- * *28282828+ * *28292829+ * *28302830+ * *27292831 ************************************************************************/2730283227312833typedef union ii_ippr_u {27322732- uint64_t ii_ippr_regval;27332733- struct {27342734- uint64_t i_ippr0 : 32;27352735- uint64_t i_ippr1 : 32;28342834+ uint64_t ii_ippr_regval;28352835+ struct {28362836+ uint64_t i_ippr0:32;28372837+ uint64_t i_ippr1:32;27362838 } ii_ippr_fld_s;27372839} ii_ippr_u_t;2738284027392739-27402740-27412741-/**************************************************************************27422742- * *27432743- * The following defines which were not formed into structures are *27442744- * probably indentical to another register, and the name of the *27452745- * register is provided against each of these registers. This *27462746- * information needs to be checked carefully *27472747- * *27482748- * IIO_ICRB1_A IIO_ICRB0_A *27492749- * IIO_ICRB1_B IIO_ICRB0_B *27502750- * IIO_ICRB1_C IIO_ICRB0_C *27512751- * IIO_ICRB1_D IIO_ICRB0_D *27522752- * IIO_ICRB1_E IIO_ICRB0_E *27532753- * IIO_ICRB2_A IIO_ICRB0_A *27542754- * IIO_ICRB2_B IIO_ICRB0_B *27552755- * IIO_ICRB2_C IIO_ICRB0_C *27562756- * IIO_ICRB2_D IIO_ICRB0_D *27572757- * IIO_ICRB2_E IIO_ICRB0_E *27582758- * IIO_ICRB3_A IIO_ICRB0_A *27592759- * IIO_ICRB3_B IIO_ICRB0_B *27602760- * IIO_ICRB3_C IIO_ICRB0_C *27612761- * IIO_ICRB3_D IIO_ICRB0_D *27622762- * IIO_ICRB3_E IIO_ICRB0_E *27632763- * IIO_ICRB4_A IIO_ICRB0_A *27642764- * IIO_ICRB4_B IIO_ICRB0_B *27652765- * IIO_ICRB4_C IIO_ICRB0_C *27662766- * IIO_ICRB4_D IIO_ICRB0_D *27672767- * IIO_ICRB4_E IIO_ICRB0_E *27682768- * IIO_ICRB5_A IIO_ICRB0_A *27692769- * IIO_ICRB5_B IIO_ICRB0_B *27702770- * IIO_ICRB5_C IIO_ICRB0_C *27712771- * IIO_ICRB5_D IIO_ICRB0_D *27722772- * IIO_ICRB5_E IIO_ICRB0_E *27732773- * IIO_ICRB6_A IIO_ICRB0_A *27742774- * IIO_ICRB6_B IIO_ICRB0_B *27752775- * IIO_ICRB6_C IIO_ICRB0_C *27762776- * IIO_ICRB6_D IIO_ICRB0_D *27772777- * IIO_ICRB6_E IIO_ICRB0_E *27782778- * IIO_ICRB7_A IIO_ICRB0_A *27792779- * IIO_ICRB7_B IIO_ICRB0_B *27802780- * IIO_ICRB7_C IIO_ICRB0_C *27812781- * IIO_ICRB7_D IIO_ICRB0_D *27822782- * IIO_ICRB7_E IIO_ICRB0_E *27832783- * IIO_ICRB8_A IIO_ICRB0_A *27842784- * IIO_ICRB8_B IIO_ICRB0_B *27852785- * IIO_ICRB8_C IIO_ICRB0_C *27862786- * IIO_ICRB8_D IIO_ICRB0_D *27872787- * IIO_ICRB8_E IIO_ICRB0_E *27882788- * IIO_ICRB9_A IIO_ICRB0_A *27892789- * IIO_ICRB9_B IIO_ICRB0_B *27902790- * IIO_ICRB9_C IIO_ICRB0_C *27912791- * IIO_ICRB9_D IIO_ICRB0_D *27922792- * IIO_ICRB9_E IIO_ICRB0_E *27932793- * IIO_ICRBA_A IIO_ICRB0_A *27942794- * IIO_ICRBA_B IIO_ICRB0_B *27952795- * IIO_ICRBA_C IIO_ICRB0_C *27962796- * IIO_ICRBA_D IIO_ICRB0_D *27972797- * IIO_ICRBA_E IIO_ICRB0_E *27982798- * IIO_ICRBB_A IIO_ICRB0_A *27992799- * IIO_ICRBB_B IIO_ICRB0_B *28002800- * IIO_ICRBB_C IIO_ICRB0_C *28012801- * IIO_ICRBB_D IIO_ICRB0_D *28022802- * IIO_ICRBB_E IIO_ICRB0_E *28032803- * IIO_ICRBC_A IIO_ICRB0_A *28042804- * IIO_ICRBC_B IIO_ICRB0_B *28052805- * IIO_ICRBC_C IIO_ICRB0_C *28062806- * IIO_ICRBC_D IIO_ICRB0_D *28072807- * IIO_ICRBC_E IIO_ICRB0_E *28082808- * IIO_ICRBD_A IIO_ICRB0_A *28092809- * IIO_ICRBD_B IIO_ICRB0_B *28102810- * IIO_ICRBD_C IIO_ICRB0_C *28112811- * IIO_ICRBD_D IIO_ICRB0_D *28122812- * IIO_ICRBD_E IIO_ICRB0_E *28132813- * IIO_ICRBE_A IIO_ICRB0_A *28142814- * IIO_ICRBE_B IIO_ICRB0_B *28152815- * IIO_ICRBE_C IIO_ICRB0_C *28162816- * IIO_ICRBE_D IIO_ICRB0_D *28172817- * IIO_ICRBE_E IIO_ICRB0_E *28182818- * *28192819- **************************************************************************/28202820-28412841+/************************************************************************28422842+ * *28432843+ * The following defines which were not formed into structures are *28442844+ * probably indentical to another register, and the name of the *28452845+ * register is provided against each of these registers. This *28462846+ * information needs to be checked carefully *28472847+ * *28482848+ * IIO_ICRB1_A IIO_ICRB0_A *28492849+ * IIO_ICRB1_B IIO_ICRB0_B *28502850+ * IIO_ICRB1_C IIO_ICRB0_C *28512851+ * IIO_ICRB1_D IIO_ICRB0_D *28522852+ * IIO_ICRB1_E IIO_ICRB0_E *28532853+ * IIO_ICRB2_A IIO_ICRB0_A *28542854+ * IIO_ICRB2_B IIO_ICRB0_B *28552855+ * IIO_ICRB2_C IIO_ICRB0_C *28562856+ * IIO_ICRB2_D IIO_ICRB0_D *28572857+ * IIO_ICRB2_E IIO_ICRB0_E *28582858+ * IIO_ICRB3_A IIO_ICRB0_A *28592859+ * IIO_ICRB3_B IIO_ICRB0_B *28602860+ * IIO_ICRB3_C IIO_ICRB0_C *28612861+ * IIO_ICRB3_D IIO_ICRB0_D *28622862+ * IIO_ICRB3_E IIO_ICRB0_E *28632863+ * IIO_ICRB4_A IIO_ICRB0_A *28642864+ * IIO_ICRB4_B IIO_ICRB0_B *28652865+ * IIO_ICRB4_C IIO_ICRB0_C *28662866+ * IIO_ICRB4_D IIO_ICRB0_D *28672867+ * IIO_ICRB4_E IIO_ICRB0_E *28682868+ * IIO_ICRB5_A IIO_ICRB0_A *28692869+ * IIO_ICRB5_B IIO_ICRB0_B *28702870+ * IIO_ICRB5_C IIO_ICRB0_C *28712871+ * IIO_ICRB5_D IIO_ICRB0_D *28722872+ * IIO_ICRB5_E IIO_ICRB0_E *28732873+ * IIO_ICRB6_A IIO_ICRB0_A *28742874+ * IIO_ICRB6_B IIO_ICRB0_B *28752875+ * IIO_ICRB6_C IIO_ICRB0_C *28762876+ * IIO_ICRB6_D IIO_ICRB0_D *28772877+ * IIO_ICRB6_E IIO_ICRB0_E *28782878+ * IIO_ICRB7_A IIO_ICRB0_A *28792879+ * IIO_ICRB7_B IIO_ICRB0_B *28802880+ * IIO_ICRB7_C IIO_ICRB0_C *28812881+ * IIO_ICRB7_D IIO_ICRB0_D *28822882+ * IIO_ICRB7_E IIO_ICRB0_E *28832883+ * IIO_ICRB8_A IIO_ICRB0_A *28842884+ * IIO_ICRB8_B IIO_ICRB0_B *28852885+ * IIO_ICRB8_C IIO_ICRB0_C *28862886+ * IIO_ICRB8_D IIO_ICRB0_D *28872887+ * IIO_ICRB8_E IIO_ICRB0_E *28882888+ * IIO_ICRB9_A IIO_ICRB0_A *28892889+ * IIO_ICRB9_B IIO_ICRB0_B *28902890+ * IIO_ICRB9_C IIO_ICRB0_C *28912891+ * IIO_ICRB9_D IIO_ICRB0_D *28922892+ * IIO_ICRB9_E IIO_ICRB0_E *28932893+ * IIO_ICRBA_A IIO_ICRB0_A *28942894+ * IIO_ICRBA_B IIO_ICRB0_B *28952895+ * IIO_ICRBA_C IIO_ICRB0_C *28962896+ * IIO_ICRBA_D IIO_ICRB0_D *28972897+ * IIO_ICRBA_E IIO_ICRB0_E *28982898+ * IIO_ICRBB_A IIO_ICRB0_A *28992899+ * IIO_ICRBB_B IIO_ICRB0_B *29002900+ * IIO_ICRBB_C IIO_ICRB0_C *29012901+ * IIO_ICRBB_D IIO_ICRB0_D *29022902+ * IIO_ICRBB_E IIO_ICRB0_E *29032903+ * IIO_ICRBC_A IIO_ICRB0_A *29042904+ * IIO_ICRBC_B IIO_ICRB0_B *29052905+ * IIO_ICRBC_C IIO_ICRB0_C *29062906+ * IIO_ICRBC_D IIO_ICRB0_D *29072907+ * IIO_ICRBC_E IIO_ICRB0_E *29082908+ * IIO_ICRBD_A IIO_ICRB0_A *29092909+ * IIO_ICRBD_B IIO_ICRB0_B *29102910+ * IIO_ICRBD_C IIO_ICRB0_C *29112911+ * IIO_ICRBD_D IIO_ICRB0_D *29122912+ * IIO_ICRBD_E IIO_ICRB0_E *29132913+ * IIO_ICRBE_A IIO_ICRB0_A *29142914+ * IIO_ICRBE_B IIO_ICRB0_B *29152915+ * IIO_ICRBE_C IIO_ICRB0_C *29162916+ * IIO_ICRBE_D IIO_ICRB0_D *29172917+ * IIO_ICRBE_E IIO_ICRB0_E *29182918+ * *29192919+ ************************************************************************/2821292028222921/*28232922 * Slightly friendlier names for some common registers.28242923 */28252825-#define IIO_WIDGET IIO_WID /* Widget identification */28262826-#define IIO_WIDGET_STAT IIO_WSTAT /* Widget status register */28272827-#define IIO_WIDGET_CTRL IIO_WCR /* Widget control register */28282828-#define IIO_PROTECT IIO_ILAPR /* IO interface protection */28292829-#define IIO_PROTECT_OVRRD IIO_ILAPO /* IO protect override */28302830-#define IIO_OUTWIDGET_ACCESS IIO_IOWA /* Outbound widget access */28312831-#define IIO_INWIDGET_ACCESS IIO_IIWA /* Inbound widget access */28322832-#define IIO_INDEV_ERR_MASK IIO_IIDEM /* Inbound device error mask */28332833-#define IIO_LLP_CSR IIO_ILCSR /* LLP control and status */28342834-#define IIO_LLP_LOG IIO_ILLR /* LLP log */28352835-#define IIO_XTALKCC_TOUT IIO_IXCC /* Xtalk credit count timeout*/28362836-#define IIO_XTALKTT_TOUT IIO_IXTT /* Xtalk tail timeout */28372837-#define IIO_IO_ERR_CLR IIO_IECLR /* IO error clear */29242924+#define IIO_WIDGET IIO_WID /* Widget identification */29252925+#define IIO_WIDGET_STAT IIO_WSTAT /* Widget status register */29262926+#define IIO_WIDGET_CTRL IIO_WCR /* Widget control register */29272927+#define IIO_PROTECT IIO_ILAPR /* IO interface protection */29282928+#define IIO_PROTECT_OVRRD IIO_ILAPO /* IO protect override */29292929+#define IIO_OUTWIDGET_ACCESS IIO_IOWA /* Outbound widget access */29302930+#define IIO_INWIDGET_ACCESS IIO_IIWA /* Inbound widget access */29312931+#define IIO_INDEV_ERR_MASK IIO_IIDEM /* Inbound device error mask */29322932+#define IIO_LLP_CSR IIO_ILCSR /* LLP control and status */29332933+#define IIO_LLP_LOG IIO_ILLR /* LLP log */29342934+#define IIO_XTALKCC_TOUT IIO_IXCC /* Xtalk credit count timeout */29352935+#define IIO_XTALKTT_TOUT IIO_IXTT /* Xtalk tail timeout */29362936+#define IIO_IO_ERR_CLR IIO_IECLR /* IO error clear */28382937#define IIO_IGFX_0 IIO_IGFX028392938#define IIO_IGFX_1 IIO_IGFX128402939#define IIO_IBCT_0 IIO_IBCT0···28502957#define IIO_PRTE_A(_x) (IIO_IPRTE0_A + (8 * (_x)))28512958#define IIO_PRTE_B(_x) (IIO_IPRTE0_B + (8 * (_x)))28522959#define IIO_NUM_PRTES 8 /* Total number of PRB table entries */28532853-#define IIO_WIDPRTE_A(x) IIO_PRTE_A(((x) - 8)) /* widget ID to its PRTE num */28542854-#define IIO_WIDPRTE_B(x) IIO_PRTE_B(((x) - 8)) /* widget ID to its PRTE num */29602960+#define IIO_WIDPRTE_A(x) IIO_PRTE_A(((x) - 8)) /* widget ID to its PRTE num */29612961+#define IIO_WIDPRTE_B(x) IIO_PRTE_B(((x) - 8)) /* widget ID to its PRTE num */2855296228562856-#define IIO_NUM_IPRBS (9) 29632963+#define IIO_NUM_IPRBS 92857296428582858-#define IIO_LLP_CSR_IS_UP 0x0000200029652965+#define IIO_LLP_CSR_IS_UP 0x0000200028592966#define IIO_LLP_CSR_LLP_STAT_MASK 0x0000300028602967#define IIO_LLP_CSR_LLP_STAT_SHFT 1228612968···28632970#define IIO_LLP_SN_MAX 0xffff /* in ILLR SN_CNT, Max Sequence Number errors */2864297128652972/* key to IIO_PROTECT_OVRRD */28662866-#define IIO_PROTECT_OVRRD_KEY 0x53474972756c6573ull /* "SGIrules" */29732973+#define IIO_PROTECT_OVRRD_KEY 0x53474972756c6573ull /* "SGIrules" */2867297428682975/* BTE register names */28692869-#define IIO_BTE_STAT_0 IIO_IBLS_0 /* Also BTE length/status 0 */28702870-#define IIO_BTE_SRC_0 IIO_IBSA_0 /* Also BTE source address 0 */28712871-#define IIO_BTE_DEST_0 IIO_IBDA_0 /* Also BTE dest. address 0 */28722872-#define IIO_BTE_CTRL_0 IIO_IBCT_0 /* Also BTE control/terminate 0 */28732873-#define IIO_BTE_NOTIFY_0 IIO_IBNA_0 /* Also BTE notification 0 */28742874-#define IIO_BTE_INT_0 IIO_IBIA_0 /* Also BTE interrupt 0 */28752875-#define IIO_BTE_OFF_0 0 /* Base offset from BTE 0 regs. */28762876-#define IIO_BTE_OFF_1 (IIO_IBLS_1 - IIO_IBLS_0) /* Offset from base to BTE 1 */29762976+#define IIO_BTE_STAT_0 IIO_IBLS_0 /* Also BTE length/status 0 */29772977+#define IIO_BTE_SRC_0 IIO_IBSA_0 /* Also BTE source address 0 */29782978+#define IIO_BTE_DEST_0 IIO_IBDA_0 /* Also BTE dest. address 0 */29792979+#define IIO_BTE_CTRL_0 IIO_IBCT_0 /* Also BTE control/terminate 0 */29802980+#define IIO_BTE_NOTIFY_0 IIO_IBNA_0 /* Also BTE notification 0 */29812981+#define IIO_BTE_INT_0 IIO_IBIA_0 /* Also BTE interrupt 0 */29822982+#define IIO_BTE_OFF_0 0 /* Base offset from BTE 0 regs. */29832983+#define IIO_BTE_OFF_1 (IIO_IBLS_1 - IIO_IBLS_0) /* Offset from base to BTE 1 */2877298428782985/* BTE register offsets from base */28792986#define BTEOFF_STAT 028802880-#define BTEOFF_SRC (IIO_BTE_SRC_0 - IIO_BTE_STAT_0)28812881-#define BTEOFF_DEST (IIO_BTE_DEST_0 - IIO_BTE_STAT_0)28822882-#define BTEOFF_CTRL (IIO_BTE_CTRL_0 - IIO_BTE_STAT_0)28832883-#define BTEOFF_NOTIFY (IIO_BTE_NOTIFY_0 - IIO_BTE_STAT_0)28842884-#define BTEOFF_INT (IIO_BTE_INT_0 - IIO_BTE_STAT_0)28852885-29872987+#define BTEOFF_SRC (IIO_BTE_SRC_0 - IIO_BTE_STAT_0)29882988+#define BTEOFF_DEST (IIO_BTE_DEST_0 - IIO_BTE_STAT_0)29892989+#define BTEOFF_CTRL (IIO_BTE_CTRL_0 - IIO_BTE_STAT_0)29902990+#define BTEOFF_NOTIFY (IIO_BTE_NOTIFY_0 - IIO_BTE_STAT_0)29912991+#define BTEOFF_INT (IIO_BTE_INT_0 - IIO_BTE_STAT_0)2886299228872993/* names used in shub diags */28882888-#define IIO_BASE_BTE0 IIO_IBLS_0 28892889-#define IIO_BASE_BTE1 IIO_IBLS_1 29942994+#define IIO_BASE_BTE0 IIO_IBLS_029952995+#define IIO_BASE_BTE1 IIO_IBLS_12890299628912997/*28922998 * Macro which takes the widget number, and returns the···28933001 * value _x is expected to be a widget number in the range28943002 * 0, 8 - 0xF28953003 */28962896-#define IIO_IOPRB(_x) (IIO_IOPRB_0 + ( ( (_x) < HUB_WIDGET_ID_MIN ? \28972897- (_x) : \28982898- (_x) - (HUB_WIDGET_ID_MIN-1)) << 3) )28992899-30043004+#define IIO_IOPRB(_x) (IIO_IOPRB_0 + ( ( (_x) < HUB_WIDGET_ID_MIN ? \30053005+ (_x) : \30063006+ (_x) - (HUB_WIDGET_ID_MIN-1)) << 3) )2900300729013008/* GFX Flow Control Node/Widget Register */29023009#define IIO_IGFX_W_NUM_BITS 4 /* size of widget num field */···29153024 (((pi) & IIO_IGFX_PI_NUM_MASK)<< IIO_IGFX_PI_NUM_SHIFT)| \29163025 (((node) & IIO_IGFX_N_NUM_MASK) << IIO_IGFX_N_NUM_SHIFT) | \29173026 (((cpu) & IIO_IGFX_P_NUM_MASK) << IIO_IGFX_P_NUM_SHIFT))29182918-2919302729203028/* Scratch registers (all bits available) */29213029#define IIO_SCRATCH_REG0 IIO_ISCR0···29363046#define IIO_SCRATCH_BIT1_0 0x0000000000000001UL29373047#define IIO_SCRATCH_BIT1_1 0x0000000000000002UL29383048/* IO Translation Table Entries */29392939-#define IIO_NUM_ITTES 7 /* ITTEs numbered 0..6 */29402940- /* Hw manuals number them 1..7! */30493049+#define IIO_NUM_ITTES 7 /* ITTEs numbered 0..6 */30503050+ /* Hw manuals number them 1..7! */29413051/*29423052 * IIO_IMEM Register fields.29433053 */29442944-#define IIO_IMEM_W0ESD 0x1UL /* Widget 0 shut down due to error */29452945-#define IIO_IMEM_B0ESD (1UL << 4) /* BTE 0 shut down due to error */29462946-#define IIO_IMEM_B1ESD (1UL << 8) /* BTE 1 Shut down due to error */30543054+#define IIO_IMEM_W0ESD 0x1UL /* Widget 0 shut down due to error */30553055+#define IIO_IMEM_B0ESD (1UL << 4) /* BTE 0 shut down due to error */30563056+#define IIO_IMEM_B1ESD (1UL << 8) /* BTE 1 Shut down due to error */2947305729483058/*29493059 * As a permanent workaround for a bug in the PI side of the shub, we've29503060 * redefined big window 7 as small window 0.29513061 XXX does this still apply for SN1??29523062 */29532953-#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)30633063+#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)2954306429553065/*29563066 * Use the top big window as a surrogate for the first small window···2961307129623072/*29633073 * CRB manipulation macros29642964- * The CRB macros are slightly complicated, since there are up to29652965- * four registers associated with each CRB entry.30743074+ * The CRB macros are slightly complicated, since there are up to30753075+ * four registers associated with each CRB entry.29663076 */29672967-#define IIO_NUM_CRBS 15 /* Number of CRBs */29682968-#define IIO_NUM_PC_CRBS 4 /* Number of partial cache CRBs */30773077+#define IIO_NUM_CRBS 15 /* Number of CRBs */30783078+#define IIO_NUM_PC_CRBS 4 /* Number of partial cache CRBs */29693079#define IIO_ICRB_OFFSET 829703080#define IIO_ICRB_0 IIO_ICRB0_A29713081#define IIO_ICRB_ADDR_SHFT 2 /* Shift to get proper address */···29733083 #define IIO_FIRST_PC_ENTRY 1229743084 */2975308529762976-#define IIO_ICRB_A(_x) ((u64)(IIO_ICRB_0 + (6 * IIO_ICRB_OFFSET * (_x))))29772977-#define IIO_ICRB_B(_x) ((u64)((char *)IIO_ICRB_A(_x) + 1*IIO_ICRB_OFFSET))29782978-#define IIO_ICRB_C(_x) ((u64)((char *)IIO_ICRB_A(_x) + 2*IIO_ICRB_OFFSET))29792979-#define IIO_ICRB_D(_x) ((u64)((char *)IIO_ICRB_A(_x) + 3*IIO_ICRB_OFFSET))29802980-#define IIO_ICRB_E(_x) ((u64)((char *)IIO_ICRB_A(_x) + 4*IIO_ICRB_OFFSET))30863086+#define IIO_ICRB_A(_x) ((u64)(IIO_ICRB_0 + (6 * IIO_ICRB_OFFSET * (_x))))30873087+#define IIO_ICRB_B(_x) ((u64)((char *)IIO_ICRB_A(_x) + 1*IIO_ICRB_OFFSET))30883088+#define IIO_ICRB_C(_x) ((u64)((char *)IIO_ICRB_A(_x) + 2*IIO_ICRB_OFFSET))30893089+#define IIO_ICRB_D(_x) ((u64)((char *)IIO_ICRB_A(_x) + 3*IIO_ICRB_OFFSET))30903090+#define IIO_ICRB_E(_x) ((u64)((char *)IIO_ICRB_A(_x) + 4*IIO_ICRB_OFFSET))2981309129823092#define TNUM_TO_WIDGET_DEV(_tnum) (_tnum & 0x7)2983309329843094/*29853095 * values for "ecode" field29863096 */29872987-#define IIO_ICRB_ECODE_DERR 0 /* Directory error due to IIO access */29882988-#define IIO_ICRB_ECODE_PERR 1 /* Poison error on IO access */29892989-#define IIO_ICRB_ECODE_WERR 2 /* Write error by IIO access29902990- * e.g. WINV to a Read only line. */29912991-#define IIO_ICRB_ECODE_AERR 3 /* Access error caused by IIO access */29922992-#define IIO_ICRB_ECODE_PWERR 4 /* Error on partial write */29932993-#define IIO_ICRB_ECODE_PRERR 5 /* Error on partial read */29942994-#define IIO_ICRB_ECODE_TOUT 6 /* CRB timeout before deallocating */29952995-#define IIO_ICRB_ECODE_XTERR 7 /* Incoming xtalk pkt had error bit */30973097+#define IIO_ICRB_ECODE_DERR 0 /* Directory error due to IIO access */30983098+#define IIO_ICRB_ECODE_PERR 1 /* Poison error on IO access */30993099+#define IIO_ICRB_ECODE_WERR 2 /* Write error by IIO access31003100+ * e.g. WINV to a Read only line. */31013101+#define IIO_ICRB_ECODE_AERR 3 /* Access error caused by IIO access */31023102+#define IIO_ICRB_ECODE_PWERR 4 /* Error on partial write */31033103+#define IIO_ICRB_ECODE_PRERR 5 /* Error on partial read */31043104+#define IIO_ICRB_ECODE_TOUT 6 /* CRB timeout before deallocating */31053105+#define IIO_ICRB_ECODE_XTERR 7 /* Incoming xtalk pkt had error bit */2996310629973107/*29983108 * Values for field imsgtype29993109 */30003000-#define IIO_ICRB_IMSGT_XTALK 0 /* Incoming Meessage from Xtalk */30013001-#define IIO_ICRB_IMSGT_BTE 1 /* Incoming message from BTE */30023002-#define IIO_ICRB_IMSGT_SN1NET 2 /* Incoming message from SN1 net */30033003-#define IIO_ICRB_IMSGT_CRB 3 /* Incoming message from CRB ??? */31103110+#define IIO_ICRB_IMSGT_XTALK 0 /* Incoming Meessage from Xtalk */31113111+#define IIO_ICRB_IMSGT_BTE 1 /* Incoming message from BTE */31123112+#define IIO_ICRB_IMSGT_SN1NET 2 /* Incoming message from SN1 net */31133113+#define IIO_ICRB_IMSGT_CRB 3 /* Incoming message from CRB ??? */3004311430053115/*30063116 * values for field initiator.30073117 */30083008-#define IIO_ICRB_INIT_XTALK 0 /* Message originated in xtalk */30093009-#define IIO_ICRB_INIT_BTE0 0x1 /* Message originated in BTE 0 */30103010-#define IIO_ICRB_INIT_SN1NET 0x2 /* Message originated in SN1net */30113011-#define IIO_ICRB_INIT_CRB 0x3 /* Message originated in CRB ? */30123012-#define IIO_ICRB_INIT_BTE1 0x5 /* MEssage originated in BTE 1 */31183118+#define IIO_ICRB_INIT_XTALK 0 /* Message originated in xtalk */31193119+#define IIO_ICRB_INIT_BTE0 0x1 /* Message originated in BTE 0 */31203120+#define IIO_ICRB_INIT_SN1NET 0x2 /* Message originated in SN1net */31213121+#define IIO_ICRB_INIT_CRB 0x3 /* Message originated in CRB ? */31223122+#define IIO_ICRB_INIT_BTE1 0x5 /* MEssage originated in BTE 1 */3013312330143124/*30153125 * Number of credits Hub widget has while sending req/response to···30173127 * Value of 3 is required by Xbow 1.130183128 * We may be able to increase this to 4 with Xbow 1.2.30193129 */30203020-#define HUBII_XBOW_CREDIT 330213021-#define HUBII_XBOW_REV2_CREDIT 431303130+#define HUBII_XBOW_CREDIT 331313131+#define HUBII_XBOW_REV2_CREDIT 43022313230233133/*30243134 * Number of credits that xtalk devices should use when communicating···30493159 */3050316030513161#define IIO_ICMR_CRB_VLD_SHFT 2030523052-#define IIO_ICMR_CRB_VLD_MASK (0x7fffUL << IIO_ICMR_CRB_VLD_SHFT)31623162+#define IIO_ICMR_CRB_VLD_MASK (0x7fffUL << IIO_ICMR_CRB_VLD_SHFT)3053316330543164#define IIO_ICMR_FC_CNT_SHFT 1630553055-#define IIO_ICMR_FC_CNT_MASK (0xf << IIO_ICMR_FC_CNT_SHFT)31653165+#define IIO_ICMR_FC_CNT_MASK (0xf << IIO_ICMR_FC_CNT_SHFT)3056316630573167#define IIO_ICMR_C_CNT_SHFT 430583058-#define IIO_ICMR_C_CNT_MASK (0xf << IIO_ICMR_C_CNT_SHFT)31683168+#define IIO_ICMR_C_CNT_MASK (0xf << IIO_ICMR_C_CNT_SHFT)3059316930603060-#define IIO_ICMR_PRECISE (1UL << 52)30613061-#define IIO_ICMR_CLR_RPPD (1UL << 13)30623062-#define IIO_ICMR_CLR_RQPD (1UL << 12)31703170+#define IIO_ICMR_PRECISE (1UL << 52)31713171+#define IIO_ICMR_CLR_RPPD (1UL << 13)31723172+#define IIO_ICMR_CLR_RQPD (1UL << 12)3063317330643174/*30653175 * IIO PIO Deallocation register field masks : (IIO_IPDR)30663176 XXX present but not needed in bedrock? See the manual.30673177 */30683068-#define IIO_IPDR_PND (1 << 4)31783178+#define IIO_IPDR_PND (1 << 4)3069317930703180/*30713181 * IIO CRB deallocation register field masks: (IIO_ICDR)30723182 */30733073-#define IIO_ICDR_PND (1 << 4)31833183+#define IIO_ICDR_PND (1 << 4)3074318430753185/* 30763186 * IO BTE Length/Status (IIO_IBLS) register bit field definitions···31133223/*31143224 * IO Error Clear register bit field definitions31153225 */31163116-#define IECLR_PI1_FWD_INT (1UL << 31) /* clear PI1_FORWARD_INT in iidsr */31173117-#define IECLR_PI0_FWD_INT (1UL << 30) /* clear PI0_FORWARD_INT in iidsr */31183118-#define IECLR_SPUR_RD_HDR (1UL << 29) /* clear valid bit in ixss reg */31193119-#define IECLR_BTE1 (1UL << 18) /* clear bte error 1 */31203120-#define IECLR_BTE0 (1UL << 17) /* clear bte error 0 */31213121-#define IECLR_CRAZY (1UL << 16) /* clear crazy bit in wstat reg */31223122-#define IECLR_PRB_F (1UL << 15) /* clear err bit in PRB_F reg */31233123-#define IECLR_PRB_E (1UL << 14) /* clear err bit in PRB_E reg */31243124-#define IECLR_PRB_D (1UL << 13) /* clear err bit in PRB_D reg */31253125-#define IECLR_PRB_C (1UL << 12) /* clear err bit in PRB_C reg */31263126-#define IECLR_PRB_B (1UL << 11) /* clear err bit in PRB_B reg */31273127-#define IECLR_PRB_A (1UL << 10) /* clear err bit in PRB_A reg */31283128-#define IECLR_PRB_9 (1UL << 9) /* clear err bit in PRB_9 reg */31293129-#define IECLR_PRB_8 (1UL << 8) /* clear err bit in PRB_8 reg */31303130-#define IECLR_PRB_0 (1UL << 0) /* clear err bit in PRB_0 reg */32263226+#define IECLR_PI1_FWD_INT (1UL << 31) /* clear PI1_FORWARD_INT in iidsr */32273227+#define IECLR_PI0_FWD_INT (1UL << 30) /* clear PI0_FORWARD_INT in iidsr */32283228+#define IECLR_SPUR_RD_HDR (1UL << 29) /* clear valid bit in ixss reg */32293229+#define IECLR_BTE1 (1UL << 18) /* clear bte error 1 */32303230+#define IECLR_BTE0 (1UL << 17) /* clear bte error 0 */32313231+#define IECLR_CRAZY (1UL << 16) /* clear crazy bit in wstat reg */32323232+#define IECLR_PRB_F (1UL << 15) /* clear err bit in PRB_F reg */32333233+#define IECLR_PRB_E (1UL << 14) /* clear err bit in PRB_E reg */32343234+#define IECLR_PRB_D (1UL << 13) /* clear err bit in PRB_D reg */32353235+#define IECLR_PRB_C (1UL << 12) /* clear err bit in PRB_C reg */32363236+#define IECLR_PRB_B (1UL << 11) /* clear err bit in PRB_B reg */32373237+#define IECLR_PRB_A (1UL << 10) /* clear err bit in PRB_A reg */32383238+#define IECLR_PRB_9 (1UL << 9) /* clear err bit in PRB_9 reg */32393239+#define IECLR_PRB_8 (1UL << 8) /* clear err bit in PRB_8 reg */32403240+#define IECLR_PRB_0 (1UL << 0) /* clear err bit in PRB_0 reg */3131324131323242/*31333243 * IIO CRB control register Fields: IIO_ICCR 31343244 */31353135-#define IIO_ICCR_PENDING (0x10000)31363136-#define IIO_ICCR_CMD_MASK (0xFF)31373137-#define IIO_ICCR_CMD_SHFT (7)31383138-#define IIO_ICCR_CMD_NOP (0x0) /* No Op */31393139-#define IIO_ICCR_CMD_WAKE (0x100) /* Reactivate CRB entry and process */31403140-#define IIO_ICCR_CMD_TIMEOUT (0x200) /* Make CRB timeout & mark invalid */31413141-#define IIO_ICCR_CMD_EJECT (0x400) /* Contents of entry written to memory 32453245+#define IIO_ICCR_PENDING 0x1000032463246+#define IIO_ICCR_CMD_MASK 0xFF32473247+#define IIO_ICCR_CMD_SHFT 732483248+#define IIO_ICCR_CMD_NOP 0x0 /* No Op */32493249+#define IIO_ICCR_CMD_WAKE 0x100 /* Reactivate CRB entry and process */32503250+#define IIO_ICCR_CMD_TIMEOUT 0x200 /* Make CRB timeout & mark invalid */32513251+#define IIO_ICCR_CMD_EJECT 0x400 /* Contents of entry written to memory31423252 * via a WB31433253 */31443144-#define IIO_ICCR_CMD_FLUSH (0x800)32543254+#define IIO_ICCR_CMD_FLUSH 0x8003145325531463256/*31473257 *···31733283 * Easy access macros for CRBs, all 5 registers (A-E)31743284 */31753285typedef ii_icrb0_a_u_t icrba_t;31763176-#define a_sidn ii_icrb0_a_fld_s.ia_sidn31773177-#define a_tnum ii_icrb0_a_fld_s.ia_tnum32863286+#define a_sidn ii_icrb0_a_fld_s.ia_sidn32873287+#define a_tnum ii_icrb0_a_fld_s.ia_tnum31783288#define a_addr ii_icrb0_a_fld_s.ia_addr31793289#define a_valid ii_icrb0_a_fld_s.ia_vld31803290#define a_iow ii_icrb0_a_fld_s.ia_iow···32143324#define c_source ii_icrb0_c_fld_s.ic_source32153325#define c_regvalue ii_icrb0_c_regval3216332632173217-32183327typedef ii_icrb0_d_u_t icrbd_t;32193328#define d_sleep ii_icrb0_d_fld_s.id_sleep32203329#define d_pricnt ii_icrb0_d_fld_s.id_pr_cnt32213330#define d_pripsc ii_icrb0_d_fld_s.id_pr_psc32223331#define d_bteop ii_icrb0_d_fld_s.id_bte_op32233223-#define d_bteaddr ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names*/32243224-#define d_benable ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names*/33323332+#define d_bteaddr ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names */33333333+#define d_benable ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names */32253334#define d_regvalue ii_icrb0_d_regval3226333532273336typedef ii_icrb0_e_u_t icrbe_t;···32293340#define icrbe_context ii_icrb0_e_fld_s.ie_context32303341#define icrbe_timeout ii_icrb0_e_fld_s.ie_timeout32313342#define e_regvalue ii_icrb0_e_regval32323232-3233334332343344/* Number of widgets supported by shub */32353345#define HUB_NUM_WIDGET 9···3255336732563368#define LNK_STAT_WORKING 0x2 /* LLP is working */3257336932583258-#define IIO_WSTAT_ECRAZY (1ULL << 32) /* Hub gone crazy */32593259-#define IIO_WSTAT_TXRETRY (1ULL << 9) /* Hub Tx Retry timeout */32603260-#define IIO_WSTAT_TXRETRY_MASK (0x7F) /* should be 0xFF?? */32613261-#define IIO_WSTAT_TXRETRY_SHFT (16)32623262-#define IIO_WSTAT_TXRETRY_CNT(w) (((w) >> IIO_WSTAT_TXRETRY_SHFT) & \32633263- IIO_WSTAT_TXRETRY_MASK)33703370+#define IIO_WSTAT_ECRAZY (1ULL << 32) /* Hub gone crazy */33713371+#define IIO_WSTAT_TXRETRY (1ULL << 9) /* Hub Tx Retry timeout */33723372+#define IIO_WSTAT_TXRETRY_MASK 0x7F /* should be 0xFF?? */33733373+#define IIO_WSTAT_TXRETRY_SHFT 1633743374+#define IIO_WSTAT_TXRETRY_CNT(w) (((w) >> IIO_WSTAT_TXRETRY_SHFT) & \33753375+ IIO_WSTAT_TXRETRY_MASK)3264337632653377/* Number of II perf. counters we can multiplex at once */3266337832673379#define IO_PERF_SETS 323268338032693381/* Bit for the widget in inbound access register */32703270-#define IIO_IIWA_WIDGET(_w) ((uint64_t)(1ULL << _w))33823382+#define IIO_IIWA_WIDGET(_w) ((uint64_t)(1ULL << _w))32713383/* Bit for the widget in outbound access register */32723272-#define IIO_IOWA_WIDGET(_w) ((uint64_t)(1ULL << _w))33843384+#define IIO_IOWA_WIDGET(_w) ((uint64_t)(1ULL << _w))3273338532743386/* NOTE: The following define assumes that we are going to get32753387 * widget numbers from 8 thru F and the device numbers within32763388 * widget from 0 thru 7.32773389 */32783278-#define IIO_IIDEM_WIDGETDEV_MASK(w, d) ((uint64_t)(1ULL << (8 * ((w) - 8) + (d))))33903390+#define IIO_IIDEM_WIDGETDEV_MASK(w, d) ((uint64_t)(1ULL << (8 * ((w) - 8) + (d))))3279339132803392/* IO Interrupt Destination Register */32813393#define IIO_IIDSR_SENT_SHIFT 28···32903402#define IIO_IIDSR_LVL_MASK 0x000000ff3291340332923404/* Xtalk timeout threshhold register (IIO_IXTT) */32933293-#define IXTT_RRSP_TO_SHFT 55 /* read response timeout */34053405+#define IXTT_RRSP_TO_SHFT 55 /* read response timeout */32943406#define IXTT_RRSP_TO_MASK (0x1FULL << IXTT_RRSP_TO_SHFT)32953295-#define IXTT_RRSP_PS_SHFT 32 /* read responsed TO prescalar */34073407+#define IXTT_RRSP_PS_SHFT 32 /* read responsed TO prescalar */32963408#define IXTT_RRSP_PS_MASK (0x7FFFFFULL << IXTT_RRSP_PS_SHFT)32973297-#define IXTT_TAIL_TO_SHFT 0 /* tail timeout counter threshold */34093409+#define IXTT_TAIL_TO_SHFT 0 /* tail timeout counter threshold */32983410#define IXTT_TAIL_TO_MASK (0x3FFFFFFULL << IXTT_TAIL_TO_SHFT)3299341133003412/*···33023414 */3303341533043416typedef union hubii_wcr_u {33053305- uint64_t wcr_reg_value;33063306- struct {33073307- uint64_t wcr_widget_id: 4, /* LLP crossbar credit */33083308- wcr_tag_mode: 1, /* Tag mode */33093309- wcr_rsvd1: 8, /* Reserved */33103310- wcr_xbar_crd: 3, /* LLP crossbar credit */33113311- wcr_f_bad_pkt: 1, /* Force bad llp pkt enable */33123312- wcr_dir_con: 1, /* widget direct connect */33133313- wcr_e_thresh: 5, /* elasticity threshold */33143314- wcr_rsvd: 41; /* unused */33153315- } wcr_fields_s;34173417+ uint64_t wcr_reg_value;34183418+ struct {34193419+ uint64_t wcr_widget_id:4, /* LLP crossbar credit */34203420+ wcr_tag_mode:1, /* Tag mode */34213421+ wcr_rsvd1:8, /* Reserved */34223422+ wcr_xbar_crd:3, /* LLP crossbar credit */34233423+ wcr_f_bad_pkt:1, /* Force bad llp pkt enable */34243424+ wcr_dir_con:1, /* widget direct connect */34253425+ wcr_e_thresh:5, /* elasticity threshold */34263426+ wcr_rsvd:41; /* unused */34273427+ } wcr_fields_s;33163428} hubii_wcr_t;3317342933183430#define iwcr_dir_con wcr_fields_s.wcr_dir_con···33243436 performed */3325343733263438typedef union io_perf_sel {33273327- uint64_t perf_sel_reg;33283328- struct {33293329- uint64_t perf_ippr0 : 4,33303330- perf_ippr1 : 4,33313331- perf_icct : 8,33323332- perf_rsvd : 48;33333333- } perf_sel_bits;34393439+ uint64_t perf_sel_reg;34403440+ struct {34413441+ uint64_t perf_ippr0:4, perf_ippr1:4, perf_icct:8, perf_rsvd:48;34423442+ } perf_sel_bits;33343443} io_perf_sel_t;3335344433363445/* io_perf_cnt is to extract the count from the shub registers. Due to33373446 hardware problems there is only one counter, not two. */3338344733393448typedef union io_perf_cnt {33403340- uint64_t perf_cnt;33413341- struct {33423342- uint64_t perf_cnt : 20,33433343- perf_rsvd2 : 12,33443344- perf_rsvd1 : 32;33453345- } perf_cnt_bits;34493449+ uint64_t perf_cnt;34503450+ struct {34513451+ uint64_t perf_cnt:20, perf_rsvd2:12, perf_rsvd1:32;34523452+ } perf_cnt_bits;3346345333473454} io_perf_cnt_t;3348345533493456typedef union iprte_a {33503350- uint64_t entry;34573457+ uint64_t entry;33513458 struct {33523352- uint64_t i_rsvd_1 : 3;33533353- uint64_t i_addr : 38;33543354- uint64_t i_init : 3;33553355- uint64_t i_source : 8;33563356- uint64_t i_rsvd : 2;33573357- uint64_t i_widget : 4;33583358- uint64_t i_to_cnt : 5;33593359- uint64_t i_vld : 1;34593459+ uint64_t i_rsvd_1:3;34603460+ uint64_t i_addr:38;34613461+ uint64_t i_init:3;34623462+ uint64_t i_source:8;34633463+ uint64_t i_rsvd:2;34643464+ uint64_t i_widget:4;34653465+ uint64_t i_to_cnt:5;34663466+ uint64_t i_vld:1;33603467 } iprte_fields;33613468} iprte_a_t;3362346933633363-#endif /* _ASM_IA64_SN_SHUBIO_H */33643364-34703470+#endif /* _ASM_IA64_SN_SHUBIO_H */
+11-14
include/asm-ia64/sn/sn_cpuid.h
···44 * License. See the file "COPYING" in the main directory of this archive55 * for more details.66 *77- * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.77+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.88 */991010···9292 * NOTE: on non-MP systems, only cpuid 0 exists9393 */94949595-extern short physical_node_map[]; /* indexed by nasid to get cnode */9595+extern short physical_node_map[]; /* indexed by nasid to get cnode */96969797/*9898 * Macros for retrieving info about current cpu9999 */100100-#define get_nasid() (nodepda->phys_cpuid[smp_processor_id()].nasid)101101-#define get_subnode() (nodepda->phys_cpuid[smp_processor_id()].subnode)102102-#define get_slice() (nodepda->phys_cpuid[smp_processor_id()].slice)103103-#define get_cnode() (nodepda->phys_cpuid[smp_processor_id()].cnode)104104-#define get_sapicid() ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)100100+#define get_nasid() (sn_nodepda->phys_cpuid[smp_processor_id()].nasid)101101+#define get_subnode() (sn_nodepda->phys_cpuid[smp_processor_id()].subnode)102102+#define get_slice() (sn_nodepda->phys_cpuid[smp_processor_id()].slice)103103+#define get_cnode() (sn_nodepda->phys_cpuid[smp_processor_id()].cnode)104104+#define get_sapicid() ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)105105106106/*107107 * Macros for retrieving info about an arbitrary cpu108108 * cpuid - logical cpu id109109 */110110-#define cpuid_to_nasid(cpuid) (nodepda->phys_cpuid[cpuid].nasid)111111-#define cpuid_to_subnode(cpuid) (nodepda->phys_cpuid[cpuid].subnode)112112-#define cpuid_to_slice(cpuid) (nodepda->phys_cpuid[cpuid].slice)110110+#define cpuid_to_nasid(cpuid) (sn_nodepda->phys_cpuid[cpuid].nasid)111111+#define cpuid_to_subnode(cpuid) (sn_nodepda->phys_cpuid[cpuid].subnode)112112+#define cpuid_to_slice(cpuid) (sn_nodepda->phys_cpuid[cpuid].slice)113113#define cpuid_to_cnodeid(cpuid) (physical_node_map[cpuid_to_nasid(cpuid)])114114115115···123123124124/*125125 * cnodeid_to_nasid - convert a cnodeid to a NASID126126- * Macro relies on pg_data for a node being on the node itself.127127- * Just extract the NASID from the pointer.128128- *129126 */130130-#define cnodeid_to_nasid(cnodeid) pda->cnodeid_to_nasid_table[cnodeid]127127+#define cnodeid_to_nasid(cnodeid) (sn_cnodeid_to_nasid[cnodeid])131128132129/*133130 * nasid_to_cnodeid - convert a NASID to a cnodeid
-44
include/asm-ia64/sn/sn_fru.h
···11-/*22- * This file is subject to the terms and conditions of the GNU General Public33- * License. See the file "COPYING" in the main directory of this archive44- * for more details.55- *66- * Copyright (C) 1992-1997,1999-2004 Silicon Graphics, Inc. All rights reserved.77- */88-#ifndef _ASM_IA64_SN_SN_FRU_H99-#define _ASM_IA64_SN_SN_FRU_H1010-1111-#define MAX_DIMMS 8 /* max # of dimm banks */1212-#define MAX_PCIDEV 8 /* max # of pci devices on a pci bus */1313-1414-typedef unsigned char confidence_t;1515-1616-typedef struct kf_mem_s {1717- confidence_t km_confidence; /* confidence level that the memory is bad1818- * is this necessary ?1919- */2020- confidence_t km_dimm[MAX_DIMMS];2121- /* confidence level that dimm[i] is bad2222- *I think this is the right number2323- */2424-2525-} kf_mem_t;2626-2727-typedef struct kf_cpu_s {2828- confidence_t kc_confidence; /* confidence level that cpu is bad */2929- confidence_t kc_icache; /* confidence level that instr. cache is bad */3030- confidence_t kc_dcache; /* confidence level that data cache is bad */3131- confidence_t kc_scache; /* confidence level that sec. cache is bad */3232- confidence_t kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */3333-} kf_cpu_t;3434-3535-3636-typedef struct kf_pci_bus_s {3737- confidence_t kpb_belief; /* confidence level that the pci bus is bad */3838- confidence_t kpb_pcidev_belief[MAX_PCIDEV];3939- /* confidence level that the pci dev is bad */4040-} kf_pci_bus_t;4141-4242-4343-#endif /* _ASM_IA64_SN_SN_FRU_H */4444-
+46-19
include/asm-ia64/sn/sn_sal.h
···557557ia64_sn_partition_serial_get(void)558558{559559 struct ia64_sal_retval ret_stuff;560560- SAL_CALL(ret_stuff, SN_SAL_PARTITION_SERIAL_GET, 0, 0, 0, 0, 0, 0, 0);560560+ ia64_sal_oemcall_reentrant(&ret_stuff, SN_SAL_PARTITION_SERIAL_GET, 0,561561+ 0, 0, 0, 0, 0, 0);561562 if (ret_stuff.status != 0)562563 return 0;563564 return ret_stuff.v0;···566565567566static inline u64568567sn_partition_serial_number_val(void) {569569- if (sn_partition_serial_number) {570570- return(sn_partition_serial_number);571571- } else {572572- return(sn_partition_serial_number = ia64_sn_partition_serial_get());568568+ if (unlikely(sn_partition_serial_number == 0)) {569569+ sn_partition_serial_number = ia64_sn_partition_serial_get();573570 }571571+ return sn_partition_serial_number;574572}575573576574/*···580580ia64_sn_sysctl_partition_get(nasid_t nasid)581581{582582 struct ia64_sal_retval ret_stuff;583583- SAL_CALL(ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid,584584- 0, 0, 0, 0, 0, 0);583583+ ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid,584584+ 0, 0, 0, 0, 0, 0);585585 if (ret_stuff.status != 0)586586 return INVALID_PARTID;587587 return ((partid_t)ret_stuff.v0);···595595596596static inline partid_t597597sn_local_partid(void) {598598- if (sn_partid < 0) {599599- return (sn_partid = ia64_sn_sysctl_partition_get(cpuid_to_nasid(smp_processor_id())));600600- } else {601601- return sn_partid;598598+ if (unlikely(sn_partid < 0)) {599599+ sn_partid = ia64_sn_sysctl_partition_get(cpuid_to_nasid(smp_processor_id()));602600 }601601+ return sn_partid;602602+}603603+604604+/*605605+ * Returns the physical address of the partition's reserved page through606606+ * an iterative number of calls.607607+ *608608+ * On first call, 'cookie' and 'len' should be set to 0, and 'addr'609609+ * set to the nasid of the partition whose reserved page's address is610610+ * being sought.611611+ * On subsequent calls, pass the values, that were passed back on the612612+ * previous call.613613+ *614614+ * While the return status equals SALRET_MORE_PASSES, keep calling615615+ * this function after first copying 'len' bytes starting at 'addr'616616+ * into 'buf'. Once the return status equals SALRET_OK, 'addr' will617617+ * be the physical address of the partition's reserved page. If the618618+ * return status equals neither of these, an error as occurred.619619+ */620620+static inline s64621621+sn_partition_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len)622622+{623623+ struct ia64_sal_retval rv;624624+ ia64_sal_oemcall_reentrant(&rv, SN_SAL_GET_PARTITION_ADDR, *cookie,625625+ *addr, buf, *len, 0, 0, 0);626626+ *cookie = rv.v0;627627+ *addr = rv.v1;628628+ *len = rv.v2;629629+ return rv.status;603630}604631605632/*···648621sn_register_xp_addr_region(u64 paddr, u64 len, int operation)649622{650623 struct ia64_sal_retval ret_stuff;651651- SAL_CALL(ret_stuff, SN_SAL_XP_ADDR_REGION, paddr, len, (u64)operation,652652- 0, 0, 0, 0);624624+ ia64_sal_oemcall(&ret_stuff, SN_SAL_XP_ADDR_REGION, paddr, len,625625+ (u64)operation, 0, 0, 0, 0);653626 return ret_stuff.status;654627}655628···673646 } else {674647 call = SN_SAL_NO_FAULT_ZONE_PHYSICAL;675648 }676676- SAL_CALL(ret_stuff, call, start_addr, end_addr, return_addr, (u64)1,677677- 0, 0, 0);649649+ ia64_sal_oemcall(&ret_stuff, call, start_addr, end_addr, return_addr,650650+ (u64)1, 0, 0, 0);678651 return ret_stuff.status;679652}680653···695668sn_change_coherence(u64 *new_domain, u64 *old_domain)696669{697670 struct ia64_sal_retval ret_stuff;698698- SAL_CALL(ret_stuff, SN_SAL_COHERENCE, new_domain, old_domain, 0, 0,699699- 0, 0, 0);671671+ ia64_sal_oemcall(&ret_stuff, SN_SAL_COHERENCE, (u64)new_domain,672672+ (u64)old_domain, 0, 0, 0, 0, 0);700673 return ret_stuff.status;701674}702675···715688 cnodeid = nasid_to_cnodeid(get_node_number(paddr));716689 // spin_lock(&NODEPDA(cnodeid)->bist_lock);717690 local_irq_save(irq_flags);718718- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_MEMPROTECT, paddr, len, nasid_array,719719- perms, 0, 0, 0);691691+ ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,692692+ (u64)nasid_array, perms, 0, 0, 0);720693 local_irq_restore(irq_flags);721694 // spin_unlock(&NODEPDA(cnodeid)->bist_lock);722695 return ret_stuff.status;
-47
include/asm-ia64/sn/sndrv.h
···11-/*22- * This file is subject to the terms and conditions of the GNU General Public33- * License. See the file "COPYING" in the main directory of this archive44- * for more details.55- *66- * Copyright (c) 2002-2004 Silicon Graphics, Inc. All Rights Reserved.77- */88-99-#ifndef _ASM_IA64_SN_SNDRV_H1010-#define _ASM_IA64_SN_SNDRV_H1111-1212-/* ioctl commands */1313-#define SNDRV_GET_ROUTERINFO 11414-#define SNDRV_GET_INFOSIZE 21515-#define SNDRV_GET_HUBINFO 31616-#define SNDRV_GET_FLASHLOGSIZE 41717-#define SNDRV_SET_FLASHSYNC 51818-#define SNDRV_GET_FLASHLOGDATA 61919-#define SNDRV_GET_FLASHLOGALL 72020-2121-#define SNDRV_SET_HISTOGRAM_TYPE 142222-2323-#define SNDRV_ELSC_COMMAND 192424-#define SNDRV_CLEAR_LOG 202525-#define SNDRV_INIT_LOG 212626-#define SNDRV_GET_PIMM_PSC 222727-#define SNDRV_SET_PARTITION 232828-#define SNDRV_GET_PARTITION 242929-3030-/* see synergy_perf_ioctl() */3131-#define SNDRV_GET_SYNERGY_VERSION 303232-#define SNDRV_GET_SYNERGY_STATUS 313333-#define SNDRV_GET_SYNERGYINFO 323434-#define SNDRV_SYNERGY_APPEND 333535-#define SNDRV_SYNERGY_ENABLE 343636-#define SNDRV_SYNERGY_FREQ 353737-3838-/* Devices */3939-#define SNDRV_UKNOWN_DEVICE -14040-#define SNDRV_ROUTER_DEVICE 14141-#define SNDRV_HUB_DEVICE 24242-#define SNDRV_ELSC_NVRAM_DEVICE 34343-#define SNDRV_ELSC_CONTROLLER_DEVICE 44444-#define SNDRV_SYSCTL_SUBCH 54545-#define SNDRV_SYNERGY_DEVICE 64646-4747-#endif /* _ASM_IA64_SN_SNDRV_H */
+436
include/asm-ia64/sn/xp.h
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved.77+ */88+99+1010+/*1111+ * External Cross Partition (XP) structures and defines.1212+ */1313+1414+1515+#ifndef _ASM_IA64_SN_XP_H1616+#define _ASM_IA64_SN_XP_H1717+1818+1919+#include <linux/version.h>2020+#include <linux/cache.h>2121+#include <linux/hardirq.h>2222+#include <asm/sn/types.h>2323+#include <asm/sn/bte.h>2424+2525+2626+#ifdef USE_DBUG_ON2727+#define DBUG_ON(condition) BUG_ON(condition)2828+#else2929+#define DBUG_ON(condition)3030+#endif3131+3232+3333+/*3434+ * Define the maximum number of logically defined partitions the system3535+ * can support. It is constrained by the maximum number of hardware3636+ * partitionable regions. The term 'region' in this context refers to the3737+ * minimum number of nodes that can comprise an access protection grouping.3838+ * The access protection is in regards to memory, IPI and IOI.3939+ *4040+ * The maximum number of hardware partitionable regions is equal to the4141+ * maximum number of nodes in the entire system divided by the minimum number4242+ * of nodes that comprise an access protection grouping.4343+ */4444+#define XP_MAX_PARTITIONS 644545+4646+4747+/*4848+ * Define the number of u64s required to represent all the C-brick nasids4949+ * as a bitmap. The cross-partition kernel modules deal only with5050+ * C-brick nasids, thus the need for bitmaps which don't account for5151+ * odd-numbered (non C-brick) nasids.5252+ */5353+#define XP_MAX_PHYSNODE_ID (MAX_PHYSNODE_ID / 2)5454+#define XP_NASID_MASK_BYTES ((XP_MAX_PHYSNODE_ID + 7) / 8)5555+#define XP_NASID_MASK_WORDS ((XP_MAX_PHYSNODE_ID + 63) / 64)5656+5757+5858+/*5959+ * Wrapper for bte_copy() that should it return a failure status will retry6060+ * the bte_copy() once in the hope that the failure was due to a temporary6161+ * aberration (i.e., the link going down temporarily).6262+ *6363+ * See bte_copy for definition of the input parameters.6464+ *6565+ * Note: xp_bte_copy() should never be called while holding a spinlock.6666+ */6767+static inline bte_result_t6868+xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)6969+{7070+ bte_result_t ret;7171+7272+7373+ ret = bte_copy(src, dest, len, mode, notification);7474+7575+ if (ret != BTE_SUCCESS) {7676+ if (!in_interrupt()) {7777+ cond_resched();7878+ }7979+ ret = bte_copy(src, dest, len, mode, notification);8080+ }8181+8282+ return ret;8383+}8484+8585+8686+/*8787+ * XPC establishes channel connections between the local partition and any8888+ * other partition that is currently up. Over these channels, kernel-level8989+ * `users' can communicate with their counterparts on the other partitions.9090+ *9191+ * The maxinum number of channels is limited to eight. For performance reasons,9292+ * the internal cross partition structures require sixteen bytes per channel,9393+ * and eight allows all of this interface-shared info to fit in one cache line.9494+ *9595+ * XPC_NCHANNELS reflects the total number of channels currently defined.9696+ * If the need for additional channels arises, one can simply increase9797+ * XPC_NCHANNELS accordingly. If the day should come where that number9898+ * exceeds the MAXIMUM number of channels allowed (eight), then one will need9999+ * to make changes to the XPC code to allow for this.100100+ */101101+#define XPC_MEM_CHANNEL 0 /* memory channel number */102102+#define XPC_NET_CHANNEL 1 /* network channel number */103103+104104+#define XPC_NCHANNELS 2 /* #of defined channels */105105+#define XPC_MAX_NCHANNELS 8 /* max #of channels allowed */106106+107107+#if XPC_NCHANNELS > XPC_MAX_NCHANNELS108108+#error XPC_NCHANNELS exceeds MAXIMUM allowed.109109+#endif110110+111111+112112+/*113113+ * The format of an XPC message is as follows:114114+ *115115+ * +-------+--------------------------------+116116+ * | flags |////////////////////////////////|117117+ * +-------+--------------------------------+118118+ * | message # |119119+ * +----------------------------------------+120120+ * | payload (user-defined message) |121121+ * | |122122+ * :123123+ * | |124124+ * +----------------------------------------+125125+ *126126+ * The size of the payload is defined by the user via xpc_connect(). A user-127127+ * defined message resides in the payload area.128128+ *129129+ * The user should have no dealings with the message header, but only the130130+ * message's payload. When a message entry is allocated (via xpc_allocate())131131+ * a pointer to the payload area is returned and not the actual beginning of132132+ * the XPC message. The user then constructs a message in the payload area133133+ * and passes that pointer as an argument on xpc_send() or xpc_send_notify().134134+ *135135+ * The size of a message entry (within a message queue) must be a cacheline136136+ * sized multiple in order to facilitate the BTE transfer of messages from one137137+ * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user138138+ * that wants to fit as many msg entries as possible in a given memory size139139+ * (e.g. a memory page).140140+ */141141+struct xpc_msg {142142+ u8 flags; /* FOR XPC INTERNAL USE ONLY */143143+ u8 reserved[7]; /* FOR XPC INTERNAL USE ONLY */144144+ s64 number; /* FOR XPC INTERNAL USE ONLY */145145+146146+ u64 payload; /* user defined portion of message */147147+};148148+149149+150150+#define XPC_MSG_PAYLOAD_OFFSET (u64) (&((struct xpc_msg *)0)->payload)151151+#define XPC_MSG_SIZE(_payload_size) \152152+ L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size))153153+154154+155155+/*156156+ * Define the return values and values passed to user's callout functions.157157+ * (It is important to add new value codes at the end just preceding158158+ * xpcUnknownReason, which must have the highest numerical value.)159159+ */160160+enum xpc_retval {161161+ xpcSuccess = 0,162162+163163+ xpcNotConnected, /* 1: channel is not connected */164164+ xpcConnected, /* 2: channel connected (opened) */165165+ xpcRETIRED1, /* 3: (formerly xpcDisconnected) */166166+167167+ xpcMsgReceived, /* 4: message received */168168+ xpcMsgDelivered, /* 5: message delivered and acknowledged */169169+170170+ xpcRETIRED2, /* 6: (formerly xpcTransferFailed) */171171+172172+ xpcNoWait, /* 7: operation would require wait */173173+ xpcRetry, /* 8: retry operation */174174+ xpcTimeout, /* 9: timeout in xpc_allocate_msg_wait() */175175+ xpcInterrupted, /* 10: interrupted wait */176176+177177+ xpcUnequalMsgSizes, /* 11: message size disparity between sides */178178+ xpcInvalidAddress, /* 12: invalid address */179179+180180+ xpcNoMemory, /* 13: no memory available for XPC structures */181181+ xpcLackOfResources, /* 14: insufficient resources for operation */182182+ xpcUnregistered, /* 15: channel is not registered */183183+ xpcAlreadyRegistered, /* 16: channel is already registered */184184+185185+ xpcPartitionDown, /* 17: remote partition is down */186186+ xpcNotLoaded, /* 18: XPC module is not loaded */187187+ xpcUnloading, /* 19: this side is unloading XPC module */188188+189189+ xpcBadMagic, /* 20: XPC MAGIC string not found */190190+191191+ xpcReactivating, /* 21: remote partition was reactivated */192192+193193+ xpcUnregistering, /* 22: this side is unregistering channel */194194+ xpcOtherUnregistering, /* 23: other side is unregistering channel */195195+196196+ xpcCloneKThread, /* 24: cloning kernel thread */197197+ xpcCloneKThreadFailed, /* 25: cloning kernel thread failed */198198+199199+ xpcNoHeartbeat, /* 26: remote partition has no heartbeat */200200+201201+ xpcPioReadError, /* 27: PIO read error */202202+ xpcPhysAddrRegFailed, /* 28: registration of phys addr range failed */203203+204204+ xpcBteDirectoryError, /* 29: maps to BTEFAIL_DIR */205205+ xpcBtePoisonError, /* 30: maps to BTEFAIL_POISON */206206+ xpcBteWriteError, /* 31: maps to BTEFAIL_WERR */207207+ xpcBteAccessError, /* 32: maps to BTEFAIL_ACCESS */208208+ xpcBtePWriteError, /* 33: maps to BTEFAIL_PWERR */209209+ xpcBtePReadError, /* 34: maps to BTEFAIL_PRERR */210210+ xpcBteTimeOutError, /* 35: maps to BTEFAIL_TOUT */211211+ xpcBteXtalkError, /* 36: maps to BTEFAIL_XTERR */212212+ xpcBteNotAvailable, /* 37: maps to BTEFAIL_NOTAVAIL */213213+ xpcBteUnmappedError, /* 38: unmapped BTEFAIL_ error */214214+215215+ xpcBadVersion, /* 39: bad version number */216216+ xpcVarsNotSet, /* 40: the XPC variables are not set up */217217+ xpcNoRsvdPageAddr, /* 41: unable to get rsvd page's phys addr */218218+ xpcInvalidPartid, /* 42: invalid partition ID */219219+ xpcLocalPartid, /* 43: local partition ID */220220+221221+ xpcUnknownReason /* 44: unknown reason -- must be last in list */222222+};223223+224224+225225+/*226226+ * Define the callout function types used by XPC to update the user on227227+ * connection activity and state changes (via the user function registered by228228+ * xpc_connect()) and to notify them of messages received and delivered (via229229+ * the user function registered by xpc_send_notify()).230230+ *231231+ * The two function types are xpc_channel_func and xpc_notify_func and232232+ * both share the following arguments, with the exception of "data", which233233+ * only xpc_channel_func has.234234+ *235235+ * Arguments:236236+ *237237+ * reason - reason code. (See following table.)238238+ * partid - partition ID associated with condition.239239+ * ch_number - channel # associated with condition.240240+ * data - pointer to optional data. (See following table.)241241+ * key - pointer to optional user-defined value provided as the "key"242242+ * argument to xpc_connect() or xpc_send_notify().243243+ *244244+ * In the following table the "Optional Data" column applies to callouts made245245+ * to functions registered by xpc_connect(). A "NA" in that column indicates246246+ * that this reason code can be passed to functions registered by247247+ * xpc_send_notify() (i.e. they don't have data arguments).248248+ *249249+ * Also, the first three reason codes in the following table indicate250250+ * success, whereas the others indicate failure. When a failure reason code251251+ * is received, one can assume that the channel is not connected.252252+ *253253+ *254254+ * Reason Code | Cause | Optional Data255255+ * =====================+================================+=====================256256+ * xpcConnected | connection has been established| max #of entries257257+ * | to the specified partition on | allowed in message258258+ * | the specified channel | queue259259+ * ---------------------+--------------------------------+---------------------260260+ * xpcMsgReceived | an XPC message arrived from | address of payload261261+ * | the specified partition on the |262262+ * | specified channel | [the user must call263263+ * | | xpc_received() when264264+ * | | finished with the265265+ * | | payload]266266+ * ---------------------+--------------------------------+---------------------267267+ * xpcMsgDelivered | notification that the message | NA268268+ * | was delivered to the intended |269269+ * | recipient and that they have |270270+ * | acknowledged its receipt by |271271+ * | calling xpc_received() |272272+ * =====================+================================+=====================273273+ * xpcUnequalMsgSizes | can't connect to the specified | NULL274274+ * | partition on the specified |275275+ * | channel because of mismatched |276276+ * | message sizes |277277+ * ---------------------+--------------------------------+---------------------278278+ * xpcNoMemory | insufficient memory avaiable | NULL279279+ * | to allocate message queue |280280+ * ---------------------+--------------------------------+---------------------281281+ * xpcLackOfResources | lack of resources to create | NULL282282+ * | the necessary kthreads to |283283+ * | support the channel |284284+ * ---------------------+--------------------------------+---------------------285285+ * xpcUnregistering | this side's user has | NULL or NA286286+ * | unregistered by calling |287287+ * | xpc_disconnect() |288288+ * ---------------------+--------------------------------+---------------------289289+ * xpcOtherUnregistering| the other side's user has | NULL or NA290290+ * | unregistered by calling |291291+ * | xpc_disconnect() |292292+ * ---------------------+--------------------------------+---------------------293293+ * xpcNoHeartbeat | the other side's XPC is no | NULL or NA294294+ * | longer heartbeating |295295+ * | |296296+ * ---------------------+--------------------------------+---------------------297297+ * xpcUnloading | this side's XPC module is | NULL or NA298298+ * | being unloaded |299299+ * | |300300+ * ---------------------+--------------------------------+---------------------301301+ * xpcOtherUnloading | the other side's XPC module is | NULL or NA302302+ * | is being unloaded |303303+ * | |304304+ * ---------------------+--------------------------------+---------------------305305+ * xpcPioReadError | xp_nofault_PIOR() returned an | NULL or NA306306+ * | error while sending an IPI |307307+ * | |308308+ * ---------------------+--------------------------------+---------------------309309+ * xpcInvalidAddress | the address either received or | NULL or NA310310+ * | sent by the specified partition|311311+ * | is invalid |312312+ * ---------------------+--------------------------------+---------------------313313+ * xpcBteNotAvailable | attempt to pull data from the | NULL or NA314314+ * xpcBtePoisonError | specified partition over the |315315+ * xpcBteWriteError | specified channel via a |316316+ * xpcBteAccessError | bte_copy() failed |317317+ * xpcBteTimeOutError | |318318+ * xpcBteXtalkError | |319319+ * xpcBteDirectoryError | |320320+ * xpcBteGenericError | |321321+ * xpcBteUnmappedError | |322322+ * ---------------------+--------------------------------+---------------------323323+ * xpcUnknownReason | the specified channel to the | NULL or NA324324+ * | specified partition was |325325+ * | unavailable for unknown reasons|326326+ * =====================+================================+=====================327327+ */328328+329329+typedef void (*xpc_channel_func)(enum xpc_retval reason, partid_t partid,330330+ int ch_number, void *data, void *key);331331+332332+typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,333333+ int ch_number, void *key);334334+335335+336336+/*337337+ * The following is a registration entry. There is a global array of these,338338+ * one per channel. It is used to record the connection registration made339339+ * by the users of XPC. As long as a registration entry exists, for any340340+ * partition that comes up, XPC will attempt to establish a connection on341341+ * that channel. Notification that a connection has been made will occur via342342+ * the xpc_channel_func function.343343+ *344344+ * The 'func' field points to the function to call when aynchronous345345+ * notification is required for such events as: a connection established/lost,346346+ * or an incomming message received, or an error condition encountered. A347347+ * non-NULL 'func' field indicates that there is an active registration for348348+ * the channel.349349+ */350350+struct xpc_registration {351351+ struct semaphore sema;352352+ xpc_channel_func func; /* function to call */353353+ void *key; /* pointer to user's key */354354+ u16 nentries; /* #of msg entries in local msg queue */355355+ u16 msg_size; /* message queue's message size */356356+ u32 assigned_limit; /* limit on #of assigned kthreads */357357+ u32 idle_limit; /* limit on #of idle kthreads */358358+} ____cacheline_aligned;359359+360360+361361+#define XPC_CHANNEL_REGISTERED(_c) (xpc_registrations[_c].func != NULL)362362+363363+364364+/* the following are valid xpc_allocate() flags */365365+#define XPC_WAIT 0 /* wait flag */366366+#define XPC_NOWAIT 1 /* no wait flag */367367+368368+369369+struct xpc_interface {370370+ void (*connect)(int);371371+ void (*disconnect)(int);372372+ enum xpc_retval (*allocate)(partid_t, int, u32, void **);373373+ enum xpc_retval (*send)(partid_t, int, void *);374374+ enum xpc_retval (*send_notify)(partid_t, int, void *,375375+ xpc_notify_func, void *);376376+ void (*received)(partid_t, int, void *);377377+ enum xpc_retval (*partid_to_nasids)(partid_t, void *);378378+};379379+380380+381381+extern struct xpc_interface xpc_interface;382382+383383+extern void xpc_set_interface(void (*)(int),384384+ void (*)(int),385385+ enum xpc_retval (*)(partid_t, int, u32, void **),386386+ enum xpc_retval (*)(partid_t, int, void *),387387+ enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func,388388+ void *),389389+ void (*)(partid_t, int, void *),390390+ enum xpc_retval (*)(partid_t, void *));391391+extern void xpc_clear_interface(void);392392+393393+394394+extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16,395395+ u16, u32, u32);396396+extern void xpc_disconnect(int);397397+398398+static inline enum xpc_retval399399+xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload)400400+{401401+ return xpc_interface.allocate(partid, ch_number, flags, payload);402402+}403403+404404+static inline enum xpc_retval405405+xpc_send(partid_t partid, int ch_number, void *payload)406406+{407407+ return xpc_interface.send(partid, ch_number, payload);408408+}409409+410410+static inline enum xpc_retval411411+xpc_send_notify(partid_t partid, int ch_number, void *payload,412412+ xpc_notify_func func, void *key)413413+{414414+ return xpc_interface.send_notify(partid, ch_number, payload, func, key);415415+}416416+417417+static inline void418418+xpc_received(partid_t partid, int ch_number, void *payload)419419+{420420+ return xpc_interface.received(partid, ch_number, payload);421421+}422422+423423+static inline enum xpc_retval424424+xpc_partid_to_nasids(partid_t partid, void *nasids)425425+{426426+ return xpc_interface.partid_to_nasids(partid, nasids);427427+}428428+429429+430430+extern u64 xp_nofault_PIOR_target;431431+extern int xp_nofault_PIOR(void *);432432+extern int xp_error_PIOR(void);433433+434434+435435+#endif /* _ASM_IA64_SN_XP_H */436436+
+2
kernel/exit.c
···846846 for (;;) ;847847}848848849849+EXPORT_SYMBOL_GPL(do_exit);850850+849851NORET_TYPE void complete_and_exit(struct completion *comp, long code)850852{851853 if (comp)