Commit 59af7038 authored by Linus Torvalds's avatar Linus Torvalds
parents e7de3690 d50f5c5c
......@@ -167,15 +167,9 @@ static void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
}
}
seen_esc = 0;
if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = 0;
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
if (tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
break;
}
tty_flip_buffer_push(tty);
}
......
......@@ -903,5 +903,6 @@ fsyscall_table:
data8 0
data8 0
data8 0
data8 0 // 1280
.org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
......@@ -60,3 +60,30 @@ END(jprobe_break)
GLOBAL_ENTRY(jprobe_inst_return)
br.call.sptk.many b0=jprobe_break
END(jprobe_inst_return)
GLOBAL_ENTRY(invalidate_stacked_regs)
movl r16=invalidate_restore_cfm
;;
mov b6=r16
;;
br.ret.sptk.many b6
;;
invalidate_restore_cfm:
mov r16=ar.rsc
;;
mov ar.rsc=r0
;;
loadrs
;;
mov ar.rsc=r16
;;
br.cond.sptk.many rp
END(invalidate_stacked_regs)
GLOBAL_ENTRY(flush_register_stack)
// flush dirty regs to backing store (must be first in insn group)
flushrs
;;
br.ret.sptk.many rp
END(flush_register_stack)
......@@ -766,11 +766,56 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
return ret;
}
struct param_bsp_cfm {
unsigned long ip;
unsigned long *bsp;
unsigned long cfm;
};
static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
{
unsigned long ip;
struct param_bsp_cfm *lp = arg;
do {
unw_get_ip(info, &ip);
if (ip == 0)
break;
if (ip == lp->ip) {
unw_get_bsp(info, (unsigned long*)&lp->bsp);
unw_get_cfm(info, (unsigned long*)&lp->cfm);
return;
}
} while (unw_unwind(info) >= 0);
lp->bsp = 0;
lp->cfm = 0;
return;
}
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
struct param_bsp_cfm pa;
int bytes;
/*
* Callee owns the argument space and could overwrite it, eg
* tail call optimization. So to be absolutely safe
* we save the argument space before transfering the control
* to instrumented jprobe function which runs in
* the process context
*/
pa.ip = regs->cr_iip;
unw_init_running(ia64_get_bsp_cfm, &pa);
bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
- (char *)pa.bsp;
memcpy( kcb->jprobes_saved_stacked_regs,
pa.bsp,
bytes );
kcb->bsp = pa.bsp;
kcb->cfm = pa.cfm;
/* save architectural state */
kcb->jprobe_saved_regs = *regs;
......@@ -792,8 +837,20 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
int bytes;
/* restoring architectural state */
*regs = kcb->jprobe_saved_regs;
/* restoring the original argument space */
flush_register_stack();
bytes = (char *)ia64_rse_skip_regs(kcb->bsp, kcb->cfm & 0x3f)
- (char *)kcb->bsp;
memcpy( kcb->bsp,
kcb->jprobes_saved_stacked_regs,
bytes );
invalidate_stacked_regs();
preempt_enable_no_resched();
return 1;
}
......
......@@ -847,7 +847,7 @@ ia64_state_restore:
;;
mov cr.iim=temp3
mov cr.iha=temp4
dep r22=0,r22,62,2 // pal_min_state, physical, uncached
dep r22=0,r22,62,1 // pal_min_state, physical, uncached
mov IA64_KR(CURRENT)=r21
ld8 r8=[temp1] // os_status
ld8 r10=[temp2] // context
......
......@@ -3,7 +3,7 @@
*
* Creates entries in /proc/sal for various system features.
*
* Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved.
* Copyright (c) 2003, 2006 Silicon Graphics, Inc. All rights reserved.
* Copyright (c) 2003 Hewlett-Packard Co
* Bjorn Helgaas <[email protected]>
*
......@@ -27,9 +27,17 @@
* mca.c may not pass a buffer, a NULL buffer just indicates that a new
* record is available in SAL.
* Replace some NR_CPUS by cpus_online, for hotplug cpu.
*
* Jan 5 2006 [email protected]
* Handle hotplug cpus coming online.
* Handle hotplug cpus going offline while they still have outstanding records.
* Use the cpu_* macros consistently.
* Replace the counting semaphore with a mutex and a test if the cpumask is non-empty.
* Modify the locking to make the test for "work to do" an atomic operation.
*/
#include <linux/capability.h>
#include <linux/cpu.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
......@@ -132,8 +140,8 @@ enum salinfo_state {
};
struct salinfo_data {
volatile cpumask_t cpu_event; /* which cpus have outstanding events */
struct semaphore sem; /* count of cpus with outstanding events (bits set in cpu_event) */
cpumask_t cpu_event; /* which cpus have outstanding events */
struct semaphore mutex;
u8 *log_buffer;
u64 log_size;
u8 *oemdata; /* decoded oem data */
......@@ -174,6 +182,21 @@ struct salinfo_platform_oemdata_parms {
int ret;
};
/* Kick the mutex that tells user space that there is work to do. Instead of
* trying to track the state of the mutex across multiple cpus, in user
* context, interrupt context, non-maskable interrupt context and hotplug cpu,
* it is far easier just to grab the mutex if it is free then release it.
*
* This routine must be called with data_saved_lock held, to make the down/up
* operation atomic.
*/
static void
salinfo_work_to_do(struct salinfo_data *data)
{
down_trylock(&data->mutex);
up(&data->mutex);
}
static void
salinfo_platform_oemdata_cpu(void *context)
{
......@@ -212,9 +235,9 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
if (irqsafe)
spin_lock_irqsave(&data_saved_lock, flags);
if (buffer) {
if (irqsafe)
spin_lock_irqsave(&data_saved_lock, flags);
for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
if (!data_saved->buffer)
break;
......@@ -232,13 +255,11 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
data_saved->size = size;
data_saved->buffer = buffer;
}
if (irqsafe)
spin_unlock_irqrestore(&data_saved_lock, flags);
}
if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
if (irqsafe)
up(&data->sem);
cpu_set(smp_processor_id(), data->cpu_event);
if (irqsafe) {
salinfo_work_to_do(data);
spin_unlock_irqrestore(&data_saved_lock, flags);
}
}
......@@ -249,20 +270,17 @@ static struct timer_list salinfo_timer;
static void
salinfo_timeout_check(struct salinfo_data *data)
{
int i;
unsigned long flags;
if (!data->open)
return;
for_each_online_cpu(i) {
if (test_bit(i, &data->cpu_event)) {
/* double up() is not a problem, user space will see no
* records for the additional "events".
*/
up(&data->sem);
}
if (!cpus_empty(data->cpu_event)) {
spin_lock_irqsave(&data_saved_lock, flags);
salinfo_work_to_do(data);
spin_unlock_irqrestore(&data_saved_lock, flags);
}
}
static void
static void
salinfo_timeout (unsigned long arg)
{
salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
......@@ -290,16 +308,20 @@ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t
int i, n, cpu = -1;
retry:
if (down_trylock(&data->sem)) {
if (cpus_empty(data->cpu_event) && down_trylock(&data->mutex)) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (down_interruptible(&data->sem))
if (down_interruptible(&data->mutex))
return -EINTR;
}
n = data->cpu_check;
for (i = 0; i < NR_CPUS; i++) {
if (test_bit(n, &data->cpu_event) && cpu_online(n)) {
if (cpu_isset(n, data->cpu_event)) {
if (!cpu_online(n)) {
cpu_clear(n, data->cpu_event);
continue;
}
cpu = n;
break;
}
......@@ -310,9 +332,6 @@ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t
if (cpu == -1)
goto retry;
/* events are sticky until the user says "clear" */
up(&data->sem);
/* for next read, start checking at next CPU */
data->cpu_check = cpu;
if (++data->cpu_check == NR_CPUS)
......@@ -381,10 +400,8 @@ salinfo_log_release(struct inode *inode, struct file *file)
static void
call_on_cpu(int cpu, void (*fn)(void *), void *arg)
{
cpumask_t save_cpus_allowed, new_cpus_allowed;
memcpy(&save_cpus_allowed, &current->cpus_allowed, sizeof(save_cpus_allowed));
memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed));
set_bit(cpu, &new_cpus_allowed);
cpumask_t save_cpus_allowed = current->cpus_allowed;
cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu);
set_cpus_allowed(current, new_cpus_allowed);
(*fn)(arg);
set_cpus_allowed(current, save_cpus_allowed);
......@@ -433,10 +450,10 @@ salinfo_log_new_read(int cpu, struct salinfo_data *data)
if (!data->saved_num)
call_on_cpu(cpu, salinfo_log_read_cpu, data);
if (!data->log_size) {
data->state = STATE_NO_DATA;
clear_bit(cpu, &data->cpu_event);
data->state = STATE_NO_DATA;
cpu_clear(cpu, data->cpu_event);
} else {
data->state = STATE_LOG_RECORD;
data->state = STATE_LOG_RECORD;
}
}
......@@ -473,27 +490,31 @@ static int
salinfo_log_clear(struct salinfo_data *data, int cpu)
{
sal_log_record_header_t *rh;
unsigned long flags;
spin_lock_irqsave(&data_saved_lock, flags);
data->state = STATE_NO_DATA;
if (!test_bit(cpu, &data->cpu_event))
if (!cpu_isset(cpu, data->cpu_event)) {
spin_unlock_irqrestore(&data_saved_lock, flags);
return 0;
down(&data->sem);
clear_bit(cpu, &data->cpu_event);
}
cpu_clear(cpu, data->cpu_event);
if (data->saved_num) {
unsigned long flags;
spin_lock_irqsave(&data_saved_lock, flags);
shift1_data_saved(data, data->saved_num - 1 );
shift1_data_saved(data, data->saved_num - 1);
data->saved_num = 0;
spin_unlock_irqrestore(&data_saved_lock, flags);
}
spin_unlock_irqrestore(&data_saved_lock, flags);
rh = (sal_log_record_header_t *)(data->log_buffer);
/* Corrected errors have already been cleared from SAL */
if (rh->severity != sal_log_severity_corrected)
call_on_cpu(cpu, salinfo_log_clear_cpu, data);
/* clearing a record may make a new record visible */
salinfo_log_new_read(cpu, data);
if (data->state == STATE_LOG_RECORD &&
!test_and_set_bit(cpu, &data->cpu_event))
up(&data->sem);
if (data->state == STATE_LOG_RECORD) {
spin_lock_irqsave(&data_saved_lock, flags);
cpu_set(cpu, data->cpu_event);
salinfo_work_to_do(data);
spin_unlock_irqrestore(&data_saved_lock, flags);
}
return 0;
}
......@@ -550,6 +571,53 @@ static struct file_operations salinfo_data_fops = {
.write = salinfo_log_write,
};
#ifdef CONFIG_HOTPLUG_CPU
static int __devinit
salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
{
unsigned int i, cpu = (unsigned long)hcpu;
unsigned long flags;
struct salinfo_data *data;
switch (action) {
case CPU_ONLINE:
spin_lock_irqsave(&data_saved_lock, flags);
for (i = 0, data = salinfo_data;
i < ARRAY_SIZE(salinfo_data);
++i, ++data) {
cpu_set(cpu, data->cpu_event);
salinfo_work_to_do(data);
}
spin_unlock_irqrestore(&data_saved_lock, flags);
break;
case CPU_DEAD:
spin_lock_irqsave(&data_saved_lock, flags);
for (i = 0, data = salinfo_data;
i < ARRAY_SIZE(salinfo_data);
++i, ++data) {
struct salinfo_data_saved *data_saved;
int j;
for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j;
j >= 0;
--j, --data_saved) {
if (data_saved->buffer && data_saved->cpu == cpu) {
shift1_data_saved(data, j);
}
}
cpu_clear(cpu, data->cpu_event);
}
spin_unlock_irqrestore(&data_saved_lock, flags);
break;
}
return NOTIFY_OK;
}
static struct notifier_block salinfo_cpu_notifier =
{
.notifier_call = salinfo_cpu_callback,
.priority = 0,
};
#endif /* CONFIG_HOTPLUG_CPU */
static int __init
salinfo_init(void)
{
......@@ -557,7 +625,7 @@ salinfo_init(void)
struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
struct proc_dir_entry *dir, *entry;
struct salinfo_data *data;
int i, j, online;
int i, j;
salinfo_dir = proc_mkdir("sal", NULL);
if (!salinfo_dir)
......@@ -572,7 +640,7 @@ salinfo_init(void)
for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
data = salinfo_data + i;
data->type = i;
sema_init(&data->sem, 0);
init_MUTEX(&data->mutex);
dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
if (!dir)
continue;
......@@ -592,12 +660,8 @@ salinfo_init(void)
*sdir++ = entry;
/* we missed any events before now */
online = 0;
for_each_online_cpu(j) {
set_bit(j, &data->cpu_event);
++online;
}
sema_init(&data->sem, online);
for_each_online_cpu(j)
cpu_set(j, data->cpu_event);
*sdir++ = dir;
}
......@@ -609,6 +673,10 @@ salinfo_init(void)
salinfo_timer.function = &salinfo_timeout;
add_timer(&salinfo_timer);
#ifdef CONFIG_HOTPLUG_CPU
register_cpu_notifier(&salinfo_cpu_notifier);
#endif
return 0;
}
......
......@@ -530,12 +530,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
if (fsys_mode(current, &regs)) {
extern char __kernel_syscall_via_break[];
/*
* Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
* need special handling; Debug trap is not supposed to happen.
* Got a trap in fsys-mode: Taken Branch Trap
* and Single Step trap need special handling;
* Debug trap is ignored (we disable it here
* and re-enable it in the lower-privilege trap).
*/
if (unlikely(vector == 29)) {
die("Got debug trap in fsys-mode---not supposed to happen!",
&regs, 0);
set_thread_flag(TIF_DB_DISABLED);
ia64_psr(&regs)->db = 0;
ia64_psr(&regs)->lp = 1;
return;
}
/* re-do the system call via break 0x100000: */
......@@ -589,10 +592,19 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
case 34:
if (isr & 0x2) {
/* Lower-Privilege Transfer Trap */
/* If we disabled debug traps during an fsyscall,
* re-enable them here.
*/
if (test_thread_flag(TIF_DB_DISABLED)) {
clear_thread_flag(TIF_DB_DISABLED);
ia64_psr(&regs)->db = 1;
}
/*
* Just clear PSR.lp and then return immediately: all the
* interesting work (e.g., signal delivery is done in the kernel
* exit path).
* Just clear PSR.lp and then return immediately:
* all the interesting work (e.g., signal delivery)
* is done in the kernel exit path.
*/
ia64_psr(&regs)->lp = 0;
return;
......
......@@ -90,7 +90,7 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
{
static DEFINE_SPINLOCK(ptcg_lock);
if (mm != current->active_mm) {
if (mm != current->active_mm || !current->mm) {
flush_tlb_all();
return;
}
......
......@@ -26,11 +26,14 @@
#define IIO_NUM_ITTES 7
#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)
struct sn_flush_device_list {
/* This struct is shared between the PROM and the kernel.
* Changes to this struct will require corresponding changes to the kernel.
*/
struct sn_flush_device_common {
int sfdl_bus;
int sfdl_slot;
int sfdl_pin;
struct bar_list {
struct common_bar_list {
unsigned long start;
unsigned long end;
} sfdl_bar_list[6];
......@@ -40,14 +43,19 @@ struct sn_flush_device_list {
uint32_t sfdl_persistent_busnum;
uint32_t sfdl_persistent_segment;
struct pcibus_info *sfdl_pcibus_info;
};
/* This struct is kernel only and is not used by the PROM */
struct sn_flush_device_kernel {
spinlock_t sfdl_flush_lock;
struct sn_flush_device_common *common;
};
/*
* **widget_p - Used as an array[wid_num][device] of sn_flush_device_list.
* **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
*/
struct sn_flush_nasid_entry {
struct sn_flush_device_list **widget_p; /* Used as a array of wid_num */
struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num
uint64_t iio_itte[8];
};
......
......@@ -33,7 +33,7 @@ void bte_error_handler(unsigned long);
* Wait until all BTE related CRBs are completed
* and then reset the interfaces.
*/
void shub1_bte_error_handler(unsigned long _nodepda)
int shub1_bte_error_handler(unsigned long _nodepda)
{
struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
......@@ -53,7 +53,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
(err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
smp_processor_id()));
return;
return 1;
}
/* Determine information about our hub */
......@@ -81,7 +81,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
mod_timer(recovery_timer, HZ * 5);
BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
smp_processor_id()));
return;
return 1;
}
if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
......@@ -99,7 +99,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
err_nodepda, smp_processor_id(),
i));
return;
return 1;
}
}
}
......@@ -124,6 +124,42 @@ void shub1_bte_error_handler(unsigned long _nodepda)
REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
del_timer(recovery_timer);
return 0;
}
/*
* Wait until all BTE related CRBs are completed
* and then reset the interfaces.
*/
int shub2_bte_error_handler(unsigned long _nodepda)
{
struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
struct bteinfo_s *bte;
nasid_t nasid;
u64 status;
int i;
nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
/*
* Verify that all the BTEs are complete
*/
for (i = 0; i < BTES_PER_NODE; i++) {
bte = &err_nodepda->bte_if[i];
status = BTE_LNSTAT_LOAD(bte);
if ((status & IBLS_ERROR) || !(status & IBLS_BUSY))
continue;
mod_timer(recovery_timer, HZ * 5);
BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
smp_processor_id()));
return 1;
}
if (ia64_sn_bte_recovery(nasid))
panic("bte_error_handler(): Fatal BTE Error");
del_timer(recovery_timer);
return 0;
}
/*
......@@ -135,7 +171,6 @@ void bte_error_handler(unsigned long _nodepda)
struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
int i;
nasid_t nasid;
unsigned long irq_flags;
volatile u64 *notify;
bte_result_t bh_error;
......@@ -160,12 +195,15 @@ void bte_error_handler(unsigned long _nodepda)
}
if (is_shub1()) {
shub1_bte_error_handler(_nodepda);
if (shub1_bte_error_handler(_nodepda)) {
spin_unlock_irqrestore(recovery_lock, irq_flags);
return;
}
} else {
nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
if (ia64_sn_bte_recovery(nasid))
panic("bte_error_handler(): Fatal BTE Error");
if (shub2_bte_error_handler(_nodepda)) {
spin_unlock_irqrestore(recovery_lock, irq_flags);
return;
}
}
for (i = 0; i < BTES_PER_NODE; i++) {
......
......@@ -32,13 +32,14 @@ static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep)
ret_stuff.v0 = 0;
hubdev_info = (struct hubdev_info *)arg;
nasid = hubdev_info->hdi_nasid;
SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
if (is_shub1()) {
SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
(u64) nasid, 0, 0, 0, 0, 0, 0);
if ((int)ret_stuff.v0)
panic("hubii_eint_handler(): Fatal TIO Error");
if ((int)ret_stuff.v0)
panic("hubii_eint_handler(): Fatal TIO Error");
if (is_shub1()) {
if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
(void)hubiio_crb_error_handler(hubdev_info);
} else
......
......@@ -76,11 +76,12 @@ static struct sn_pcibus_provider sn_pci_default_provider = {
};
/*
* Retrieve the DMA Flush List given nasid. This list is needed
* to implement the WAR - Flush DMA data on PIO Reads.
* Retrieve the DMA Flush List given nasid, widget, and device.
* This list is needed to implement the WAR - Flush DMA data on PIO Reads.
*/
static inline uint64_t
sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address)
static inline u64
sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
u64 address)
{
struct ia64_sal_retval ret_stuff;
......@@ -88,17 +89,17 @@ sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address)
ret_stuff.v0 = 0;
SAL_CALL_NOLOCK(ret_stuff,
(u64) SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
(u64) nasid, (u64) widget_num, (u64) address, 0, 0, 0,
0);
return ret_stuff.v0;
(u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
(u64) nasid, (u64) widget_num,
(u64) device_num, (u64) address, 0, 0, 0);
return ret_stuff.status;
}
/*
* Retrieve the hub device info structure for the given nasid.
*/
static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address)
static inline u64 sal_get_hubdev_info(u64 handle, u64 address)
{
struct ia6