From 821376bf15e692941f9235f13a14987009fd0b10 Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Thu, 21 Apr 2005 11:07:59 -0700 Subject: [IA64] fix fls() The ia64-version of fls() never worked as intended (the bitnumbering was off by 1 and fls(0) was undefined). This patch fixes the problem by using a popcnt-based fls(), which on McKinley-derived cores is slightly faster than both ia64_fls() and generic_fls(). The resulting code, however, is bigger (7-8 bundles instead of about 3 bundles). Also switch ia64_popcnt() to __builtin_popcountl() for GCC v3.4 or newer since the compiler can predicate that and schedule it better. Thanks to Simon Derr and Matt Mackall for tracking down this bug. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- include/asm-ia64/bitops.h | 21 +++++++++++++++++---- include/asm-ia64/gcc_intrin.h | 10 +++++++--- 2 files changed, 24 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h index 925d54cee475..7232528e2d0c 100644 --- a/include/asm-ia64/bitops.h +++ b/include/asm-ia64/bitops.h @@ -314,8 +314,8 @@ __ffs (unsigned long x) #ifdef __KERNEL__ /* - * find_last_zero_bit - find the last zero bit in a 64 bit quantity - * @x: The value to search + * Return bit number of last (most-significant) bit set. Undefined + * for x==0. Bits are numbered from 0..63 (e.g., ia64_fls(9) == 3). */ static inline unsigned long ia64_fls (unsigned long x) @@ -327,10 +327,23 @@ ia64_fls (unsigned long x) return exp - 0xffff; } +/* + * Find the last (most significant) bit set. Returns 0 for x==0 and + * bits are numbered from 1..32 (e.g., fls(9) == 4). + */ static inline int -fls (int x) +fls (int t) { - return ia64_fls((unsigned int) x); + unsigned long x = t & 0xffffffffu; + + if (!x) + return 0; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return ia64_popcnt(x); } /* diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h index 7c357dfbae50..4fb4e439b05c 100644 --- a/include/asm-ia64/gcc_intrin.h +++ b/include/asm-ia64/gcc_intrin.h @@ -133,13 +133,17 @@ register unsigned long ia64_r13 asm ("r13") __attribute_used__; ia64_intri_res; \ }) -#define ia64_popcnt(x) \ -({ \ +#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# define ia64_popcnt(x) __builtin_popcountl(x) +#else +# define ia64_popcnt(x) \ + ({ \ __u64 ia64_intri_res; \ asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \ \ ia64_intri_res; \ -}) + }) +#endif #define ia64_getf_exp(x) \ ({ \ -- cgit v1.2.3 From 29c4be51e3fd52205d848248d38924941f22ca0e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 21 Apr 2005 16:46:56 -0700 Subject: [AX25]: make ax25_queue_xmit a net_device parameter I.e. not using skb->dev as a way to pass the parameter used to fill... skb->dev :-) Also to get the _type_trans open coded sequence grouped, next changesets will introduce ax25_type_trans. Signed-off-by: Ralf Baechle Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/net/ax25.h | 2 +- net/ax25/af_ax25.c | 4 +--- net/ax25/ax25_ip.c | 4 +--- net/ax25/ax25_out.c | 8 +++----- net/ax25/ax25_subr.c | 4 +--- 5 files changed, 7 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/net/ax25.h b/include/net/ax25.h index fb95ecb6fe03..875edbba396d 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h @@ -305,7 +305,7 @@ extern ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_addr extern void ax25_output(ax25_cb *, int, struct sk_buff *); extern void ax25_kick(ax25_cb *); extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int); -extern void ax25_queue_xmit(struct sk_buff *); +extern void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev); extern int ax25_check_iframes_acked(ax25_cb *, unsigned short); /* ax25_route.c */ diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 33b1a3763027..707097deac3d 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1587,9 +1587,7 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, *asmptr = AX25_UI; /* Datagram frames go straight out of the door as UI */ - skb->dev = ax25->ax25_dev->dev; - - ax25_queue_xmit(skb); + ax25_queue_xmit(skb, ax25->ax25_dev->dev); err = len; diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index 04d711344d55..bba0173e2d65 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c @@ -199,9 +199,7 @@ int ax25_rebuild_header(struct sk_buff *skb) skb = ourskb; } - skb->dev = dev; - - ax25_queue_xmit(skb); + ax25_queue_xmit(skb, dev); put: ax25_put_route(route); diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 3475a3ac9343..94557b1a1fa2 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -340,21 +340,19 @@ void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type) ax25_addr_build(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus); - skb->dev = ax25->ax25_dev->dev; - - ax25_queue_xmit(skb); + ax25_queue_xmit(skb, ax25->ax25_dev->dev); } /* * A small shim to dev_queue_xmit to add the KISS control byte, and do * any packet forwarding in operation. */ -void ax25_queue_xmit(struct sk_buff *skb) +void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned char *ptr; skb->protocol = htons(ETH_P_AX25); - skb->dev = ax25_fwd_dev(skb->dev); + skb->dev = ax25_fwd_dev(dev); ptr = skb_push(skb, 1); *ptr = 0x00; /* KISS */ diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 8cf72707af8b..99694b57f6f5 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c @@ -220,9 +220,7 @@ void ax25_return_dm(struct net_device *dev, ax25_address *src, ax25_address *des dptr = skb_push(skb, ax25_addr_size(digi)); dptr += ax25_addr_build(dptr, dest, src, &retdigi, AX25_RESPONSE, AX25_MODULUS); - skb->dev = dev; - - ax25_queue_xmit(skb); + ax25_queue_xmit(skb, dev); } /* -- cgit v1.2.3 From 6e9017a7d9b949aea638eeba67d34affaa145f14 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 21 Apr 2005 16:58:56 -0700 Subject: [TG3]: add bcm5752 entry to pci_ids.h Add proper entry for bcm5752 PCI ID to pci_ids.h, and use it in tg3. I did this separately in case patches like this (i.e. new PCI IDs) need to come from more "official" sources. Signed-off-by: John W. Linville Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- include/linux/pci_ids.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b72e95e8fac5..4375eec06d37 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -206,7 +206,7 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, - { PCI_VENDOR_ID_BROADCOM, 0x1600, /* TIGON3_5752 */ + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f1f75fde8cd4..6a1897481942 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2062,6 +2062,7 @@ #define PCI_DEVICE_ID_AFAVLAB_P030 0x2182 #define PCI_VENDOR_ID_BROADCOM 0x14e4 +#define PCI_DEVICE_ID_TIGON3_5752 0x1600 #define PCI_DEVICE_ID_TIGON3_5700 0x1644 #define PCI_DEVICE_ID_TIGON3_5701 0x1645 #define PCI_DEVICE_ID_TIGON3_5702 0x1646 -- cgit v1.2.3 From d7be828e03969ea7f922f299acb8daa0d8ce7006 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 21 Apr 2005 21:41:33 -0700 Subject: [SPARC64]: Provide a pgprot_noncached() implementation. Signed-off-by: David S. Miller --- include/asm-sparc64/pgtable.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index af9bf175a223..ae2cd5b09a7c 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -416,6 +416,11 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot); +/* Clear virtual and physical cachability, set side-effect bit. */ +#define pgprot_noncached(prot) \ + (__pgprot((pgprot_val(prot) & ~(_PAGE_CP | _PAGE_CV)) | \ + _PAGE_E)) + /* * For sparc32&64, the pfn in io_remap_pfn_range() carries in * its high 4 bits. These macros/functions put it there or get it from there. -- cgit v1.2.3 From b4bca26c0160f48b4eb04f21d31a229832732013 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 21 Apr 2005 21:42:34 -0700 Subject: [SPARC]: Provide generic ioctls in Sparc RTC driver. Provide support for drivers/char/rtc.c ioctls in the Mostek rtc driver as well as the Sparc specific RTCGET and RTCSET. This allows userspace to be much less messy. Currently util-linux and other spots jump through hoops trying various ioctl variants until it hits the right one whatever driver actually being used supports. Eventually all of this should move over to the genrtc.c driver, but not today... While we are here, fix up the register types for sparse. Thanks to Frans Pop for helping point out this issue. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 37 +++++++++------- drivers/sbus/char/rtc.c | 103 +++++++++++++++++++++++++++++++++++++++++-- include/asm-sparc64/mostek.h | 6 +-- 3 files changed, 123 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 6a717d4d2bc5..c60785c046be 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -48,7 +48,7 @@ DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); -unsigned long mstk48t02_regs = 0UL; +void * __iomem mstk48t02_regs = 0UL; #ifdef CONFIG_PCI unsigned long ds1287_regs = 0UL; #endif @@ -59,8 +59,8 @@ u64 jiffies_64 = INITIAL_JIFFIES; EXPORT_SYMBOL(jiffies_64); -static unsigned long mstk48t08_regs = 0UL; -static unsigned long mstk48t59_regs = 0UL; +static void * __iomem mstk48t08_regs; +static void * __iomem mstk48t59_regs; static int set_rtc_mmss(unsigned long); @@ -520,7 +520,7 @@ void timer_tick_interrupt(struct pt_regs *regs) /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ static void __init kick_start_clock(void) { - unsigned long regs = mstk48t02_regs; + void * __iomem regs = mstk48t02_regs; u8 sec, tmp; int i, count; @@ -604,7 +604,7 @@ static void __init kick_start_clock(void) /* Return nonzero if the clock chip battery is low. */ static int __init has_low_battery(void) { - unsigned long regs = mstk48t02_regs; + void * __iomem regs = mstk48t02_regs; u8 data1, data2; spin_lock_irq(&mostek_lock); @@ -623,7 +623,7 @@ static int __init has_low_battery(void) static void __init set_system_time(void) { unsigned int year, mon, day, hour, min, sec; - unsigned long mregs = mstk48t02_regs; + void * __iomem mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; #else @@ -843,7 +843,8 @@ void __init clock_probe(void) !strcmp(model, "m5823")) { ds1287_regs = edev->resource[0].start; } else { - mstk48t59_regs = edev->resource[0].start; + mstk48t59_regs = (void * __iomem) + edev->resource[0].start; mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } break; @@ -865,7 +866,8 @@ try_isa_clock: !strcmp(model, "m5823")) { ds1287_regs = isadev->resource.start; } else { - mstk48t59_regs = isadev->resource.start; + mstk48t59_regs = (void * __iomem) + isadev->resource.start; mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } break; @@ -893,21 +895,24 @@ try_isa_clock: } if(model[5] == '0' && model[6] == '2') { - mstk48t02_regs = (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); + mstk48t02_regs = (void * __iomem) + (((u64)clk_reg[0].phys_addr) | + (((u64)clk_reg[0].which_io)<<32UL)); } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); + mstk48t08_regs = (void * __iomem) + (((u64)clk_reg[0].phys_addr) | + (((u64)clk_reg[0].which_io)<<32UL)); mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; } else { - mstk48t59_regs = (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); + mstk48t59_regs = (void * __iomem) + (((u64)clk_reg[0].phys_addr) | + (((u64)clk_reg[0].which_io)<<32UL)); mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } break; } - if (mstk48t02_regs != 0UL) { + if (mstk48t02_regs != NULL) { /* Report a low battery voltage condition. */ if (has_low_battery()) prom_printf("NVRAM: Low battery voltage!\n"); @@ -1087,7 +1092,7 @@ unsigned long long sched_clock(void) static int set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, chip_minutes; - unsigned long mregs = mstk48t02_regs; + void * __iomem mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; #else diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c index bf3273eb1c8b..49d1cd99d5ac 100644 --- a/drivers/sbus/char/rtc.c +++ b/drivers/sbus/char/rtc.c @@ -28,6 +28,42 @@ static int rtc_busy = 0; +/* This is the structure layout used by drivers/char/rtc.c, we + * support that driver's ioctls so that things are less messy in + * userspace. + */ +struct rtc_time_generic { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; +#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */ +#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */ +#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ +#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */ +#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */ +#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */ +#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */ +#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */ +#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time */ +#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time */ +#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */ +#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */ +#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */ +#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */ +#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ +#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ +#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ +#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ +#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ +#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ + /* Retrieve the current date and time from the real time clock. */ static void get_rtc_time(struct rtc_time *t) { @@ -82,29 +118,87 @@ void set_rtc_time(struct rtc_time *t) spin_unlock_irq(&mostek_lock); } +static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm) +{ + struct rtc_time_generic __user *utm = argp; + + if (__put_user(tm->sec, &utm->tm_sec) || + __put_user(tm->min, &utm->tm_min) || + __put_user(tm->hour, &utm->tm_hour) || + __put_user(tm->dom, &utm->tm_mday) || + __put_user(tm->month, &utm->tm_mon) || + __put_user(tm->year, &utm->tm_year) || + __put_user(tm->dow, &utm->tm_wday) || + __put_user(0, &utm->tm_yday) || + __put_user(0, &utm->tm_isdst)) + return -EFAULT; + + return 0; +} + +static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp) +{ + struct rtc_time_generic __user *utm = argp; + + if (__get_user(tm->sec, &utm->tm_sec) || + __get_user(tm->min, &utm->tm_min) || + __get_user(tm->hour, &utm->tm_hour) || + __get_user(tm->dom, &utm->tm_mday) || + __get_user(tm->month, &utm->tm_mon) || + __get_user(tm->year, &utm->tm_year) || + __get_user(tm->dow, &utm->tm_wday)) + return -EFAULT; + + return 0; +} + static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct rtc_time rtc_tm; void __user *argp = (void __user *)arg; - switch (cmd) - { + switch (cmd) { + /* No interrupt support, return an error + * compatible with drivers/char/rtc.c + */ + case RTC_AIE_OFF: + case RTC_AIE_ON: + case RTC_PIE_OFF: + case RTC_PIE_ON: + case RTC_UIE_OFF: + case RTC_UIE_ON: + case RTC_IRQP_READ: + case RTC_IRQP_SET: + case RTC_EPOCH_SET: + case RTC_EPOCH_READ: + return -EINVAL; + case RTCGET: + case RTC_RD_TIME: memset(&rtc_tm, 0, sizeof(struct rtc_time)); get_rtc_time(&rtc_tm); - if (copy_to_user(argp, &rtc_tm, sizeof(struct rtc_time))) + if (cmd == RTCGET) { + if (copy_to_user(argp, &rtc_tm, + sizeof(struct rtc_time))) + return -EFAULT; + } else if (put_rtc_time_generic(argp, &rtc_tm)) return -EFAULT; return 0; case RTCSET: + case RTC_SET_TIME: if (!capable(CAP_SYS_TIME)) return -EPERM; - if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) + if (cmd == RTCSET) { + if (copy_from_user(&rtc_tm, argp, + sizeof(struct rtc_time))) + return -EFAULT; + } else if (get_rtc_time_generic(&rtc_tm, argp)) return -EFAULT; set_rtc_time(&rtc_tm); @@ -164,6 +258,7 @@ static int __init rtc_sun_init(void) printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n"); return error; } + printk("rtc_sun_init: Registered Mostek RTC driver.\n"); return 0; } diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h index ccf2f5f82d7f..1f9b1356a48e 100644 --- a/include/asm-sparc64/mostek.h +++ b/include/asm-sparc64/mostek.h @@ -38,7 +38,7 @@ * * We now deal with physical addresses for I/O to the chip. -DaveM */ -static __inline__ u8 mostek_read(unsigned long addr) +static __inline__ u8 mostek_read(void * __iomem addr) { u8 ret; @@ -48,7 +48,7 @@ static __inline__ u8 mostek_read(unsigned long addr) return ret; } -static __inline__ void mostek_write(unsigned long addr, u8 val) +static __inline__ void mostek_write(void * __iomem addr, u8 val) { __asm__ __volatile__("stba %0, [%1] %2" : /* no outputs */ @@ -67,7 +67,7 @@ static __inline__ void mostek_write(unsigned long addr, u8 val) #define MOSTEK_YEAR 0x07ffUL extern spinlock_t mostek_lock; -extern unsigned long mstk48t02_regs; +extern void *__iomem mstk48t02_regs; /* Control register values. */ #define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ -- cgit v1.2.3 From b8d8b883e6f029e99c35c88f853501740e322131 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Fri, 22 Apr 2005 14:44:40 -0700 Subject: [IA64] cpu hotplug: return offlined cpus to SAL This patch is required to support cpu removal for IPF systems. Existing code just fakes the real offline by keeping it run the idle thread, and polling for the bit to re-appear in the cpu_state to get out of the idle loop. For the cpu-offline to work correctly, we need to pass control of this CPU back to SAL so it can continue in the boot-rendez mode. This gives the SAL control to not pick this cpu as the monarch processor for global MCA events, and addition does not wait for this cpu to checkin with SAL for global MCA events as well. The handoff is implemented as documented in SAL specification section 3.2.5.1 "OS_BOOT_RENDEZ to SAL return State" Signed-off-by: Ashok Raj Signed-off-by: Tony Luck --- arch/ia64/kernel/head.S | 280 ++++++++++++++++++++++++++++++++++++++++----- arch/ia64/kernel/mca_asm.S | 88 ++++++++------ arch/ia64/kernel/process.c | 22 ++-- arch/ia64/kernel/smpboot.c | 81 ++++++++----- include/asm-ia64/sal.h | 38 ++++++ 5 files changed, 399 insertions(+), 110 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 105c7fec8c6d..0d535d65eea6 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -15,6 +15,8 @@ * Copyright (C) 1999 Don Dugger * Copyright (C) 2002 Fenghua Yu * -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2. + * Copyright (C) 2004 Ashok Raj + * Support for CPU Hotplug */ #include @@ -29,6 +31,134 @@ #include #include #include +#include + +#ifdef CONFIG_HOTPLUG_CPU +#define SAL_PSR_BITS_TO_SET \ + (IA64_PSR_AC | IA64_PSR_BN | IA64_PSR_MFH | IA64_PSR_MFL) + +#define SAVE_FROM_REG(src, ptr, dest) \ + mov dest=src;; \ + st8 [ptr]=dest,0x08 + +#define RESTORE_REG(reg, ptr, _tmp) \ + ld8 _tmp=[ptr],0x08;; \ + mov reg=_tmp + +#define SAVE_BREAK_REGS(ptr, _idx, _breg, _dest)\ + mov ar.lc=IA64_NUM_DBG_REGS-1;; \ + mov _idx=0;; \ +1: \ + SAVE_FROM_REG(_breg[_idx], ptr, _dest);; \ + add _idx=1,_idx;; \ + br.cloop.sptk.many 1b + +#define RESTORE_BREAK_REGS(ptr, _idx, _breg, _tmp, _lbl)\ + mov ar.lc=IA64_NUM_DBG_REGS-1;; \ + mov _idx=0;; \ +_lbl: RESTORE_REG(_breg[_idx], ptr, _tmp);; \ + add _idx=1, _idx;; \ + br.cloop.sptk.many _lbl + +#define SAVE_ONE_RR(num, _reg, _tmp) \ + movl _tmp=(num<<61);; \ + mov _reg=rr[_tmp] + +#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \ + SAVE_ONE_RR(0,_r0, _tmp);; \ + SAVE_ONE_RR(1,_r1, _tmp);; \ + SAVE_ONE_RR(2,_r2, _tmp);; \ + SAVE_ONE_RR(3,_r3, _tmp);; \ + SAVE_ONE_RR(4,_r4, _tmp);; \ + SAVE_ONE_RR(5,_r5, _tmp);; \ + SAVE_ONE_RR(6,_r6, _tmp);; \ + SAVE_ONE_RR(7,_r7, _tmp);; + +#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \ + st8 [ptr]=_r0, 8;; \ + st8 [ptr]=_r1, 8;; \ + st8 [ptr]=_r2, 8;; \ + st8 [ptr]=_r3, 8;; \ + st8 [ptr]=_r4, 8;; \ + st8 [ptr]=_r5, 8;; \ + st8 [ptr]=_r6, 8;; \ + st8 [ptr]=_r7, 8;; + +#define RESTORE_REGION_REGS(ptr, _idx1, _idx2, _tmp) \ + mov ar.lc=0x08-1;; \ + movl _idx1=0x00;; \ +RestRR: \ + dep.z _idx2=_idx1,61,3;; \ + ld8 _tmp=[ptr],8;; \ + mov rr[_idx2]=_tmp;; \ + srlz.d;; \ + add _idx1=1,_idx1;; \ + br.cloop.sptk.few RestRR + +/* + * Adjust region registers saved before starting to save + * break regs and rest of the states that need to be preserved. + */ +#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(_reg1,_reg2,_pred) \ + SAVE_FROM_REG(b0,_reg1,_reg2);; \ + SAVE_FROM_REG(b1,_reg1,_reg2);; \ + SAVE_FROM_REG(b2,_reg1,_reg2);; \ + SAVE_FROM_REG(b3,_reg1,_reg2);; \ + SAVE_FROM_REG(b4,_reg1,_reg2);; \ + SAVE_FROM_REG(b5,_reg1,_reg2);; \ + st8 [_reg1]=r1,0x08;; \ + st8 [_reg1]=r12,0x08;; \ + st8 [_reg1]=r13,0x08;; \ + SAVE_FROM_REG(ar.fpsr,_reg1,_reg2);; \ + SAVE_FROM_REG(ar.pfs,_reg1,_reg2);; \ + SAVE_FROM_REG(ar.rnat,_reg1,_reg2);; \ + SAVE_FROM_REG(ar.unat,_reg1,_reg2);; \ + SAVE_FROM_REG(ar.bspstore,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.dcr,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.iva,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.pta,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.itv,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.pmv,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.cmcv,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.lrr0,_reg1,_reg2);; \ + SAVE_FROM_REG(cr.lrr1,_reg1,_reg2);; \ + st8 [_reg1]=r4,0x08;; \ + st8 [_reg1]=r5,0x08;; \ + st8 [_reg1]=r6,0x08;; \ + st8 [_reg1]=r7,0x08;; \ + st8 [_reg1]=_pred,0x08;; \ + SAVE_FROM_REG(ar.lc, _reg1, _reg2);; \ + stf.spill.nta [_reg1]=f2,16;; \ + stf.spill.nta [_reg1]=f3,16;; \ + stf.spill.nta [_reg1]=f4,16;; \ + stf.spill.nta [_reg1]=f5,16;; \ + stf.spill.nta [_reg1]=f16,16;; \ + stf.spill.nta [_reg1]=f17,16;; \ + stf.spill.nta [_reg1]=f18,16;; \ + stf.spill.nta [_reg1]=f19,16;; \ + stf.spill.nta [_reg1]=f20,16;; \ + stf.spill.nta [_reg1]=f21,16;; \ + stf.spill.nta [_reg1]=f22,16;; \ + stf.spill.nta [_reg1]=f23,16;; \ + stf.spill.nta [_reg1]=f24,16;; \ + stf.spill.nta [_reg1]=f25,16;; \ + stf.spill.nta [_reg1]=f26,16;; \ + stf.spill.nta [_reg1]=f27,16;; \ + stf.spill.nta [_reg1]=f28,16;; \ + stf.spill.nta [_reg1]=f29,16;; \ + stf.spill.nta [_reg1]=f30,16;; \ + stf.spill.nta [_reg1]=f31,16;; + +#else +#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(a1,a2) +#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) +#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) +#endif + +#define SET_ONE_RR(num, pgsize, _tmp1, _tmp2, vhpt) \ + movl _tmp1=(num << 61);; \ + mov _tmp2=((ia64_rid(IA64_REGION_ID_KERNEL, (num<<61)) << 8) | (pgsize << 2) | vhpt);; \ + mov rr[_tmp1]=_tmp2 .section __special_page_section,"ax" @@ -63,6 +193,12 @@ start_ap: ;; srlz.i ;; + /* + * Save the region registers, predicate before they get clobbered + */ + SAVE_REGION_REGS(r2, r8,r9,r10,r11,r12,r13,r14,r15); + mov r25=pr;; + /* * Initialize kernel region registers: * rr[0]: VHPT enabled, page size = PAGE_SHIFT @@ -76,32 +212,14 @@ start_ap: * We initialize all of them to prevent inadvertently assuming * something about the state of address translation early in boot. */ - mov r6=((ia64_rid(IA64_REGION_ID_KERNEL, (0<<61)) << 8) | (PAGE_SHIFT << 2) | 1) - movl r7=(0<<61) - mov r8=((ia64_rid(IA64_REGION_ID_KERNEL, (1<<61)) << 8) | (PAGE_SHIFT << 2) | 1) - movl r9=(1<<61) - mov r10=((ia64_rid(IA64_REGION_ID_KERNEL, (2<<61)) << 8) | (PAGE_SHIFT << 2) | 1) - movl r11=(2<<61) - mov r12=((ia64_rid(IA64_REGION_ID_KERNEL, (3<<61)) << 8) | (PAGE_SHIFT << 2) | 1) - movl r13=(3<<61) - mov r14=((ia64_rid(IA64_REGION_ID_KERNEL, (4<<61)) << 8) | (PAGE_SHIFT << 2) | 1) - movl r15=(4<<61) - mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, (5<<61)) << 8) | (PAGE_SHIFT << 2) | 1) - movl r17=(5<<61) - mov r18=((ia64_rid(IA64_REGION_ID_KERNEL, (6<<61)) << 8) | (IA64_GRANULE_SHIFT << 2)) - movl r19=(6<<61) - mov r20=((ia64_rid(IA64_REGION_ID_KERNEL, (7<<61)) << 8) | (IA64_GRANULE_SHIFT << 2)) - movl r21=(7<<61) - ;; - mov rr[r7]=r6 - mov rr[r9]=r8 - mov rr[r11]=r10 - mov rr[r13]=r12 - mov rr[r15]=r14 - mov rr[r17]=r16 - mov rr[r19]=r18 - mov rr[r21]=r20 - ;; + SET_ONE_RR(0, PAGE_SHIFT, r2, r16, 1);; + SET_ONE_RR(1, PAGE_SHIFT, r2, r16, 1);; + SET_ONE_RR(2, PAGE_SHIFT, r2, r16, 1);; + SET_ONE_RR(3, PAGE_SHIFT, r2, r16, 1);; + SET_ONE_RR(4, PAGE_SHIFT, r2, r16, 1);; + SET_ONE_RR(5, PAGE_SHIFT, r2, r16, 1);; + SET_ONE_RR(6, IA64_GRANULE_SHIFT, r2, r16, 0);; + SET_ONE_RR(7, IA64_GRANULE_SHIFT, r2, r16, 0);; /* * Now pin mappings into the TLB for kernel text and data */ @@ -142,6 +260,13 @@ start_ap: ;; 1: // now we are in virtual mode + movl r2=sal_state_for_booting_cpu;; + ld8 r16=[r2];; + + STORE_REGION_REGS(r16, r8,r9,r10,r11,r12,r13,r14,r15); + SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(r16,r17,r25) + ;; + // set IVT entry point---can't access I/O ports without it movl r3=ia64_ivt ;; @@ -211,12 +336,13 @@ start_ap: mov IA64_KR(CURRENT_STACK)=r16 mov r13=r2 /* - * Reserve space at the top of the stack for "struct pt_regs". Kernel threads - * don't store interesting values in that structure, but the space still needs - * to be there because time-critical stuff such as the context switching can - * be implemented more efficiently (for example, __switch_to() + * Reserve space at the top of the stack for "struct pt_regs". Kernel + * threads don't store interesting values in that structure, but the space + * still needs to be there because time-critical stuff such as the context + * switching can be implemented more efficiently (for example, __switch_to() * always sets the psr.dfh bit of the task it is switching to). */ + addl r12=IA64_STK_OFFSET-IA64_PT_REGS_SIZE-16,r2 addl r2=IA64_RBS_OFFSET,r2 // initialize the RSE mov ar.rsc=0 // place RSE in enforced lazy mode @@ -993,4 +1119,98 @@ END(ia64_spinlock_contention) #endif +#ifdef CONFIG_HOTPLUG_CPU +GLOBAL_ENTRY(ia64_jump_to_sal) + alloc r16=ar.pfs,1,0,0,0;; + rsm psr.i | psr.ic +{ + flushrs + srlz.i +} + tpa r25=in0 + movl r18=tlb_purge_done;; + DATA_VA_TO_PA(r18);; + mov b1=r18 // Return location + movl r18=ia64_do_tlb_purge;; + DATA_VA_TO_PA(r18);; + mov b2=r18 // doing tlb_flush work + mov ar.rsc=0 // Put RSE in enforced lazy, LE mode + movl r17=1f;; + DATA_VA_TO_PA(r17);; + mov cr.iip=r17 + movl r16=SAL_PSR_BITS_TO_SET;; + mov cr.ipsr=r16 + mov cr.ifs=r0;; + rfi;; +1: + /* + * Invalidate all TLB data/inst + */ + br.sptk.many b2;; // jump to tlb purge code + +tlb_purge_done: + RESTORE_REGION_REGS(r25, r17,r18,r19);; + RESTORE_REG(b0, r25, r17);; + RESTORE_REG(b1, r25, r17);; + RESTORE_REG(b2, r25, r17);; + RESTORE_REG(b3, r25, r17);; + RESTORE_REG(b4, r25, r17);; + RESTORE_REG(b5, r25, r17);; + ld8 r1=[r25],0x08;; + ld8 r12=[r25],0x08;; + ld8 r13=[r25],0x08;; + RESTORE_REG(ar.fpsr, r25, r17);; + RESTORE_REG(ar.pfs, r25, r17);; + RESTORE_REG(ar.rnat, r25, r17);; + RESTORE_REG(ar.unat, r25, r17);; + RESTORE_REG(ar.bspstore, r25, r17);; + RESTORE_REG(cr.dcr, r25, r17);; + RESTORE_REG(cr.iva, r25, r17);; + RESTORE_REG(cr.pta, r25, r17);; + RESTORE_REG(cr.itv, r25, r17);; + RESTORE_REG(cr.pmv, r25, r17);; + RESTORE_REG(cr.cmcv, r25, r17);; + RESTORE_REG(cr.lrr0, r25, r17);; + RESTORE_REG(cr.lrr1, r25, r17);; + ld8 r4=[r25],0x08;; + ld8 r5=[r25],0x08;; + ld8 r6=[r25],0x08;; + ld8 r7=[r25],0x08;; + ld8 r17=[r25],0x08;; + mov pr=r17,-1;; + RESTORE_REG(ar.lc, r25, r17);; + /* + * Now Restore floating point regs + */ + ldf.fill.nta f2=[r25],16;; + ldf.fill.nta f3=[r25],16;; + ldf.fill.nta f4=[r25],16;; + ldf.fill.nta f5=[r25],16;; + ldf.fill.nta f16=[r25],16;; + ldf.fill.nta f17=[r25],16;; + ldf.fill.nta f18=[r25],16;; + ldf.fill.nta f19=[r25],16;; + ldf.fill.nta f20=[r25],16;; + ldf.fill.nta f21=[r25],16;; + ldf.fill.nta f22=[r25],16;; + ldf.fill.nta f23=[r25],16;; + ldf.fill.nta f24=[r25],16;; + ldf.fill.nta f25=[r25],16;; + ldf.fill.nta f26=[r25],16;; + ldf.fill.nta f27=[r25],16;; + ldf.fill.nta f28=[r25],16;; + ldf.fill.nta f29=[r25],16;; + ldf.fill.nta f30=[r25],16;; + ldf.fill.nta f31=[r25],16;; + + /* + * Now that we have done all the register restores + * we are now ready for the big DIVE to SAL Land + */ + ssm psr.ic;; + srlz.d;; + br.ret.sptk.many b0;; +END(ia64_jump_to_sal) +#endif /* CONFIG_HOTPLUG_CPU */ + #endif /* CONFIG_SMP */ diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index cf3f8014f9ad..ef3fd7265b67 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -110,46 +110,19 @@ .global ia64_os_mca_dispatch_end .global ia64_sal_to_os_handoff_state .global ia64_os_to_sal_handoff_state + .global ia64_do_tlb_purge .text .align 16 -ia64_os_mca_dispatch: - - // Serialize all MCA processing - mov r3=1;; - LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);; -ia64_os_mca_spin: - xchg8 r4=[r2],r3;; - cmp.ne p6,p0=r4,r0 -(p6) br ia64_os_mca_spin - - // Save the SAL to OS MCA handoff state as defined - // by SAL SPEC 3.0 - // NOTE : The order in which the state gets saved - // is dependent on the way the C-structure - // for ia64_mca_sal_to_os_state_t has been - // defined in include/asm/mca.h - SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) - ;; - - // LOG PROCESSOR STATE INFO FROM HERE ON.. -begin_os_mca_dump: - br ia64_os_mca_proc_state_dump;; - -ia64_os_mca_done_dump: - - LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56) - ;; - ld8 r18=[r16] // Get processor state parameter on existing PALE_CHECK. - ;; - tbit.nz p6,p7=r18,60 -(p7) br.spnt done_tlb_purge_and_reload - - // The following code purges TC and TR entries. Then reload all TC entries. - // Purge percpu data TC entries. -begin_tlb_purge_and_reload: +/* + * Just the TLB purge part is moved to a separate function + * so we can re-use the code for cpu hotplug code as well + * Caller should now setup b1, so we can branch once the + * tlb flush is complete. + */ +ia64_do_tlb_purge: #define O(member) IA64_CPUINFO_##member##_OFFSET GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2 @@ -230,6 +203,51 @@ begin_tlb_purge_and_reload: ;; srlz.i ;; + // Now branch away to caller. + br.sptk.many b1 + ;; + +ia64_os_mca_dispatch: + + // Serialize all MCA processing + mov r3=1;; + LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);; +ia64_os_mca_spin: + xchg8 r4=[r2],r3;; + cmp.ne p6,p0=r4,r0 +(p6) br ia64_os_mca_spin + + // Save the SAL to OS MCA handoff state as defined + // by SAL SPEC 3.0 + // NOTE : The order in which the state gets saved + // is dependent on the way the C-structure + // for ia64_mca_sal_to_os_state_t has been + // defined in include/asm/mca.h + SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) + ;; + + // LOG PROCESSOR STATE INFO FROM HERE ON.. +begin_os_mca_dump: + br ia64_os_mca_proc_state_dump;; + +ia64_os_mca_done_dump: + + LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56) + ;; + ld8 r18=[r16] // Get processor state parameter on existing PALE_CHECK. + ;; + tbit.nz p6,p7=r18,60 +(p7) br.spnt done_tlb_purge_and_reload + + // The following code purges TC and TR entries. Then reload all TC entries. + // Purge percpu data TC entries. +begin_tlb_purge_and_reload: + movl r18=ia64_reload_tr;; + LOAD_PHYSICAL(p0,r18,ia64_reload_tr);; + mov b1=r18;; + br.sptk.many ia64_do_tlb_purge;; + +ia64_reload_tr: // Finally reload the TR registers. // 1. Reload DTR/ITR registers for kernel. mov r18=KERNEL_TR_PAGE_SHIFT<<2 diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 91293388dd29..7c43aea5f7f7 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -3,6 +3,7 @@ * * Copyright (C) 1998-2003 Hewlett-Packard Co * David Mosberger-Tang + * 04/11/17 Ashok Raj Added CPU Hotplug Support */ #define __KERNEL_SYSCALLS__ /* see */ #include @@ -200,27 +201,20 @@ default_idle (void) static inline void play_dead(void) { extern void ia64_cpu_local_tick (void); + unsigned int this_cpu = smp_processor_id(); + /* Ack it */ __get_cpu_var(cpu_state) = CPU_DEAD; - /* We shouldn't have to disable interrupts while dead, but - * some interrupts just don't seem to go away, and this makes - * it "work" for testing purposes. */ max_xtp(); local_irq_disable(); - /* Death loop */ - while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) - cpu_relax(); - + idle_task_exit(); + ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]); /* - * Enable timer interrupts from now on - * Not required if we put processor in SAL_BOOT_RENDEZ mode. + * The above is a point of no-return, the processor is + * expected to be in SAL loop now. */ - local_flush_tlb_all(); - cpu_set(smp_processor_id(), cpu_online_map); - wmb(); - ia64_cpu_local_tick (); - local_irq_enable(); + BUG(); } #else static inline void play_dead(void) diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 5318f0cbfc26..ca1536db3394 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -9,6 +9,7 @@ * 02/07/31 David Mosberger Switch over to hotplug-CPU boot-sequence. * smp_boot_cpus()/smp_commence() is replaced by * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). + * 04/06/21 Ashok Raj Added CPU Hotplug Support */ #include @@ -58,6 +59,37 @@ #define Dprintk(x...) #endif +#ifdef CONFIG_HOTPLUG_CPU +/* + * Store all idle threads, this can be reused instead of creating + * a new thread. Also avoids complicated thread destroy functionality + * for idle threads. + */ +struct task_struct *idle_thread_array[NR_CPUS]; + +/* + * Global array allocated for NR_CPUS at boot time + */ +struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS]; + +/* + * start_ap in head.S uses this to store current booting cpu + * info. + */ +struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0]; + +#define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]); + +#define get_idle_for_cpu(x) (idle_thread_array[(x)]) +#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p)) + +#else + +#define get_idle_for_cpu(x) (NULL) +#define set_idle_for_cpu(x,p) +#define set_brendez_area(x) +#endif + /* * ITC synchronization related stuff: @@ -345,7 +377,6 @@ start_secondary (void *unused) { /* Early console may use I/O ports */ ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase)); - Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id()); efi_map_pal_code(); cpu_init(); @@ -384,6 +415,13 @@ do_boot_cpu (int sapicid, int cpu) .done = COMPLETION_INITIALIZER(c_idle.done), }; DECLARE_WORK(work, do_fork_idle, &c_idle); + + c_idle.idle = get_idle_for_cpu(cpu); + if (c_idle.idle) { + init_idle(c_idle.idle, cpu); + goto do_rest; + } + /* * We can't use kernel_thread since we must avoid to reschedule the child. */ @@ -396,10 +434,15 @@ do_boot_cpu (int sapicid, int cpu) if (IS_ERR(c_idle.idle)) panic("failed fork for CPU %d", cpu); + + set_idle_for_cpu(cpu, c_idle.idle); + +do_rest: task_for_booting_cpu = c_idle.idle; Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); + set_brendez_area(cpu); platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); /* @@ -555,16 +598,6 @@ void __devinit smp_prepare_boot_cpu(void) #ifdef CONFIG_HOTPLUG_CPU extern void fixup_irqs(void); /* must be called with cpucontrol mutex held */ -static int __devinit cpu_enable(unsigned int cpu) -{ - per_cpu(cpu_state,cpu) = CPU_UP_PREPARE; - wmb(); - - while (!cpu_online(cpu)) - cpu_relax(); - return 0; -} - int __cpu_disable(void) { int cpu = smp_processor_id(); @@ -577,7 +610,7 @@ int __cpu_disable(void) fixup_irqs(); local_flush_tlb_all(); - printk ("Disabled cpu %u\n", smp_processor_id()); + cpu_clear(cpu, cpu_callin_map); return 0; } @@ -589,12 +622,7 @@ void __cpu_die(unsigned int cpu) /* They ack this in play_dead by setting CPU_DEAD */ if (per_cpu(cpu_state, cpu) == CPU_DEAD) { - /* - * TBD: Enable this when physical removal - * or when we put the processor is put in - * SAL_BOOT_RENDEZ mode - * cpu_clear(cpu, cpu_callin_map); - */ + printk ("CPU %d is now offline\n", cpu); return; } msleep(100); @@ -602,11 +630,6 @@ void __cpu_die(unsigned int cpu) printk(KERN_ERR "CPU %u didn't die...\n", cpu); } #else /* !CONFIG_HOTPLUG_CPU */ -static int __devinit cpu_enable(unsigned int cpu) -{ - return 0; -} - int __cpu_disable(void) { return -ENOSYS; @@ -648,16 +671,12 @@ __cpu_up (unsigned int cpu) return -EINVAL; /* - * Already booted.. just enable and get outa idle lool + * Already booted cpu? not valid anymore since we dont + * do idle loop tightspin anymore. */ if (cpu_isset(cpu, cpu_callin_map)) - { - cpu_enable(cpu); - local_irq_enable(); - while (!cpu_isset(cpu, cpu_online_map)) - mb(); - return 0; - } + return -EINVAL; + /* Processor goes to start_secondary(), sets online flag */ ret = do_boot_cpu(sapicid, cpu); if (ret < 0) diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index ea1ed377de4c..240676f75390 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -832,6 +832,44 @@ extern int ia64_sal_oemcall_nolock(struct ia64_sal_retval *, u64, u64, u64, u64, u64, u64, u64, u64); extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64, u64, u64, u64, u64, u64); +#ifdef CONFIG_HOTPLUG_CPU +/* + * System Abstraction Layer Specification + * Section 3.2.5.1: OS_BOOT_RENDEZ to SAL return State. + * Note: region regs are stored first in head.S _start. Hence they must + * stay up front. + */ +struct sal_to_os_boot { + u64 rr[8]; /* Region Registers */ + u64 br[6]; /* br0: return addr into SAL boot rendez routine */ + u64 gr1; /* SAL:GP */ + u64 gr12; /* SAL:SP */ + u64 gr13; /* SAL: Task Pointer */ + u64 fpsr; + u64 pfs; + u64 rnat; + u64 unat; + u64 bspstore; + u64 dcr; /* Default Control Register */ + u64 iva; + u64 pta; + u64 itv; + u64 pmv; + u64 cmcv; + u64 lrr[2]; + u64 gr[4]; + u64 pr; /* Predicate registers */ + u64 lc; /* Loop Count */ + struct ia64_fpreg fp[20]; +}; + +/* + * Global array allocated for NR_CPUS at boot time + */ +extern struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS]; + +extern void ia64_jump_to_sal(struct sal_to_os_boot *); +#endif extern void ia64_sal_handler_init(void *entry_point, void *gpval); -- cgit v1.2.3 From 3106dbcd914d8dac4b89f52d8d51ec93526cbb95 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Apr 2005 12:28:35 -0700 Subject: [PATCH] __get_unaligned() turned into macro Turns __get_unaligned() and __put_unaligned into macros. That is definitely safe; leaving them as inlines breaks on e.g. alpha [try to build ncpfs there and you'll get unresolved symbols since we end up getting __get_unaligned() not inlined]. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- include/asm-generic/unaligned.h | 83 +++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h index c856a43e3b45..6c90f0f36eec 100644 --- a/include/asm-generic/unaligned.h +++ b/include/asm-generic/unaligned.h @@ -76,46 +76,47 @@ static inline void __ustw(__u16 val, __u16 *addr) ptr->x = val; } -static inline unsigned long __get_unaligned(const void *ptr, size_t size) -{ - unsigned long val; - switch (size) { - case 1: - val = *(const __u8 *)ptr; - break; - case 2: - val = __uldw((const __u16 *)ptr); - break; - case 4: - val = __uldl((const __u32 *)ptr); - break; - case 8: - val = __uldq((const __u64 *)ptr); - break; - default: - bad_unaligned_access_length(); - }; - return val; -} - -static inline void __put_unaligned(unsigned long val, void *ptr, size_t size) -{ - switch (size) { - case 1: - *(__u8 *)ptr = val; - break; - case 2: - __ustw(val, (__u16 *)ptr); - break; - case 4: - __ustl(val, (__u32 *)ptr); - break; - case 8: - __ustq(val, (__u64 *)ptr); - break; - default: - bad_unaligned_access_length(); - }; -} +#define __get_unaligned(ptr, size) ({ \ + const void *__gu_p = ptr; \ + unsigned long val; \ + switch (size) { \ + case 1: \ + val = *(const __u8 *)__gu_p; \ + break; \ + case 2: \ + val = __uldw(__gu_p); \ + break; \ + case 4: \ + val = __uldl(__gu_p); \ + break; \ + case 8: \ + val = __uldq(__gu_p); \ + break; \ + default: \ + bad_unaligned_access_length(); \ + }; \ + val; \ +}) + +#define __put_unaligned(val, ptr, size) \ +do { \ + void *__gu_p = ptr; \ + switch (size) { \ + case 1: \ + *(__u8 *)__gu_p = val; \ + break; \ + case 2: \ + __ustw(val, __gu_p); \ + break; \ + case 4: \ + __ustl(val, __gu_p); \ + break; \ + case 8: \ + __ustq(val, __gu_p); \ + break; \ + default: \ + bad_unaligned_access_length(); \ + }; \ +} while(0) #endif /* _ASM_GENERIC_UNALIGNED_H */ -- cgit v1.2.3 From ef0299bf8e868c09bff13e6f3c4fc9b835f60471 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Apr 2005 12:28:36 -0700 Subject: [PATCH] mostek bogus sparse annotations fixed void * __iomem foo is not a pointer to iomem - it's an iomem variable containing void *. A pile of such guys in arch/sparc64/kernel/time.c, drivers/sbus/char/rtc.c and include/asm-sparc64/mostek.h turned into intended void __iomem *. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/sparc64/kernel/time.c | 24 ++++++++++++------------ drivers/sbus/char/rtc.c | 6 +++--- include/asm-sparc64/mostek.h | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index c60785c046be..71b4e3807694 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -48,7 +48,7 @@ DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); -void * __iomem mstk48t02_regs = 0UL; +void __iomem *mstk48t02_regs = NULL; #ifdef CONFIG_PCI unsigned long ds1287_regs = 0UL; #endif @@ -59,8 +59,8 @@ u64 jiffies_64 = INITIAL_JIFFIES; EXPORT_SYMBOL(jiffies_64); -static void * __iomem mstk48t08_regs; -static void * __iomem mstk48t59_regs; +static void __iomem *mstk48t08_regs; +static void __iomem *mstk48t59_regs; static int set_rtc_mmss(unsigned long); @@ -520,7 +520,7 @@ void timer_tick_interrupt(struct pt_regs *regs) /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ static void __init kick_start_clock(void) { - void * __iomem regs = mstk48t02_regs; + void __iomem *regs = mstk48t02_regs; u8 sec, tmp; int i, count; @@ -604,7 +604,7 @@ static void __init kick_start_clock(void) /* Return nonzero if the clock chip battery is low. */ static int __init has_low_battery(void) { - void * __iomem regs = mstk48t02_regs; + void __iomem *regs = mstk48t02_regs; u8 data1, data2; spin_lock_irq(&mostek_lock); @@ -623,7 +623,7 @@ static int __init has_low_battery(void) static void __init set_system_time(void) { unsigned int year, mon, day, hour, min, sec; - void * __iomem mregs = mstk48t02_regs; + void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; #else @@ -843,7 +843,7 @@ void __init clock_probe(void) !strcmp(model, "m5823")) { ds1287_regs = edev->resource[0].start; } else { - mstk48t59_regs = (void * __iomem) + mstk48t59_regs = (void __iomem *) edev->resource[0].start; mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } @@ -866,7 +866,7 @@ try_isa_clock: !strcmp(model, "m5823")) { ds1287_regs = isadev->resource.start; } else { - mstk48t59_regs = (void * __iomem) + mstk48t59_regs = (void __iomem *) isadev->resource.start; mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } @@ -895,16 +895,16 @@ try_isa_clock: } if(model[5] == '0' && model[6] == '2') { - mstk48t02_regs = (void * __iomem) + mstk48t02_regs = (void __iomem *) (((u64)clk_reg[0].phys_addr) | (((u64)clk_reg[0].which_io)<<32UL)); } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = (void * __iomem) + mstk48t08_regs = (void __iomem *) (((u64)clk_reg[0].phys_addr) | (((u64)clk_reg[0].which_io)<<32UL)); mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; } else { - mstk48t59_regs = (void * __iomem) + mstk48t59_regs = (void __iomem *) (((u64)clk_reg[0].phys_addr) | (((u64)clk_reg[0].which_io)<<32UL)); mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; @@ -1092,7 +1092,7 @@ unsigned long long sched_clock(void) static int set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, chip_minutes; - void * __iomem mregs = mstk48t02_regs; + void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; #else diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c index 49d1cd99d5ac..9b988baf0b51 100644 --- a/drivers/sbus/char/rtc.c +++ b/drivers/sbus/char/rtc.c @@ -67,7 +67,7 @@ struct rtc_time_generic { /* Retrieve the current date and time from the real time clock. */ static void get_rtc_time(struct rtc_time *t) { - void * __iomem regs = mstk48t02_regs; + void __iomem *regs = mstk48t02_regs; u8 tmp; spin_lock_irq(&mostek_lock); @@ -94,7 +94,7 @@ static void get_rtc_time(struct rtc_time *t) /* Set the current date and time inthe real time clock. */ void set_rtc_time(struct rtc_time *t) { - void * __iomem regs = mstk48t02_regs; + void __iomem *regs = mstk48t02_regs; u8 tmp; spin_lock_irq(&mostek_lock); @@ -250,7 +250,7 @@ static int __init rtc_sun_init(void) /* It is possible we are being driven by some other RTC chip * and thus another RTC driver is handling things. */ - if (mstk48t02_regs == 0) + if (!mstk48t02_regs) return -ENODEV; error = misc_register(&rtc_dev); diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h index 1f9b1356a48e..09b5aba6678a 100644 --- a/include/asm-sparc64/mostek.h +++ b/include/asm-sparc64/mostek.h @@ -38,7 +38,7 @@ * * We now deal with physical addresses for I/O to the chip. -DaveM */ -static __inline__ u8 mostek_read(void * __iomem addr) +static __inline__ u8 mostek_read(void __iomem *addr) { u8 ret; @@ -48,7 +48,7 @@ static __inline__ u8 mostek_read(void * __iomem addr) return ret; } -static __inline__ void mostek_write(void * __iomem addr, u8 val) +static __inline__ void mostek_write(void __iomem *addr, u8 val) { __asm__ __volatile__("stba %0, [%1] %2" : /* no outputs */ @@ -67,7 +67,7 @@ static __inline__ void mostek_write(void * __iomem addr, u8 val) #define MOSTEK_YEAR 0x07ffUL extern spinlock_t mostek_lock; -extern void *__iomem mstk48t02_regs; +extern void __iomem *mstk48t02_regs; /* Control register values. */ #define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ -- cgit v1.2.3 From e2178f199b341cc3e3ac86be50a54b0d8d8a132f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Apr 2005 14:58:08 -0700 Subject: [PATCH] ppc trivial iomem annotations: chrp Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/ppc/platforms/chrp_pci.c | 7 ++++--- arch/ppc/platforms/chrp_setup.c | 2 +- include/asm-ppc/hydra.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c index 5bb6492ecf8c..7d0ee308f662 100644 --- a/arch/ppc/platforms/chrp_pci.c +++ b/arch/ppc/platforms/chrp_pci.c @@ -129,7 +129,7 @@ static struct pci_ops rtas_pci_ops = rtas_write_config }; -volatile struct Hydra *Hydra = NULL; +volatile struct Hydra __iomem *Hydra = NULL; int __init hydra_init(void) @@ -175,13 +175,14 @@ chrp_pcibios_fixup(void) static void __init setup_python(struct pci_controller *hose, struct device_node *dev) { - u32 *reg, val; + u32 __iomem *reg; + u32 val; unsigned long addr = dev->addrs[0].address; setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010); /* Clear the magic go-slow bit */ - reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40); + reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40); val = in_be32(®[12]); if (val & PRG_CL_RESET_VALID) { out_be32(®[12], val & ~PRG_CL_RESET_VALID); diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c index f23c4f320760..57f29ab29bda 100644 --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c @@ -356,7 +356,7 @@ static void __init chrp_find_openpic(void) struct device_node *np; int len, i; unsigned int *iranges; - void *isu; + void __iomem *isu; np = find_type_devices("open-pic"); if (np == NULL || np->n_addrs == 0) diff --git a/include/asm-ppc/hydra.h b/include/asm-ppc/hydra.h index 1134431431da..833a8aff2a80 100644 --- a/include/asm-ppc/hydra.h +++ b/include/asm-ppc/hydra.h @@ -51,7 +51,7 @@ struct Hydra { char OpenPIC[0x40000]; }; -extern volatile struct Hydra *Hydra; +extern volatile struct Hydra __iomem *Hydra; /* -- cgit v1.2.3 From e281e3ac2b6c294d672034909883e7bb9e649ac7 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 24 Apr 2005 18:41:38 -0700 Subject: [NETFILTER]: Fix NAT sequence number adjustment The NAT changes in 2.6.11 changed the position where helpers are called and perform packet mangling. Before 2.6.11, a NAT helper was called before the packet was NATed and had its sequence number adjusted. Since 2.6.11, the helpers get packets with already adjusted sequence numbers. This breaks sequence number adjustment, adjust_tcp_sequence() needs the original sequence number to determine whether a packet was a retransmission and to store it for further corrections. It can't be reconstructed without more information than available, so this patch restores the old order by calling helpers from a new conntrack hook two priorities below ip_conntrack_confirm() and adjusting the sequence number from a new NAT hook one priority below ip_conntrack_confirm(). Tracked down by Phil Oester Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter_ipv4.h | 3 ++ net/ipv4/netfilter/ip_conntrack_standalone.c | 51 ++++++++++++++++++++++---- net/ipv4/netfilter/ip_nat_core.c | 9 ----- net/ipv4/netfilter/ip_nat_standalone.c | 54 +++++++++++++++++++++++++++- 4 files changed, 101 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index c9bacf9b2431..9e5750079e09 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -62,6 +62,9 @@ enum nf_ip_hook_priorities { NF_IP_PRI_FILTER = 0, NF_IP_PRI_NAT_SRC = 100, NF_IP_PRI_SELINUX_LAST = 225, + NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2, + NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1, + NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, NF_IP_PRI_LAST = INT_MAX, }; diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 80a7bde2a57a..0c29ccf62a89 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -400,6 +400,16 @@ static unsigned int ip_confirm(unsigned int hooknum, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) +{ + /* We've seen it coming out the other side: confirm it */ + return ip_conntrack_confirm(pskb); +} + +static unsigned int ip_conntrack_help(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; @@ -412,9 +422,7 @@ static unsigned int ip_confirm(unsigned int hooknum, if (ret != NF_ACCEPT) return ret; } - - /* We've seen it coming out the other side: confirm it */ - return ip_conntrack_confirm(pskb); + return NF_ACCEPT; } static unsigned int ip_conntrack_defrag(unsigned int hooknum, @@ -516,13 +524,30 @@ static struct nf_hook_ops ip_conntrack_local_out_ops = { .priority = NF_IP_PRI_CONNTRACK, }; +/* helpers */ +static struct nf_hook_ops ip_conntrack_helper_out_ops = { + .hook = ip_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_HELPER, +}; + +static struct nf_hook_ops ip_conntrack_helper_in_ops = { + .hook = ip_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_CONNTRACK_HELPER, +}; + /* Refragmenter; last chance. */ static struct nf_hook_ops ip_conntrack_out_ops = { .hook = ip_refrag, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_LAST, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }; static struct nf_hook_ops ip_conntrack_local_in_ops = { @@ -530,7 +555,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_LAST-1, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }; /* Sysctl support */ @@ -831,10 +856,20 @@ static int init_or_cleanup(int init) printk("ip_conntrack: can't register local out hook.\n"); goto cleanup_inops; } + ret = nf_register_hook(&ip_conntrack_helper_in_ops); + if (ret < 0) { + printk("ip_conntrack: can't register local in helper hook.\n"); + goto cleanup_inandlocalops; + } + ret = nf_register_hook(&ip_conntrack_helper_out_ops); + if (ret < 0) { + printk("ip_conntrack: can't register postrouting helper hook.\n"); + goto cleanup_helperinops; + } ret = nf_register_hook(&ip_conntrack_out_ops); if (ret < 0) { printk("ip_conntrack: can't register post-routing hook.\n"); - goto cleanup_inandlocalops; + goto cleanup_helperoutops; } ret = nf_register_hook(&ip_conntrack_local_in_ops); if (ret < 0) { @@ -860,6 +895,10 @@ static int init_or_cleanup(int init) nf_unregister_hook(&ip_conntrack_local_in_ops); cleanup_inoutandlocalops: nf_unregister_hook(&ip_conntrack_out_ops); + cleanup_helperoutops: + nf_unregister_hook(&ip_conntrack_helper_out_ops); + cleanup_helperinops: + nf_unregister_hook(&ip_conntrack_helper_in_ops); cleanup_inandlocalops: nf_unregister_hook(&ip_conntrack_local_out_ops); cleanup_inops: diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 162ceacfc29a..9fc6f93af0dd 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -356,15 +356,6 @@ unsigned int nat_packet(struct ip_conntrack *ct, unsigned long statusbit; enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum); - if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) - && (hooknum == NF_IP_POST_ROUTING || hooknum == NF_IP_LOCAL_IN)) { - DEBUGP("ip_nat_core: adjusting sequence number\n"); - /* future: put this in a l4-proto specific function, - * and call this function here. */ - if (!ip_nat_seq_adjust(pskb, ct, ctinfo)) - return NF_DROP; - } - if (mtype == IP_NAT_MANIP_SRC) statusbit = IPS_SRC_NAT; else diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index dec4a74212cd..79f56f662b33 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -230,6 +230,25 @@ ip_nat_local_fn(unsigned int hooknum, return ret; } +static unsigned int +ip_nat_adjust(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + struct ip_conntrack *ct; + enum ip_conntrack_info ctinfo; + + ct = ip_conntrack_get(*pskb, &ctinfo); + if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { + DEBUGP("ip_nat_standalone: adjusting sequence number\n"); + if (!ip_nat_seq_adjust(pskb, ct, ctinfo)) + return NF_DROP; + } + return NF_ACCEPT; +} + /* We must be after connection tracking and before packet filtering. */ /* Before packet filtering, change destination */ @@ -250,6 +269,15 @@ static struct nf_hook_ops ip_nat_out_ops = { .priority = NF_IP_PRI_NAT_SRC, }; +/* After conntrack, adjust sequence number */ +static struct nf_hook_ops ip_nat_adjust_out_ops = { + .hook = ip_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, +}; + /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_local_out_ops = { .hook = ip_nat_local_fn, @@ -268,6 +296,16 @@ static struct nf_hook_ops ip_nat_local_in_ops = { .priority = NF_IP_PRI_NAT_SRC, }; +/* After conntrack, adjust sequence number */ +static struct nf_hook_ops ip_nat_adjust_in_ops = { + .hook = ip_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, +}; + + static int init_or_cleanup(int init) { int ret = 0; @@ -296,10 +334,20 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't register out hook.\n"); goto cleanup_inops; } + ret = nf_register_hook(&ip_nat_adjust_in_ops); + if (ret < 0) { + printk("ip_nat_init: can't register adjust in hook.\n"); + goto cleanup_outops; + } + ret = nf_register_hook(&ip_nat_adjust_out_ops); + if (ret < 0) { + printk("ip_nat_init: can't register adjust out hook.\n"); + goto cleanup_adjustin_ops; + } ret = nf_register_hook(&ip_nat_local_out_ops); if (ret < 0) { printk("ip_nat_init: can't register local out hook.\n"); - goto cleanup_outops; + goto cleanup_adjustout_ops;; } ret = nf_register_hook(&ip_nat_local_in_ops); if (ret < 0) { @@ -312,6 +360,10 @@ static int init_or_cleanup(int init) nf_unregister_hook(&ip_nat_local_in_ops); cleanup_localoutops: nf_unregister_hook(&ip_nat_local_out_ops); + cleanup_adjustout_ops: + nf_unregister_hook(&ip_nat_adjust_out_ops); + cleanup_adjustin_ops: + nf_unregister_hook(&ip_nat_adjust_in_ops); cleanup_outops: nf_unregister_hook(&ip_nat_out_ops); cleanup_inops: -- cgit v1.2.3 From 56cb515628e6a831bb76783f282a71f7285dad33 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 24 Apr 2005 18:53:06 -0700 Subject: [AX25] Introduce ax25_type_trans Replacing the open coded equivalents and making ax25 look more like a linux network protocol, i.e. more similar to inet. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- drivers/net/hamradio/6pack.c | 4 +--- drivers/net/hamradio/baycom_epp.c | 4 +--- drivers/net/hamradio/bpqether.c | 10 ++-------- drivers/net/hamradio/dmascc.c | 4 +--- drivers/net/hamradio/hdlcdrv.c | 4 +--- drivers/net/hamradio/mkiss.c | 4 +--- drivers/net/hamradio/scc.c | 5 +---- drivers/net/hamradio/yam.c | 4 +--- include/net/ax25.h | 8 ++++++++ net/ax25/ax25_ds_subr.c | 3 +-- net/ax25/ax25_out.c | 3 +-- 11 files changed, 19 insertions(+), 34 deletions(-) (limited to 'include') diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 067b353e1cbd..89454915b857 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -394,13 +394,11 @@ static void sp_bump(struct sixpack *sp, char cmd) if ((skb = dev_alloc_skb(count)) == NULL) goto out_mem; - skb->dev = sp->dev; ptr = skb_put(skb, count); *ptr++ = cmd; /* KISS command */ memcpy(ptr, sp->cooked_buf + 1, count); - skb->mac.raw = skb->data; - skb->protocol = htons(ETH_P_AX25); + skb->protocol = ax25_type_trans(skb, sp->dev); netif_rx(skb); sp->dev->last_rx = jiffies; sp->stats.rx_packets++; diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index e8cb87d906fc..1c563f905a59 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -601,12 +601,10 @@ static void do_rxpacket(struct net_device *dev) bc->stats.rx_dropped++; return; } - skb->dev = dev; cp = skb_put(skb, pktlen); *cp++ = 0; /* KISS kludge */ memcpy(cp, bc->hdlcrx.buf, pktlen - 1); - skb->protocol = htons(ETH_P_AX25); - skb->mac.raw = skb->data; + skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; bc->stats.rx_packets++; diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index ef1a359e2273..ba9f0580e1f9 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -211,11 +211,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty ptr = skb_push(skb, 1); *ptr = 0; - skb->dev = dev; - skb->protocol = htons(ETH_P_AX25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; unlock: @@ -272,8 +268,6 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) skb = newskb; } - skb->protocol = htons(ETH_P_AX25); - ptr = skb_push(skb, 2); *ptr++ = (size + 5) % 256; @@ -287,7 +281,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) return -ENODEV; } - skb->dev = dev; + skb->protocol = ax25_type_trans(skb, dev); skb->nh.raw = skb->data; dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0); bpq->stats.tx_packets++; diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index f3269b70a8c5..f515245a3fd0 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -1306,9 +1306,7 @@ static void rx_bh(void *arg) data = skb_put(skb, cb + 1); data[0] = 0; memcpy(&data[1], priv->rx_buf[i], cb); - skb->dev = priv->dev; - skb->protocol = ntohs(ETH_P_AX25); - skb->mac.raw = skb->data; + skb->protocol = ax25_type_trans(skb, priv->dev); netif_rx(skb); priv->dev->last_rx = jiffies; priv->stats.rx_packets++; diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index b89959a596d7..b4c836e4fe86 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -174,12 +174,10 @@ static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s) s->stats.rx_dropped++; return; } - skb->dev = dev; cp = skb_put(skb, pkt_len); *cp++ = 0; /* KISS kludge */ memcpy(cp, s->hdlcrx.buffer, pkt_len - 1); - skb->protocol = htons(ETH_P_AX25); - skb->mac.raw = skb->data; + skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; s->stats.rx_packets++; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index d9ea080aea0f..62790511098f 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -332,12 +332,10 @@ static void ax_bump(struct ax_disp *ax) return; } - skb->dev = ax->dev; spin_lock_bh(&ax->buflock); memcpy(skb_put(skb,count), ax->rbuff, count); spin_unlock_bh(&ax->buflock); - skb->mac.raw = skb->data; - skb->protocol = htons(ETH_P_AX25); + skb->protocol = ax25_type_trans(skb, ax->dev); netif_rx(skb); ax->dev->last_rx = jiffies; ax->rx_packets++; diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index ce9e7af020da..ece1b1a13186 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -1630,10 +1630,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb) scc->dev_stat.rx_packets++; scc->dev_stat.rx_bytes += skb->len; - skb->dev = scc->dev; - skb->protocol = htons(ETH_P_AX25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; + skb->protocol = ax25_type_trans(skb, scc->dev); netif_rx(skb); scc->dev->last_rx = jiffies; diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index fd7b00fe38e5..41213ef602dc 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -522,12 +522,10 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp) ++yp->stats.rx_dropped; } else { unsigned char *cp; - skb->dev = dev; cp = skb_put(skb, pkt_len); *cp++ = 0; /* KISS kludge */ memcpy(cp, yp->rx_buf, pkt_len - 1); - skb->protocol = htons(ETH_P_AX25); - skb->mac.raw = skb->data; + skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; ++yp->stats.rx_packets; diff --git a/include/net/ax25.h b/include/net/ax25.h index 875edbba396d..9e6368a54547 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h @@ -220,6 +220,14 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25) } } +static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev) +{ + skb->dev = dev; + skb->pkt_type = PACKET_HOST; + skb->mac.raw = skb->data; + return htons(ETH_P_AX25); +} + /* af_ax25.c */ extern struct hlist_head ax25_list; extern spinlock_t ax25_list_lock; diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c index 10ffd2beba3f..1d4ab641f82b 100644 --- a/net/ax25/ax25_ds_subr.c +++ b/net/ax25/ax25_ds_subr.c @@ -143,8 +143,7 @@ static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char p *p++ = cmd; *p++ = param; - skb->dev = ax25_dev->dev; - skb->protocol = htons(ETH_P_AX25); + skb->protocol = ax25_type_trans(skb, ax25_dev->dev); dev_queue_xmit(skb); } diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 94557b1a1fa2..5fc048dcd39a 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -351,8 +351,7 @@ void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned char *ptr; - skb->protocol = htons(ETH_P_AX25); - skb->dev = ax25_fwd_dev(dev); + skb->protocol = ax25_type_trans(skb, ax25_fwd_dev(dev)); ptr = skb_push(skb, 1); *ptr = 0x00; /* KISS */ -- cgit v1.2.3 From d5ac99a648b8c61d0c7f1c32a8ab7f1dca0123d2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Apr 2005 19:12:33 -0700 Subject: [TCP]: skb pcount with MTU discovery The problem is that when doing MTU discovery, the too-large segments in the write queue will be calculated as having a pcount of >1. When tcp_write_xmit() is trying to send, tcp_snd_test() fails the cwnd test when pcount > cwnd. The segments are eventually transmitted one at a time by keepalive, but this can take a long time. This patch checks if TSO is enabled when setting pcount. Signed-off-by: John Heffner Signed-off-by: David S. Miller --- include/net/tcp.h | 11 ++++++----- net/ipv4/tcp_output.c | 25 ++++++++++++++----------- 2 files changed, 20 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/net/tcp.h b/include/net/tcp.h index 503810a70e21..9355ae5b1d75 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1417,19 +1417,20 @@ tcp_nagle_check(const struct tcp_sock *tp, const struct sk_buff *skb, tcp_minshall_check(tp)))); } -extern void tcp_set_skb_tso_segs(struct sk_buff *, unsigned int); +extern void tcp_set_skb_tso_segs(struct sock *, struct sk_buff *); /* This checks if the data bearing packet SKB (usually sk->sk_send_head) * should be put on the wire right now. */ -static __inline__ int tcp_snd_test(const struct tcp_sock *tp, +static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb, unsigned cur_mss, int nonagle) { + struct tcp_sock *tp = tcp_sk(sk); int pkts = tcp_skb_pcount(skb); if (!pkts) { - tcp_set_skb_tso_segs(skb, tp->mss_cache_std); + tcp_set_skb_tso_segs(sk, skb); pkts = tcp_skb_pcount(skb); } @@ -1490,7 +1491,7 @@ static __inline__ void __tcp_push_pending_frames(struct sock *sk, if (skb) { if (!tcp_skb_is_last(sk, skb)) nonagle = TCP_NAGLE_PUSH; - if (!tcp_snd_test(tp, skb, cur_mss, nonagle) || + if (!tcp_snd_test(sk, skb, cur_mss, nonagle) || tcp_write_xmit(sk, nonagle)) tcp_check_probe_timer(sk, tp); } @@ -1508,7 +1509,7 @@ static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp) struct sk_buff *skb = sk->sk_send_head; return (skb && - tcp_snd_test(tp, skb, tcp_current_mss(sk, 1), + tcp_snd_test(sk, skb, tcp_current_mss(sk, 1), tcp_skb_is_last(sk, skb) ? TCP_NAGLE_PUSH : tp->nonagle)); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 13c14cb6dee4..a12df6979ffd 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -427,7 +427,7 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss) struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb = sk->sk_send_head; - if (tcp_snd_test(tp, skb, cur_mss, TCP_NAGLE_PUSH)) { + if (tcp_snd_test(sk, skb, cur_mss, TCP_NAGLE_PUSH)) { /* Send it out now. */ TCP_SKB_CB(skb)->when = tcp_time_stamp; tcp_tso_set_push(skb); @@ -440,9 +440,12 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss) } } -void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std) +void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb) { - if (skb->len <= mss_std) { + struct tcp_sock *tp = tcp_sk(sk); + + if (skb->len <= tp->mss_cache_std || + !(sk->sk_route_caps & NETIF_F_TSO)) { /* Avoid the costly divide in the normal * non-TSO case. */ @@ -451,10 +454,10 @@ void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std) } else { unsigned int factor; - factor = skb->len + (mss_std - 1); - factor /= mss_std; + factor = skb->len + (tp->mss_cache_std - 1); + factor /= tp->mss_cache_std; skb_shinfo(skb)->tso_segs = factor; - skb_shinfo(skb)->tso_size = mss_std; + skb_shinfo(skb)->tso_size = tp->mss_cache_std; } } @@ -525,8 +528,8 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len) } /* Fix up tso_factor for both original and new SKB. */ - tcp_set_skb_tso_segs(skb, tp->mss_cache_std); - tcp_set_skb_tso_segs(buff, tp->mss_cache_std); + tcp_set_skb_tso_segs(sk, skb); + tcp_set_skb_tso_segs(sk, buff); if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { tp->lost_out += tcp_skb_pcount(skb); @@ -601,7 +604,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) * factor and mss. */ if (tcp_skb_pcount(skb) > 1) - tcp_set_skb_tso_segs(skb, tcp_skb_mss(skb)); + tcp_set_skb_tso_segs(sk, skb); return 0; } @@ -752,7 +755,7 @@ int tcp_write_xmit(struct sock *sk, int nonagle) mss_now = tcp_current_mss(sk, 1); while ((skb = sk->sk_send_head) && - tcp_snd_test(tp, skb, mss_now, + tcp_snd_test(sk, skb, mss_now, tcp_skb_is_last(sk, skb) ? nonagle : TCP_NAGLE_PUSH)) { if (skb->len > mss_now) { @@ -1676,7 +1679,7 @@ int tcp_write_wakeup(struct sock *sk) tp->mss_cache = tp->mss_cache_std; } } else if (!tcp_skb_pcount(skb)) - tcp_set_skb_tso_segs(skb, tp->mss_cache_std); + tcp_set_skb_tso_segs(sk, skb); TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; TCP_SKB_CB(skb)->when = tcp_time_stamp; -- cgit v1.2.3 From db7530797992bb2be703f9f3cc69b1a578f812f8 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 24 Apr 2005 20:10:16 -0700 Subject: [PKT_SCHED]: Introduce simple actions. And provide an example simply action in order to demonstrate usage. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/tc_act/tc_defact.h | 21 ++++++ include/net/act_generic.h | 142 +++++++++++++++++++++++++++++++++++++++ include/net/tc_act/tc_defact.h | 13 ++++ net/sched/Kconfig | 10 +++ net/sched/Makefile | 11 +-- net/sched/simple.c | 107 +++++++++++++++++++++++++++++ 6 files changed, 299 insertions(+), 5 deletions(-) create mode 100644 include/linux/tc_act/tc_defact.h create mode 100644 include/net/act_generic.h create mode 100644 include/net/tc_act/tc_defact.h create mode 100644 net/sched/simple.c (limited to 'include') diff --git a/include/linux/tc_act/tc_defact.h b/include/linux/tc_act/tc_defact.h new file mode 100644 index 000000000000..964f473af0f0 --- /dev/null +++ b/include/linux/tc_act/tc_defact.h @@ -0,0 +1,21 @@ +#ifndef __LINUX_TC_DEF_H +#define __LINUX_TC_DEF_H + +#include + +struct tc_defact +{ + tc_gen; +}; + +enum +{ + TCA_DEF_UNSPEC, + TCA_DEF_TM, + TCA_DEF_PARMS, + TCA_DEF_DATA, + __TCA_DEF_MAX +}; +#define TCA_DEF_MAX (__TCA_DEF_MAX - 1) + +#endif diff --git a/include/net/act_generic.h b/include/net/act_generic.h new file mode 100644 index 000000000000..95b120781c14 --- /dev/null +++ b/include/net/act_generic.h @@ -0,0 +1,142 @@ +/* + * include/net/act_generic.h + * +*/ +#ifndef ACT_GENERIC_H +#define ACT_GENERIC_H +static inline int tcf_defact_release(struct tcf_defact *p, int bind) +{ + int ret = 0; + if (p) { + if (bind) { + p->bindcnt--; + } + p->refcnt--; + if (p->bindcnt <= 0 && p->refcnt <= 0) { + kfree(p->defdata); + tcf_hash_destroy(p); + ret = 1; + } + } + return ret; +} + +static inline int +alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) +{ + p->defdata = kmalloc(datalen, GFP_KERNEL); + if (p->defdata == NULL) + return -ENOMEM; + p->datalen = datalen; + memcpy(p->defdata, defdata, datalen); + return 0; +} + +static inline int +realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) +{ + /* safer to be just brute force for now */ + kfree(p->defdata); + return alloc_defdata(p, datalen, defdata); +} + +static inline int +tcf_defact_init(struct rtattr *rta, struct rtattr *est, + struct tc_action *a, int ovr, int bind) +{ + struct rtattr *tb[TCA_DEF_MAX]; + struct tc_defact *parm; + struct tcf_defact *p; + void *defdata; + u32 datalen = 0; + int ret = 0; + + if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0) + return -EINVAL; + + if (tb[TCA_DEF_PARMS - 1] == NULL || + RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm)) + return -EINVAL; + + parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]); + defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]); + if (defdata == NULL) + return -EINVAL; + + datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]); + if (datalen <= 0) + return -EINVAL; + + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) + return -ENOMEM; + + ret = alloc_defdata(p, datalen, defdata); + if (ret < 0) { + kfree(p); + return ret; + } + ret = ACT_P_CREATED; + } else { + if (!ovr) { + tcf_defact_release(p, bind); + return -EEXIST; + } + realloc_defdata(p, datalen, defdata); + } + + spin_lock_bh(&p->lock); + p->action = parm->action; + spin_unlock_bh(&p->lock); + if (ret == ACT_P_CREATED) + tcf_hash_insert(p); + return ret; +} + +static inline int tcf_defact_cleanup(struct tc_action *a, int bind) +{ + struct tcf_defact *p = PRIV(a, defact); + + if (p != NULL) + return tcf_defact_release(p, bind); + return 0; +} + +static inline int +tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +{ + unsigned char *b = skb->tail; + struct tc_defact opt; + struct tcf_defact *p = PRIV(a, defact); + struct tcf_t t; + + opt.index = p->index; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + opt.action = p->action; + RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); + RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata); + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); + RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t); + return skb->len; + +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +#define tca_use_default_ops \ + .dump = tcf_defact_dump, \ + .cleanup = tcf_defact_cleanup, \ + .init = tcf_defact_init, \ + .walk = tcf_generic_walker, \ + +#define tca_use_default_defines(name) \ + static u32 idx_gen; \ + static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \ + static DEFINE_RWLOCK(##name_lock); +#endif /* _NET_ACT_GENERIC_H */ diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h new file mode 100644 index 000000000000..463aa671f95d --- /dev/null +++ b/include/net/tc_act/tc_defact.h @@ -0,0 +1,13 @@ +#ifndef __NET_TC_DEF_H +#define __NET_TC_DEF_H + +#include + +struct tcf_defact +{ + tca_gen(defact); + u32 datalen; + void *defdata; +}; + +#endif diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 3d1d902dd1a1..9c118baed9dc 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -506,3 +506,13 @@ config NET_CLS_POLICE Say Y to support traffic policing (bandwidth limits). Needed for ingress and egress rate limiting. +config NET_ACT_SIMP + tristate "Simple action" + depends on NET_CLS_ACT + ---help--- + You must have new iproute2 to use this feature. + This adds a very simple action for demonstration purposes + The idea is to give action authors a basic example to look at. + All this action will do is print on the console the configured + policy string followed by _ then packet count. + diff --git a/net/sched/Makefile b/net/sched/Makefile index 431e55786efd..eb3fe583eba8 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -6,13 +6,14 @@ obj-y := sch_generic.o obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o obj-$(CONFIG_NET_CLS) += cls_api.o -obj-$(CONFIG_NET_CLS_ACT) += act_api.o +obj-$(CONFIG_NET_CLS_ACT) += act_api.o obj-$(CONFIG_NET_ACT_POLICE) += police.o obj-$(CONFIG_NET_CLS_POLICE) += police.o -obj-$(CONFIG_NET_ACT_GACT) += gact.o -obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o -obj-$(CONFIG_NET_ACT_IPT) += ipt.o -obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o +obj-$(CONFIG_NET_ACT_GACT) += gact.o +obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o +obj-$(CONFIG_NET_ACT_IPT) += ipt.o +obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o +obj-$(CONFIG_NET_ACT_SIMP) += simple.o obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o diff --git a/net/sched/simple.c b/net/sched/simple.c new file mode 100644 index 000000000000..b0d3d15848ad --- /dev/null +++ b/net/sched/simple.c @@ -0,0 +1,107 @@ +/* + * net/sched/simp.c Simple example of an action + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Jamal Hadi Salim (2005) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TCA_ACT_SIMP 22 + +/* XXX: Hide all these common elements under some macro + * probably +*/ +#include +#include + +/* use generic hash table with 8 buckets */ +#define MY_TAB_SIZE 8 +#define MY_TAB_MASK (MY_TAB_SIZE - 1) +static u32 idx_gen; +static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE]; +static DEFINE_RWLOCK(simp_lock); + +/* override the defaults */ +#define tcf_st tcf_defact +#define tc_st tc_defact +#define tcf_t_lock simp_lock +#define tcf_ht tcf_simp_ht + +#define CONFIG_NET_ACT_INIT 1 +#include +#include + +static int tcf_simp(struct sk_buff **pskb, struct tc_action *a) +{ + struct sk_buff *skb = *pskb; + struct tcf_defact *p = PRIV(a, defact); + + spin_lock(&p->lock); + p->tm.lastuse = jiffies; + p->bstats.bytes += skb->len; + p->bstats.packets++; + + /* print policy string followed by _ then packet count + * Example if this was the 3rd packet and the string was "hello" + * then it would look like "hello_3" (without quotes) + **/ + printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets); + spin_unlock(&p->lock); + return p->action; +} + +static struct tc_action_ops act_simp_ops = { + .kind = "simple", + .type = TCA_ACT_SIMP, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_simp, + tca_use_default_ops +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2005)"); +MODULE_DESCRIPTION("Simple example action"); +MODULE_LICENSE("GPL"); + +static int __init simp_init_module(void) +{ + int ret = tcf_register_action(&act_simp_ops); + if (!ret) + printk("Simple TC action Loaded\n"); + return ret; +} + +static void __exit simp_cleanup_module(void) +{ + tcf_unregister_action(&act_simp_ops); +} + +module_init(simp_init_module); +module_exit(simp_cleanup_module); -- cgit v1.2.3 From 0d3d077cd4f1154e63a9858e47fe3fb1ad0c03e5 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Apr 2005 20:16:19 -0700 Subject: [SELINUX]: Fix ipv6_skip_exthdr() invocation causing OOPS. The SELinux hooks invoke ipv6_skip_exthdr() with an incorrect length final argument. However, the length argument turns out to be superfluous. I was just reading ipv6_skip_exthdr and it occured to me that we can get rid of len altogether. The only place where len is used is to check whether the skb has two bytes for ipv6_opt_hdr. This check is done by skb_header_pointer/skb_copy_bits anyway. Now it might appear that we've made the code slower by deferring the check to skb_copy_bits. However, this check should not trigger in the common case so this is OK. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/net/ipv6.h | 2 +- net/ipv6/exthdrs_core.c | 11 ++++------- net/ipv6/icmp.c | 4 ++-- security/selinux/hooks.c | 3 +-- 4 files changed, 8 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 87c45cbfbaf6..771b47e30f86 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -416,7 +416,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb, u8 *proto); extern int ipv6_skip_exthdr(const struct sk_buff *, int start, - u8 *nexthdrp, int len); + u8 *nexthdrp); extern int ipv6_ext_hdr(u8 nexthdr); diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 6dda815c013f..315bc1fbec3f 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -41,8 +41,8 @@ int ipv6_ext_hdr(u8 nexthdr) * when Linux implements ESP (and maybe AUTH) headers. * --AK * - * This function parses (probably truncated) exthdr set "hdr" - * of length "len". "nexthdrp" initially points to some place, + * This function parses (probably truncated) exthdr set "hdr". + * "nexthdrp" initially points to some place, * where type of the first header can be found. * * It skips all well-known exthdrs, and returns pointer to the start @@ -63,7 +63,7 @@ int ipv6_ext_hdr(u8 nexthdr) * --ANK (980726) */ -int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len) +int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) { u8 nexthdr = *nexthdrp; @@ -71,13 +71,11 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len struct ipv6_opt_hdr _hdr, *hp; int hdrlen; - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return -1; if (nexthdr == NEXTHDR_NONE) return -1; hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); if (hp == NULL) - BUG(); + return -1; if (nexthdr == NEXTHDR_FRAGMENT) { unsigned short _frag_off, *fp; fp = skb_header_pointer(skb, @@ -97,7 +95,6 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len hdrlen = ipv6_optlen(hp); nexthdr = hp->nexthdr; - len -= hdrlen; start += hdrlen; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 87b9082ceab2..8e0f569b883e 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -135,7 +135,7 @@ static int is_ineligible(struct sk_buff *skb) if (len < 0) return 1; - ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len); + ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr); if (ptr < 0) return 0; if (nexthdr == IPPROTO_ICMPV6) { @@ -514,7 +514,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info) nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; if (ipv6_ext_hdr(nexthdr)) { /* now skip over extension headers */ - inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr)); + inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); if (inner_offset<0) return; } else { diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2ae7d3cb8df4..0d378141c95a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2855,8 +2855,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad nexthdr = ip6->nexthdr; offset += sizeof(_ipv6h); - offset = ipv6_skip_exthdr(skb, offset, &nexthdr, - skb->tail - skb->head - offset); + offset = ipv6_skip_exthdr(skb, offset, &nexthdr); if (offset < 0) goto out; -- cgit v1.2.3 From 205a7edad99d68d57dfcbf9bdda1a6fb7c33169e Mon Sep 17 00:00:00 2001 From: Tom 'spot' Callaway Date: Sun, 24 Apr 2005 20:46:00 -0700 Subject: [SPARC]: Fix mxcc warning Peter Jones uncovered this one while we were debugging the framebuffer issues. There are some references to -1 in the mxcc asm code, which should be 0xffffffff. This patch gets rid of the -1s. Signed-off-by: Tom 'spot' Callaway Signed-off-by: David S. Miller --- include/asm-sparc/mxcc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-sparc/mxcc.h b/include/asm-sparc/mxcc.h index efe4e843122d..60ef9d6fe7bc 100644 --- a/include/asm-sparc/mxcc.h +++ b/include/asm-sparc/mxcc.h @@ -115,8 +115,8 @@ extern __inline__ unsigned long mxcc_get_creg(void) { unsigned long mxcc_control; - __asm__ __volatile__("set -1, %%g2\n\t" - "set -1, %%g3\n\t" + __asm__ __volatile__("set 0xffffffff, %%g2\n\t" + "set 0xffffffff, %%g3\n\t" "stda %%g2, [%1] %2\n\t" "lda [%3] %2, %0\n\t" : "=r" (mxcc_control) : -- cgit v1.2.3 From 9a59c1860d01b3dea9ab01d5cefb9d5c52042e6d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Apr 2005 21:04:02 -0700 Subject: [SPARC64]: Fix SMP build. Kill build failures in the SMP+!PREEMPT case introduced by Al Viro's spinlock.h changes. Signed-off-by: David S. Miller --- include/asm-sparc64/spinlock.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h index d1f91a4f24ae..db7581bdb531 100644 --- a/include/asm-sparc64/spinlock.h +++ b/include/asm-sparc64/spinlock.h @@ -44,7 +44,7 @@ typedef struct { #define spin_unlock_wait(lp) \ do { membar("#LoadLoad"); \ -} while(lp->lock) +} while((lp)->lock) static inline void _raw_spin_lock(spinlock_t *lock) { @@ -149,7 +149,7 @@ typedef struct { unsigned int break_lock; #endif } rwlock_t; -#define RW_LOCK_UNLOCKED {0,} +#define RW_LOCK_UNLOCKED (rwlock_t) {0,} #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0) static void inline __read_lock(rwlock_t *lock) -- cgit v1.2.3 From 9090e001f28de4bccae232f1b78e78fad5132ecb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Apr 2005 07:55:57 -0700 Subject: [PATCH] ppc user annotations: sigcontext sigcontext.regs is a userland pointer Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/ppc/kernel/signal.c | 2 +- include/asm-ppc/sigcontext.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c index 645eae19805c..d500f5ebc29c 100644 --- a/arch/ppc/kernel/signal.c +++ b/arch/ppc/kernel/signal.c @@ -632,7 +632,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) || __put_user(oldset->sig[0], &sc->oldmask) || __put_user(oldset->sig[1], &sc->_unused[3]) - || __put_user((struct pt_regs *)frame, &sc->regs) + || __put_user((struct pt_regs __user *)frame, &sc->regs) || __put_user(sig, &sc->signal)) goto badframe; diff --git a/include/asm-ppc/sigcontext.h b/include/asm-ppc/sigcontext.h index fc5e358c65f1..f82dcccdee1e 100644 --- a/include/asm-ppc/sigcontext.h +++ b/include/asm-ppc/sigcontext.h @@ -9,7 +9,7 @@ struct sigcontext { int signal; unsigned long handler; unsigned long oldmask; - struct pt_regs *regs; + struct pt_regs __user *regs; }; #endif -- cgit v1.2.3 From 92a11f9e7cb876e6cf9080e4a1642142cb9221b2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Apr 2005 07:55:57 -0700 Subject: [PATCH] ppc iomem annotations: ->io_base_virt * ->io_base_virt in struct pci_controller is iomem pointer. Marked as such. Most of the places that used it are already annotated to expect iomem. * places that did gratitious (and wrong) casts a-la isa_io_base = (unsigned long)ioremap(...); hose->io_base_virt = (void *)isa_io_base; turned into hose->io_base_virt = ioremap(...); isa_io_base = (unsigned long)hose->io_base_virt; * pci_bus_io_base() annotated as returning iomem pointer. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/ppc/kernel/pci.c | 2 +- arch/ppc/platforms/4xx/ebony.c | 5 ++--- arch/ppc/platforms/4xx/luan.c | 5 ++--- arch/ppc/platforms/4xx/ocotea.c | 5 ++--- arch/ppc/syslib/m8260_pci.c | 5 ++--- arch/ppc/syslib/mpc52xx_pci.c | 8 +++----- arch/ppc/syslib/ppc85xx_setup.c | 12 +++++------- include/asm-ppc/pci-bridge.h | 4 ++-- 8 files changed, 19 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 98f94b60204c..47a15306823a 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -1432,7 +1432,7 @@ pci_bus_to_hose(int bus) return NULL; } -void* +void __iomem * pci_bus_io_base(unsigned int bus) { struct pci_controller *hose; diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index f63bca83e757..55120c317f7d 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -210,9 +210,8 @@ ebony_setup_hose(void) hose->io_space.end = EBONY_PCI_UPPER_IO; hose->mem_space.start = EBONY_PCI_LOWER_MEM; hose->mem_space.end = EBONY_PCI_UPPER_MEM; - isa_io_base = - (unsigned long)ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE); - hose->io_base_virt = (void *)isa_io_base; + hose->io_base_virt = ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE); + isa_io_base = (unsigned long)hose->io_base_virt; setup_indirect_pci(hose, EBONY_PCI_CFGA_PLB32, diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c index 1df2339f1f6c..95359f748e7b 100644 --- a/arch/ppc/platforms/4xx/luan.c +++ b/arch/ppc/platforms/4xx/luan.c @@ -223,9 +223,8 @@ luan_setup_hose(struct pci_controller *hose, hose->io_space.end = LUAN_PCIX_UPPER_IO; hose->mem_space.start = lower_mem; hose->mem_space.end = upper_mem; - isa_io_base = - (unsigned long)ioremap64(pcix_io_base, PCIX_IO_SIZE); - hose->io_base_virt = (void *)isa_io_base; + hose->io_base_virt = ioremap64(pcix_io_base, PCIX_IO_SIZE); + isa_io_base = (unsigned long) hose->io_base_virt; setup_indirect_pci(hose, cfga, cfgd); hose->set_cfg_type = 1; diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 28de707434f1..5f82a6bc7046 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -227,9 +227,8 @@ ocotea_setup_hose(void) hose->io_space.end = OCOTEA_PCI_UPPER_IO; hose->mem_space.start = OCOTEA_PCI_LOWER_MEM; hose->mem_space.end = OCOTEA_PCI_UPPER_MEM; - isa_io_base = - (unsigned long)ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE); - hose->io_base_virt = (void *)isa_io_base; + hose->io_base_virt = ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE); + isa_io_base = (unsigned long) hose->io_base_virt; setup_indirect_pci(hose, OCOTEA_PCI_CFGA_PLB32, diff --git a/arch/ppc/syslib/m8260_pci.c b/arch/ppc/syslib/m8260_pci.c index bd564fb35ab6..057cc3f8ff37 100644 --- a/arch/ppc/syslib/m8260_pci.c +++ b/arch/ppc/syslib/m8260_pci.c @@ -171,10 +171,9 @@ void __init m8260_find_bridges(void) m8260_setup_pci(hose); hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET; - isa_io_base = - (unsigned long) ioremap(MPC826x_PCI_IO_BASE, + hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE, MPC826x_PCI_IO_SIZE); - hose->io_base_virt = (void *) isa_io_base; + isa_io_base = (unsigned long) hose->io_base_virt; /* setup resources */ pci_init_resource(&hose->mem_resources[0], diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c index c723efd954a6..59cf3e8bd1a0 100644 --- a/arch/ppc/syslib/mpc52xx_pci.c +++ b/arch/ppc/syslib/mpc52xx_pci.c @@ -205,13 +205,11 @@ mpc52xx_find_bridges(void) hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET; - isa_io_base = - (unsigned long) ioremap(MPC52xx_PCI_IO_BASE, - MPC52xx_PCI_IO_SIZE); - hose->io_base_virt = (void *) isa_io_base; + hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE); + isa_io_base = (unsigned long) hose->io_base_virt; hose->cfg_addr = &pci_regs->car; - hose->cfg_data = (void __iomem *) isa_io_base; + hose->cfg_data = hose->io_base_virt; /* Setup resources */ pci_init_resource(&hose->mem_resources[0], diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index 81f1968c3269..152c3ef1312a 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -280,16 +280,14 @@ mpc85xx_setup_hose(void) hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO; hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE; #ifdef CONFIG_85xx_PCI2 - isa_io_base = - (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE, + hose_a->io_base_virt = ioremap(MPC85XX_PCI1_IO_BASE, MPC85XX_PCI1_IO_SIZE + MPC85XX_PCI2_IO_SIZE); #else - isa_io_base = - (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE, + hose_a->io_base_virt = ioremap(MPC85XX_PCI1_IO_BASE, MPC85XX_PCI1_IO_SIZE); #endif - hose_a->io_base_virt = (void *) isa_io_base; + isa_io_base = (unsigned long)hose_a->io_base_virt; /* setup resources */ pci_init_resource(&hose_a->mem_resources[0], @@ -329,8 +327,8 @@ mpc85xx_setup_hose(void) hose_b->io_space.start = MPC85XX_PCI2_LOWER_IO; hose_b->io_space.end = MPC85XX_PCI2_UPPER_IO; hose_b->io_base_phys = MPC85XX_PCI2_IO_BASE; - hose_b->io_base_virt = (void *) isa_io_base + MPC85XX_PCI1_IO_SIZE; - + hose_b->io_base_virt = hose_a->io_base_virt + MPC85XX_PCI1_IO_SIZE; + /* setup resources */ pci_init_resource(&hose_b->mem_resources[0], MPC85XX_PCI2_LOWER_MEM, diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h index 78e9be619f14..ffa423456c2b 100644 --- a/include/asm-ppc/pci-bridge.h +++ b/include/asm-ppc/pci-bridge.h @@ -12,7 +12,7 @@ struct pci_controller; * pci_io_base returns the memory address at which you can access * the I/O space for PCI bus number `bus' (or NULL on error). */ -extern void *pci_bus_io_base(unsigned int bus); +extern void __iomem *pci_bus_io_base(unsigned int bus); extern unsigned long pci_bus_io_base_phys(unsigned int bus); extern unsigned long pci_bus_mem_base_phys(unsigned int bus); @@ -48,7 +48,7 @@ struct pci_controller { int last_busno; int bus_offset; - void *io_base_virt; + void __iomem *io_base_virt; unsigned long io_base_phys; /* Some machines (PReP) have a non 1:1 mapping of -- cgit v1.2.3 From a3342421363642d03b2ae3ecd27e3041de043e99 Mon Sep 17 00:00:00 2001 From: Lucas Correia Villa Real Date: Mon, 25 Apr 2005 18:36:50 +0100 Subject: [PATCH] ARM: 2640/1: Adds DRAM/BANKSIZE_MASK definitions for S3C2400 Patch from Lucas Correia Villa Real Adds DRAM refresh definitions and sets the BANKSIZE_MASK for the S3C2400 on include/asm-arm/arch-s3c2400/regs-mem.h Signed-off-by: Lucas Correia Villa Real Signed-off-by: Ben Dooks Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/regs-mem.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h index 1a1328ac0d79..a2d7d0cec042 100644 --- a/include/asm-arm/arch-s3c2410/regs-mem.h +++ b/include/asm-arm/arch-s3c2410/regs-mem.h @@ -12,6 +12,7 @@ * Changelog: * 29-Sep-2004 BJD Initial include for Linux * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + * 04-Apr-2005 LCVR Added S3C2400 DRAM/BANKSIZE_MASK definitions * */ @@ -183,6 +184,12 @@ #define S3C2410_REFRESH_TRP_3clk (1<<20) #define S3C2410_REFRESH_TRP_4clk (2<<20) +#define S3C2400_REFRESH_DRAM_TRP_MASK (3<<20) +#define S3C2400_REFRESH_DRAM_TRP_1_5clk (0<<20) +#define S3C2400_REFRESH_DRAM_TRP_2_5clk (1<<20) +#define S3C2400_REFRESH_DRAM_TRP_3_5clk (2<<20) +#define S3C2400_REFRESH_DRAM_TRP_4_5clk (3<<20) + #define S3C2410_REFRESH_TSRC_MASK (3<<18) #define S3C2410_REFRESH_TSRC_4clk (0<<18) #define S3C2410_REFRESH_TSRC_5clk (1<<18) @@ -205,6 +212,7 @@ #define S3C2410_BANKSIZE_4M (0x5 << 0) #define S3C2410_BANKSIZE_2M (0x4 << 0) #define S3C2410_BANKSIZE_MASK (0x7 << 0) +#define S3C2400_BANKSIZE_MASK (0x4 << 0) #define S3C2410_BANKSIZE_SCLK_EN (1<<4) #define S3C2410_BANKSIZE_SCKE_EN (1<<5) #define S3C2410_BANKSIZE_BURST (1<<7) -- cgit v1.2.3 From b7ebcc108a1754a1d044b49c0acf977a7e86ae71 Mon Sep 17 00:00:00 2001 From: Lucas Correia Villa Real Date: Mon, 25 Apr 2005 18:40:31 +0100 Subject: [PATCH] ARM: 2641/1: Adds S3C2400_SPPIN_nCS to arch-s3c2410/regs-spi.h Patch from Lucas Correia Villa Real Adds a define to the SPI Card Select bit on the S3C2400 into include/asm-arm/arch-s3c2410/regs-spi.h Signed-off-by: Lucas Correia Villa Real Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/regs-spi.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/asm-arm/arch-s3c2410/regs-spi.h b/include/asm-arm/arch-s3c2410/regs-spi.h index cb502a88158b..338217858c73 100644 --- a/include/asm-arm/arch-s3c2410/regs-spi.h +++ b/include/asm-arm/arch-s3c2410/regs-spi.h @@ -12,6 +12,7 @@ * 20-04-2004 KF Created file * 04-10-2004 BJD Removed VA address (no longer mapped) * tidied file for submission + * 03-04-2005 LCVR Added S3C2400_SPPIN_nCS definition */ #ifndef __ASM_ARCH_REGS_SPI_H @@ -46,6 +47,7 @@ #define S3C2410_SPPIN_ENMUL (1<<2) /* Multi Master Error detect */ #define S3C2410_SPPIN_RESERVED (1<<1) +#define S3C2400_SPPIN_nCS (1<<1) /* SPI Card Select */ #define S3C2410_SPPIN_KEEP (1<<0) /* Master Out keep */ -- cgit v1.2.3 From 9b08ebd167a3f3812131a54512f92c3c6738ad03 Mon Sep 17 00:00:00 2001 From: Mark Maule Date: Mon, 25 Apr 2005 11:32:16 -0700 Subject: [IA64-SGI] sn2-move-pci-headers.patch Move a couple of headers out of arch/ia64/sn/include/pci and into include/asm-ia64/sn. Signed-off-by: Mark Maule Signed-off-by: Tony Luck --- arch/ia64/sn/include/pci/pcibus_provider_defs.h | 51 ---------------------- arch/ia64/sn/include/pci/pcidev.h | 58 ------------------------- arch/ia64/sn/kernel/io_init.c | 4 +- arch/ia64/sn/kernel/irq.c | 4 +- arch/ia64/sn/pci/pci_dma.c | 4 +- arch/ia64/sn/pci/pcibr/pcibr_ate.c | 4 +- arch/ia64/sn/pci/pcibr/pcibr_dma.c | 4 +- arch/ia64/sn/pci/pcibr/pcibr_provider.c | 4 +- arch/ia64/sn/pci/pcibr/pcibr_reg.c | 4 +- include/asm-ia64/sn/pcibus_provider_defs.h | 51 ++++++++++++++++++++++ include/asm-ia64/sn/pcidev.h | 58 +++++++++++++++++++++++++ 11 files changed, 123 insertions(+), 123 deletions(-) delete mode 100644 arch/ia64/sn/include/pci/pcibus_provider_defs.h delete mode 100644 arch/ia64/sn/include/pci/pcidev.h create mode 100644 include/asm-ia64/sn/pcibus_provider_defs.h create mode 100644 include/asm-ia64/sn/pcidev.h (limited to 'include') diff --git a/arch/ia64/sn/include/pci/pcibus_provider_defs.h b/arch/ia64/sn/include/pci/pcibus_provider_defs.h deleted file mode 100644 index f546b4ece33c..000000000000 --- a/arch/ia64/sn/include/pci/pcibus_provider_defs.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. - */ -#ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H -#define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H - -/* - * SN pci asic types. Do not ever renumber these or reuse values. The - * values must agree with what prom thinks they are. - */ - -#define PCIIO_ASIC_TYPE_UNKNOWN 0 -#define PCIIO_ASIC_TYPE_PPB 1 -#define PCIIO_ASIC_TYPE_PIC 2 -#define PCIIO_ASIC_TYPE_TIOCP 3 - -#define PCIIO_ASIC_MAX_TYPES 4 - -/* - * Common pciio bus provider data. There should be one of these as the - * first field in any pciio based provider soft structure (e.g. pcibr_soft - * tioca_soft, etc). - */ - -struct pcibus_bussoft { - uint32_t bs_asic_type; /* chipset type */ - uint32_t bs_xid; /* xwidget id */ - uint64_t bs_persist_busnum; /* Persistent Bus Number */ - uint64_t bs_legacy_io; /* legacy io pio addr */ - uint64_t bs_legacy_mem; /* legacy mem pio addr */ - uint64_t bs_base; /* widget base */ - struct xwidget_info *bs_xwidget_info; -}; - -/* - * SN pci bus indirection - */ - -struct sn_pcibus_provider { - dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t); - dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t); - void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); - void * (*bus_fixup)(struct pcibus_bussoft *); -}; - -extern struct sn_pcibus_provider *sn_pci_provider[]; -#endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */ diff --git a/arch/ia64/sn/include/pci/pcidev.h b/arch/ia64/sn/include/pci/pcidev.h deleted file mode 100644 index ed4031d80811..000000000000 --- a/arch/ia64/sn/include/pci/pcidev.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. - */ -#ifndef _ASM_IA64_SN_PCI_PCIDEV_H -#define _ASM_IA64_SN_PCI_PCIDEV_H - -#include - -extern struct sn_irq_info **sn_irq; - -#define SN_PCIDEV_INFO(pci_dev) \ - ((struct pcidev_info *)(pci_dev)->sysdata) - -/* - * Given a pci_bus, return the sn pcibus_bussoft struct. Note that - * this only works for root busses, not for busses represented by PPB's. - */ - -#define SN_PCIBUS_BUSSOFT(pci_bus) \ - ((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data)) - -/* - * Given a struct pci_dev, return the sn pcibus_bussoft struct. Note - * that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due - * due to possible PPB's in the path. - */ - -#define SN_PCIDEV_BUSSOFT(pci_dev) \ - (SN_PCIDEV_INFO(pci_dev)->pdi_host_pcidev_info->pdi_pcibus_info) - -#define SN_PCIDEV_BUSPROVIDER(pci_dev) \ - (SN_PCIDEV_INFO(pci_dev)->pdi_provider) - -#define PCIIO_BUS_NONE 255 /* bus 255 reserved */ -#define PCIIO_SLOT_NONE 255 -#define PCIIO_FUNC_NONE 255 -#define PCIIO_VENDOR_ID_NONE (-1) - -struct pcidev_info { - uint64_t pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */ - uint64_t pdi_slot_host_handle; /* Bus and devfn Host pci_dev */ - - struct pcibus_bussoft *pdi_pcibus_info; /* Kernel common bus soft */ - struct pcidev_info *pdi_host_pcidev_info; /* Kernel Host pci_dev */ - struct pci_dev *pdi_linux_pcidev; /* Kernel pci_dev */ - - struct sn_irq_info *pdi_sn_irq_info; - struct sn_pcibus_provider *pdi_provider; /* sn pci ops */ -}; - -extern void sn_irq_fixup(struct pci_dev *pci_dev, - struct sn_irq_info *sn_irq_info); - -#endif /* _ASM_IA64_SN_PCI_PCIDEV_H */ diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 3e5e4a901302..9f9d0464f72c 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -11,8 +11,8 @@ #include #include #include -#include "pci/pcibus_provider_defs.h" -#include "pci/pcidev.h" +#include +#include #include "pci/pcibr_provider.h" #include "xtalk/xwidgetdev.h" #include diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 3be44724f6c8..b52d32975f2b 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -13,8 +13,8 @@ #include #include #include "xtalk/xwidgetdev.h" -#include "pci/pcibus_provider_defs.h" -#include "pci/pcidev.h" +#include +#include #include "pci/pcibr_provider.h" #include #include diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index c2b92b94c563..5da9bdbde7cb 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -12,8 +12,8 @@ #include #include #include -#include "pci/pcibus_provider_defs.h" -#include "pci/pcidev.h" +#include +#include #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) #define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG)) diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index 9d6854666f9b..0e47bce85f2d 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c @@ -8,8 +8,8 @@ #include #include -#include "pci/pcibus_provider_defs.h" -#include "pci/pcidev.h" +#include +#include #include "pci/pcibr_provider.h" int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 3c305f46417f..c90685985d81 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -12,8 +12,8 @@ #include #include "xtalk/xwidgetdev.h" #include "xtalk/hubdev.h" -#include "pci/pcibus_provider_defs.h" -#include "pci/pcidev.h" +#include +#include #include "pci/tiocp.h" #include "pci/pic.h" #include "pci/pcibr_provider.h" diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 539ab1fdab21..3893999d23d8 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -13,8 +13,8 @@ #include "xtalk/xwidgetdev.h" #include #include "xtalk/hubdev.h" -#include "pci/pcibus_provider_defs.h" -#include "pci/pcidev.h" +#include +#include #include "pci/pcibr_provider.h" #include diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c index 74a74a7d2a13..865c11c3b50a 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c @@ -8,8 +8,8 @@ #include #include -#include "pci/pcibus_provider_defs.h" -#include "pci/pcidev.h" +#include +#include #include "pci/tiocp.h" #include "pci/pic.h" #include "pci/pcibr_provider.h" diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h new file mode 100644 index 000000000000..f546b4ece33c --- /dev/null +++ b/include/asm-ia64/sn/pcibus_provider_defs.h @@ -0,0 +1,51 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + */ +#ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H +#define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H + +/* + * SN pci asic types. Do not ever renumber these or reuse values. The + * values must agree with what prom thinks they are. + */ + +#define PCIIO_ASIC_TYPE_UNKNOWN 0 +#define PCIIO_ASIC_TYPE_PPB 1 +#define PCIIO_ASIC_TYPE_PIC 2 +#define PCIIO_ASIC_TYPE_TIOCP 3 + +#define PCIIO_ASIC_MAX_TYPES 4 + +/* + * Common pciio bus provider data. There should be one of these as the + * first field in any pciio based provider soft structure (e.g. pcibr_soft + * tioca_soft, etc). + */ + +struct pcibus_bussoft { + uint32_t bs_asic_type; /* chipset type */ + uint32_t bs_xid; /* xwidget id */ + uint64_t bs_persist_busnum; /* Persistent Bus Number */ + uint64_t bs_legacy_io; /* legacy io pio addr */ + uint64_t bs_legacy_mem; /* legacy mem pio addr */ + uint64_t bs_base; /* widget base */ + struct xwidget_info *bs_xwidget_info; +}; + +/* + * SN pci bus indirection + */ + +struct sn_pcibus_provider { + dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t); + dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t); + void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); + void * (*bus_fixup)(struct pcibus_bussoft *); +}; + +extern struct sn_pcibus_provider *sn_pci_provider[]; +#endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */ diff --git a/include/asm-ia64/sn/pcidev.h b/include/asm-ia64/sn/pcidev.h new file mode 100644 index 000000000000..ed4031d80811 --- /dev/null +++ b/include/asm-ia64/sn/pcidev.h @@ -0,0 +1,58 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + */ +#ifndef _ASM_IA64_SN_PCI_PCIDEV_H +#define _ASM_IA64_SN_PCI_PCIDEV_H + +#include + +extern struct sn_irq_info **sn_irq; + +#define SN_PCIDEV_INFO(pci_dev) \ + ((struct pcidev_info *)(pci_dev)->sysdata) + +/* + * Given a pci_bus, return the sn pcibus_bussoft struct. Note that + * this only works for root busses, not for busses represented by PPB's. + */ + +#define SN_PCIBUS_BUSSOFT(pci_bus) \ + ((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data)) + +/* + * Given a struct pci_dev, return the sn pcibus_bussoft struct. Note + * that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due + * due to possible PPB's in the path. + */ + +#define SN_PCIDEV_BUSSOFT(pci_dev) \ + (SN_PCIDEV_INFO(pci_dev)->pdi_host_pcidev_info->pdi_pcibus_info) + +#define SN_PCIDEV_BUSPROVIDER(pci_dev) \ + (SN_PCIDEV_INFO(pci_dev)->pdi_provider) + +#define PCIIO_BUS_NONE 255 /* bus 255 reserved */ +#define PCIIO_SLOT_NONE 255 +#define PCIIO_FUNC_NONE 255 +#define PCIIO_VENDOR_ID_NONE (-1) + +struct pcidev_info { + uint64_t pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */ + uint64_t pdi_slot_host_handle; /* Bus and devfn Host pci_dev */ + + struct pcibus_bussoft *pdi_pcibus_info; /* Kernel common bus soft */ + struct pcidev_info *pdi_host_pcidev_info; /* Kernel Host pci_dev */ + struct pci_dev *pdi_linux_pcidev; /* Kernel pci_dev */ + + struct sn_irq_info *pdi_sn_irq_info; + struct sn_pcibus_provider *pdi_provider; /* sn pci ops */ +}; + +extern void sn_irq_fixup(struct pci_dev *pci_dev, + struct sn_irq_info *sn_irq_info); + +#endif /* _ASM_IA64_SN_PCI_PCIDEV_H */ -- cgit v1.2.3 From 9c90bdde77f7b7a42f7ebb900275d459ce2bac05 Mon Sep 17 00:00:00 2001 From: Mark Maule Date: Mon, 25 Apr 2005 11:35:54 -0700 Subject: [IA64-SGI] altix: tioca chip driver (agp) Provide a driver for the altix TIOCA AGP chipset. An agpgart backend will be provided as a separate patch. Signed-off-by: Mark Maule Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/io_init.c | 2 + arch/ia64/sn/pci/Makefile | 2 +- arch/ia64/sn/pci/tioca_provider.c | 668 +++++++++++++++++++++++++++++ include/asm-ia64/sn/pcibus_provider_defs.h | 3 +- include/asm-ia64/sn/tioca.h | 596 +++++++++++++++++++++++++ include/asm-ia64/sn/tioca_provider.h | 206 +++++++++ 6 files changed, 1475 insertions(+), 2 deletions(-) create mode 100644 arch/ia64/sn/pci/tioca_provider.c create mode 100644 include/asm-ia64/sn/tioca.h create mode 100644 include/asm-ia64/sn/tioca_provider.h (limited to 'include') diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 9f9d0464f72c..18160a06a8c9 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -19,6 +19,7 @@ #include "xtalk/hubdev.h" #include #include +#include char master_baseio_wid; nasid_t master_nasid = INVALID_NASID; /* Partition Master */ @@ -393,6 +394,7 @@ static int __init sn_pci_init(void) sn_pci_provider[i] = &sn_pci_default_provider; pcibr_init_provider(); + tioca_init_provider(); /* * This is needed to avoid bounce limit checks in the blk layer diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile index b5dca0097a8e..2f915bce25f9 100644 --- a/arch/ia64/sn/pci/Makefile +++ b/arch/ia64/sn/pci/Makefile @@ -7,4 +7,4 @@ # # Makefile for the sn pci general routines. -obj-y := pci_dma.o pcibr/ +obj-y := pci_dma.o tioca_provider.o pcibr/ diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c new file mode 100644 index 000000000000..2234d61cdd4b --- /dev/null +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -0,0 +1,668 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +uint32_t tioca_gart_found; +EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */ + +LIST_HEAD(tioca_list); +EXPORT_SYMBOL(tioca_list); /* used by agp-sgi */ + +static int tioca_gart_init(struct tioca_kernel *); + +/** + * tioca_gart_init - Initialize SGI TIOCA GART + * @tioca_common: ptr to common prom/kernel struct identifying the + * + * If the indicated tioca has devices present, initialize its associated + * GART MMR's and kernel memory. + */ +static int +tioca_gart_init(struct tioca_kernel *tioca_kern) +{ + uint64_t ap_reg; + uint64_t offset; + struct page *tmp; + struct tioca_common *tioca_common; + volatile struct tioca *ca_base; + + tioca_common = tioca_kern->ca_common; + ca_base = (struct tioca *)tioca_common->ca_common.bs_base; + + if (list_empty(tioca_kern->ca_devices)) + return 0; + + ap_reg = 0; + + /* + * Validate aperature size + */ + + switch (CA_APERATURE_SIZE >> 20) { + case 4: + ap_reg |= (0x3ff << CA_GART_AP_SIZE_SHFT); /* 4MB */ + break; + case 8: + ap_reg |= (0x3fe << CA_GART_AP_SIZE_SHFT); /* 8MB */ + break; + case 16: + ap_reg |= (0x3fc << CA_GART_AP_SIZE_SHFT); /* 16MB */ + break; + case 32: + ap_reg |= (0x3f8 << CA_GART_AP_SIZE_SHFT); /* 32 MB */ + break; + case 64: + ap_reg |= (0x3f0 << CA_GART_AP_SIZE_SHFT); /* 64 MB */ + break; + case 128: + ap_reg |= (0x3e0 << CA_GART_AP_SIZE_SHFT); /* 128 MB */ + break; + case 256: + ap_reg |= (0x3c0 << CA_GART_AP_SIZE_SHFT); /* 256 MB */ + break; + case 512: + ap_reg |= (0x380 << CA_GART_AP_SIZE_SHFT); /* 512 MB */ + break; + case 1024: + ap_reg |= (0x300 << CA_GART_AP_SIZE_SHFT); /* 1GB */ + break; + case 2048: + ap_reg |= (0x200 << CA_GART_AP_SIZE_SHFT); /* 2GB */ + break; + case 4096: + ap_reg |= (0x000 << CA_GART_AP_SIZE_SHFT); /* 4 GB */ + break; + default: + printk(KERN_ERR "%s: Invalid CA_APERATURE_SIZE " + "0x%lx\n", __FUNCTION__, (ulong) CA_APERATURE_SIZE); + return -1; + } + + /* + * Set up other aperature parameters + */ + + if (PAGE_SIZE >= 16384) { + tioca_kern->ca_ap_pagesize = 16384; + ap_reg |= CA_GART_PAGE_SIZE; + } else { + tioca_kern->ca_ap_pagesize = 4096; + } + + tioca_kern->ca_ap_size = CA_APERATURE_SIZE; + tioca_kern->ca_ap_bus_base = CA_APERATURE_BASE; + tioca_kern->ca_gart_entries = + tioca_kern->ca_ap_size / tioca_kern->ca_ap_pagesize; + + ap_reg |= (CA_GART_AP_ENB_AGP | CA_GART_AP_ENB_PCI); + ap_reg |= tioca_kern->ca_ap_bus_base; + + /* + * Allocate and set up the GART + */ + + tioca_kern->ca_gart_size = tioca_kern->ca_gart_entries * sizeof(u64); + tmp = + alloc_pages_node(tioca_kern->ca_closest_node, + GFP_KERNEL | __GFP_ZERO, + get_order(tioca_kern->ca_gart_size)); + + if (!tmp) { + printk(KERN_ERR "%s: Could not allocate " + "%lu bytes (order %d) for GART\n", + __FUNCTION__, + tioca_kern->ca_gart_size, + get_order(tioca_kern->ca_gart_size)); + return -ENOMEM; + } + + tioca_kern->ca_gart = page_address(tmp); + tioca_kern->ca_gart_coretalk_addr = + PHYS_TO_TIODMA(virt_to_phys(tioca_kern->ca_gart)); + + /* + * Compute PCI/AGP convenience fields + */ + + offset = CA_PCI32_MAPPED_BASE - CA_APERATURE_BASE; + tioca_kern->ca_pciap_base = CA_PCI32_MAPPED_BASE; + tioca_kern->ca_pciap_size = CA_PCI32_MAPPED_SIZE; + tioca_kern->ca_pcigart_start = offset / tioca_kern->ca_ap_pagesize; + tioca_kern->ca_pcigart_base = + tioca_kern->ca_gart_coretalk_addr + offset; + tioca_kern->ca_pcigart = + &tioca_kern->ca_gart[tioca_kern->ca_pcigart_start]; + tioca_kern->ca_pcigart_entries = + tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize; + tioca_kern->ca_pcigart_pagemap = + kcalloc(1, tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL); + if (!tioca_kern->ca_pcigart_pagemap) { + free_pages((unsigned long)tioca_kern->ca_gart, + get_order(tioca_kern->ca_gart_size)); + return -1; + } + + offset = CA_AGP_MAPPED_BASE - CA_APERATURE_BASE; + tioca_kern->ca_gfxap_base = CA_AGP_MAPPED_BASE; + tioca_kern->ca_gfxap_size = CA_AGP_MAPPED_SIZE; + tioca_kern->ca_gfxgart_start = offset / tioca_kern->ca_ap_pagesize; + tioca_kern->ca_gfxgart_base = + tioca_kern->ca_gart_coretalk_addr + offset; + tioca_kern->ca_gfxgart = + &tioca_kern->ca_gart[tioca_kern->ca_gfxgart_start]; + tioca_kern->ca_gfxgart_entries = + tioca_kern->ca_gfxap_size / tioca_kern->ca_ap_pagesize; + + /* + * various control settings: + * use agp op-combining + * use GET semantics to fetch memory + * participate in coherency domain + * prefetch TLB entries + */ + + ca_base->ca_control1 |= CA_AGPDMA_OP_ENB_COMBDELAY; /* PV895469 ? */ + ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM); + ca_base->ca_control2 |= (0x2ull << CA_GART_MEM_PARAM_SHFT); + tioca_kern->ca_gart_iscoherent = 1; + ca_base->ca_control2 |= + (CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB); + + /* + * Unmask GART fetch error interrupts. Clear residual errors first. + */ + + ca_base->ca_int_status_alias = CA_GART_FETCH_ERR; + ca_base->ca_mult_error_alias = CA_GART_FETCH_ERR; + ca_base->ca_int_mask &= ~CA_GART_FETCH_ERR; + + /* + * Program the aperature and gart registers in TIOCA + */ + + ca_base->ca_gart_aperature = ap_reg; + ca_base->ca_gart_ptr_table = tioca_kern->ca_gart_coretalk_addr | 1; + + return 0; +} + +/** + * tioca_fastwrite_enable - enable AGP FW for a tioca and its functions + * @tioca_kernel: structure representing the CA + * + * Given a CA, scan all attached functions making sure they all support + * FastWrite. If so, enable FastWrite for all functions and the CA itself. + */ + +void +tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) +{ + int cap_ptr; + uint64_t ca_control1; + uint32_t reg; + struct tioca *tioca_base; + struct pci_dev *pdev; + struct tioca_common *common; + + common = tioca_kern->ca_common; + + /* + * Scan all vga controllers on this bus making sure they all + * suport FW. If not, return. + */ + + list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) { + if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8)) + continue; + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return; /* no AGP CAP means no FW */ + + pci_read_config_dword(pdev, cap_ptr + PCI_AGP_STATUS, ®); + if (!(reg & PCI_AGP_STATUS_FW)) + return; /* function doesn't support FW */ + } + + /* + * Set fw for all vga fn's + */ + + list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) { + if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8)) + continue; + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + pci_read_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, ®); + reg |= PCI_AGP_COMMAND_FW; + pci_write_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, reg); + } + + /* + * Set ca's fw to match + */ + + tioca_base = (struct tioca *)common->ca_common.bs_base; + ca_control1 = tioca_base->ca_control1; + ca_control1 |= CA_AGP_FW_ENABLE; + tioca_base->ca_control1 = ca_control1; +} + +EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */ + +/** + * tioca_dma_d64 - create a DMA mapping using 64-bit direct mode + * @paddr: system physical address + * + * Map @paddr into 64-bit CA bus space. No device context is necessary. + * Bits 53:0 come from the coretalk address. We just need to mask in the + * following optional bits of the 64-bit pci address: + * + * 63:60 - Coretalk Packet Type - 0x1 for Mem Get/Put (coherent) + * 0x2 for PIO (non-coherent) + * We will always use 0x1 + * 55:55 - Swap bytes Currently unused + */ +static uint64_t +tioca_dma_d64(unsigned long paddr) +{ + dma_addr_t bus_addr; + + bus_addr = PHYS_TO_TIODMA(paddr); + + BUG_ON(!bus_addr); + BUG_ON(bus_addr >> 54); + + /* Set upper nibble to Cache Coherent Memory op */ + bus_addr |= (1UL << 60); + + return bus_addr; +} + +/** + * tioca_dma_d48 - create a DMA mapping using 48-bit direct mode + * @pdev: linux pci_dev representing the function + * @paddr: system physical address + * + * Map @paddr into 64-bit bus space of the CA associated with @pcidev_info. + * + * The CA agp 48 bit direct address falls out as follows: + * + * When direct mapping AGP addresses, the 48 bit AGP address is + * constructed as follows: + * + * [47:40] - Low 8 bits of the page Node ID extracted from coretalk + * address [47:40]. The upper 8 node bits are fixed + * and come from the xxx register bits [5:0] + * [39:38] - Chiplet ID extracted from coretalk address [39:38] + * [37:00] - node offset extracted from coretalk address [37:00] + * + * Since the node id in general will be non-zero, and the chiplet id + * will always be non-zero, it follows that the device must support + * a dma mask of at least 0xffffffffff (40 bits) to target node 0 + * and in general should be 0xffffffffffff (48 bits) to target nodes + * up to 255. Nodes above 255 need the support of the xxx register, + * and so a given CA can only directly target nodes in the range + * xxx - xxx+255. + */ +static uint64_t +tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) +{ + struct tioca_common *tioca_common; + struct tioca *ca_base; + uint64_t ct_addr; + dma_addr_t bus_addr; + uint32_t node_upper; + uint64_t agp_dma_extn; + struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); + + tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; + ca_base = (struct tioca *)tioca_common->ca_common.bs_base; + + ct_addr = PHYS_TO_TIODMA(paddr); + if (!ct_addr) + return 0; + + bus_addr = (dma_addr_t) (ct_addr & 0xffffffffffff); + node_upper = ct_addr >> 48; + + if (node_upper > 64) { + printk(KERN_ERR "%s: coretalk addr 0x%p node id out " + "of range\n", __FUNCTION__, (void *)ct_addr); + return 0; + } + + agp_dma_extn = ca_base->ca_agp_dma_addr_extn; + if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) { + printk(KERN_ERR "%s: coretalk upper node (%u) " + "mismatch with ca_agp_dma_addr_extn (%lu)\n", + __FUNCTION__, + node_upper, (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)); + return 0; + } + + return bus_addr; +} + +/** + * tioca_dma_mapped - create a DMA mapping using a CA GART + * @pdev: linux pci_dev representing the function + * @paddr: host physical address to map + * @req_size: len (bytes) to map + * + * Map @paddr into CA address space using the GART mechanism. The mapped + * dma_addr_t is guarenteed to be contiguous in CA bus space. + */ +static dma_addr_t +tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size) +{ + int i, ps, ps_shift, entry, entries, mapsize, last_entry; + uint64_t xio_addr, end_xio_addr; + struct tioca_common *tioca_common; + struct tioca_kernel *tioca_kern; + dma_addr_t bus_addr = 0; + struct tioca_dmamap *ca_dmamap; + void *map; + unsigned long flags; + struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);; + + tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; + tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private; + + xio_addr = PHYS_TO_TIODMA(paddr); + if (!xio_addr) + return 0; + + spin_lock_irqsave(&tioca_kern->ca_lock, flags); + + /* + * allocate a map struct + */ + + ca_dmamap = kcalloc(1, sizeof(struct tioca_dmamap), GFP_ATOMIC); + if (!ca_dmamap) + goto map_return; + + /* + * Locate free entries that can hold req_size. Account for + * unaligned start/length when allocating. + */ + + ps = tioca_kern->ca_ap_pagesize; /* will be power of 2 */ + ps_shift = ffs(ps) - 1; + end_xio_addr = xio_addr + req_size - 1; + + entries = (end_xio_addr >> ps_shift) - (xio_addr >> ps_shift) + 1; + + map = tioca_kern->ca_pcigart_pagemap; + mapsize = tioca_kern->ca_pcigart_entries; + + entry = find_first_zero_bit(map, mapsize); + while (entry < mapsize) { + last_entry = find_next_bit(map, mapsize, entry); + + if (last_entry - entry >= entries) + break; + + entry = find_next_zero_bit(map, mapsize, last_entry); + } + + if (entry > mapsize) + goto map_return; + + for (i = 0; i < entries; i++) + set_bit(entry + i, map); + + bus_addr = tioca_kern->ca_pciap_base + (entry * ps); + + ca_dmamap->cad_dma_addr = bus_addr; + ca_dmamap->cad_gart_size = entries; + ca_dmamap->cad_gart_entry = entry; + list_add(&ca_dmamap->cad_list, &tioca_kern->ca_list); + + if (xio_addr % ps) { + tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr); + bus_addr += xio_addr & (ps - 1); + xio_addr &= ~(ps - 1); + xio_addr += ps; + entry++; + } + + while (xio_addr < end_xio_addr) { + tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr); + xio_addr += ps; + entry++; + } + + tioca_tlbflush(tioca_kern); + +map_return: + spin_unlock_irqrestore(&tioca_kern->ca_lock, flags); + return bus_addr; +} + +/** + * tioca_dma_unmap - release CA mapping resources + * @pdev: linux pci_dev representing the function + * @bus_addr: bus address returned by an earlier tioca_dma_map + * @dir: mapping direction (unused) + * + * Locate mapping resources associated with @bus_addr and release them. + * For mappings created using the direct modes (64 or 48) there are no + * resources to release. + */ +void +tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) +{ + int i, entry; + struct tioca_common *tioca_common; + struct tioca_kernel *tioca_kern; + struct tioca_dmamap *map; + struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); + unsigned long flags; + + tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; + tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private; + + /* return straight away if this isn't be a mapped address */ + + if (bus_addr < tioca_kern->ca_pciap_base || + bus_addr >= (tioca_kern->ca_pciap_base + tioca_kern->ca_pciap_size)) + return; + + spin_lock_irqsave(&tioca_kern->ca_lock, flags); + + list_for_each_entry(map, &tioca_kern->ca_dmamaps, cad_list) + if (map->cad_dma_addr == bus_addr) + break; + + BUG_ON(map == NULL); + + entry = map->cad_gart_entry; + + for (i = 0; i < map->cad_gart_size; i++, entry++) { + clear_bit(entry, tioca_kern->ca_pcigart_pagemap); + tioca_kern->ca_pcigart[entry] = 0; + } + tioca_tlbflush(tioca_kern); + + list_del(&map->cad_list); + spin_unlock_irqrestore(&tioca_kern->ca_lock, flags); + kfree(map); +} + +/** + * tioca_dma_map - map pages for PCI DMA + * @pdev: linux pci_dev representing the function + * @paddr: host physical address to map + * @byte_count: bytes to map + * + * This is the main wrapper for mapping host physical pages to CA PCI space. + * The mapping mode used is based on the devices dma_mask. As a last resort + * use the GART mapped mode. + */ +uint64_t +tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +{ + uint64_t mapaddr; + + /* + * If card is 64 or 48 bit addresable, use a direct mapping. 32 + * bit direct is so restrictive w.r.t. where the memory resides that + * we don't use it even though CA has some support. + */ + + if (pdev->dma_mask == ~0UL) + mapaddr = tioca_dma_d64(paddr); + else if (pdev->dma_mask == 0xffffffffffffUL) + mapaddr = tioca_dma_d48(pdev, paddr); + else + mapaddr = 0; + + /* Last resort ... use PCI portion of CA GART */ + + if (mapaddr == 0) + mapaddr = tioca_dma_mapped(pdev, paddr, byte_count); + + return mapaddr; +} + +/** + * tioca_error_intr_handler - SGI TIO CA error interrupt handler + * @irq: unused + * @arg: pointer to tioca_common struct for the given CA + * @pt: unused + * + * Handle a CA error interrupt. Simply a wrapper around a SAL call which + * defers processing to the SGI prom. + */ +static irqreturn_t +tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) +{ + struct tioca_common *soft = arg; + struct ia64_sal_retval ret_stuff; + uint64_t segment; + uint64_t busnum; + ret_stuff.status = 0; + ret_stuff.v0 = 0; + + segment = 0; + busnum = soft->ca_common.bs_persist_busnum; + + SAL_CALL_NOLOCK(ret_stuff, + (u64) SN_SAL_IOIF_ERROR_INTERRUPT, + segment, busnum, 0, 0, 0, 0, 0); + + return IRQ_HANDLED; +} + +/** + * tioca_bus_fixup - perform final PCI fixup for a TIO CA bus + * @prom_bussoft: Common prom/kernel struct representing the bus + * + * Replicates the tioca_common pointed to by @prom_bussoft in kernel + * space. Allocates and initializes a kernel-only area for a given CA, + * and sets up an irq for handling CA error interrupts. + * + * On successful setup, returns the kernel version of tioca_common back to + * the caller. + */ +void * +tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft) +{ + struct tioca_common *tioca_common; + struct tioca_kernel *tioca_kern; + struct pci_bus *bus; + + /* sanity check prom rev */ + + if (sn_sal_rev_major() < 4 || + (sn_sal_rev_major() == 4 && sn_sal_rev_minor() < 6)) { + printk + (KERN_ERR "%s: SGI prom rev 4.06 or greater required " + "for tioca support\n", __FUNCTION__); + return NULL; + } + + /* + * Allocate kernel bus soft and copy from prom. + */ + + tioca_common = kcalloc(1, sizeof(struct tioca_common), GFP_KERNEL); + if (!tioca_common) + return NULL; + + memcpy(tioca_common, prom_bussoft, sizeof(struct tioca_common)); + tioca_common->ca_common.bs_base |= __IA64_UNCACHED_OFFSET; + + /* init kernel-private area */ + + tioca_kern = kcalloc(1, sizeof(struct tioca_kernel), GFP_KERNEL); + if (!tioca_kern) { + kfree(tioca_common); + return NULL; + } + + tioca_kern->ca_common = tioca_common; + spin_lock_init(&tioca_kern->ca_lock); + INIT_LIST_HEAD(&tioca_kern->ca_dmamaps); + tioca_kern->ca_closest_node = + nasid_to_cnodeid(tioca_common->ca_closest_nasid); + tioca_common->ca_kernel_private = (uint64_t) tioca_kern; + + bus = pci_find_bus(0, tioca_common->ca_common.bs_persist_busnum); + BUG_ON(!bus); + tioca_kern->ca_devices = &bus->devices; + + /* init GART */ + + if (tioca_gart_init(tioca_kern) < 0) { + kfree(tioca_kern); + kfree(tioca_common); + return NULL; + } + + tioca_gart_found++; + list_add(&tioca_kern->ca_list, &tioca_list); + + if (request_irq(SGI_TIOCA_ERROR, + tioca_error_intr_handler, + SA_SHIRQ, "TIOCA error", (void *)tioca_common)) + printk(KERN_WARNING + "%s: Unable to get irq %d. " + "Error interrupts won't be routed for TIOCA bus %d\n", + __FUNCTION__, SGI_TIOCA_ERROR, + (int)tioca_common->ca_common.bs_persist_busnum); + + return tioca_common; +} + +static struct sn_pcibus_provider tioca_pci_interfaces = { + .dma_map = tioca_dma_map, + .dma_map_consistent = tioca_dma_map, + .dma_unmap = tioca_dma_unmap, + .bus_fixup = tioca_bus_fixup, +}; + +/** + * tioca_init_provider - init SN PCI provider ops for TIO CA + */ +int +tioca_init_provider(void) +{ + sn_pci_provider[PCIIO_ASIC_TYPE_TIOCA] = &tioca_pci_interfaces; + return 0; +} diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h index f546b4ece33c..04e27d5b3820 100644 --- a/include/asm-ia64/sn/pcibus_provider_defs.h +++ b/include/asm-ia64/sn/pcibus_provider_defs.h @@ -17,8 +17,9 @@ #define PCIIO_ASIC_TYPE_PPB 1 #define PCIIO_ASIC_TYPE_PIC 2 #define PCIIO_ASIC_TYPE_TIOCP 3 +#define PCIIO_ASIC_TYPE_TIOCA 4 -#define PCIIO_ASIC_MAX_TYPES 4 +#define PCIIO_ASIC_MAX_TYPES 5 /* * Common pciio bus provider data. There should be one of these as the diff --git a/include/asm-ia64/sn/tioca.h b/include/asm-ia64/sn/tioca.h new file mode 100644 index 000000000000..bc1aacfb9483 --- /dev/null +++ b/include/asm-ia64/sn/tioca.h @@ -0,0 +1,596 @@ +#ifndef _ASM_IA64_SN_TIO_TIOCA_H +#define _ASM_IA64_SN_TIO_TIOCA_H + +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2003-2005 Silicon Graphics, Inc. All rights reserved. + */ + + +#define TIOCA_PART_NUM 0xE020 +#define TIOCA_MFGR_NUM 0x24 +#define TIOCA_REV_A 0x1 + +/* + * Register layout for TIO:CA. See below for bitmasks for each register. + */ + +struct tioca { + uint64_t ca_id; /* 0x000000 */ + uint64_t ca_control1; /* 0x000008 */ + uint64_t ca_control2; /* 0x000010 */ + uint64_t ca_status1; /* 0x000018 */ + uint64_t ca_status2; /* 0x000020 */ + uint64_t ca_gart_aperature; /* 0x000028 */ + uint64_t ca_gfx_detach; /* 0x000030 */ + uint64_t ca_inta_dest_addr; /* 0x000038 */ + uint64_t ca_intb_dest_addr; /* 0x000040 */ + uint64_t ca_err_int_dest_addr; /* 0x000048 */ + uint64_t ca_int_status; /* 0x000050 */ + uint64_t ca_int_status_alias; /* 0x000058 */ + uint64_t ca_mult_error; /* 0x000060 */ + uint64_t ca_mult_error_alias; /* 0x000068 */ + uint64_t ca_first_error; /* 0x000070 */ + uint64_t ca_int_mask; /* 0x000078 */ + uint64_t ca_crm_pkterr_type; /* 0x000080 */ + uint64_t ca_crm_pkterr_type_alias; /* 0x000088 */ + uint64_t ca_crm_ct_error_detail_1; /* 0x000090 */ + uint64_t ca_crm_ct_error_detail_2; /* 0x000098 */ + uint64_t ca_crm_tnumto; /* 0x0000A0 */ + uint64_t ca_gart_err; /* 0x0000A8 */ + uint64_t ca_pcierr_type; /* 0x0000B0 */ + uint64_t ca_pcierr_addr; /* 0x0000B8 */ + + uint64_t ca_pad_0000C0[3]; /* 0x0000{C0..D0} */ + + uint64_t ca_pci_rd_buf_flush; /* 0x0000D8 */ + uint64_t ca_pci_dma_addr_extn; /* 0x0000E0 */ + uint64_t ca_agp_dma_addr_extn; /* 0x0000E8 */ + uint64_t ca_force_inta; /* 0x0000F0 */ + uint64_t ca_force_intb; /* 0x0000F8 */ + uint64_t ca_debug_vector_sel; /* 0x000100 */ + uint64_t ca_debug_mux_core_sel; /* 0x000108 */ + uint64_t ca_debug_mux_pci_sel; /* 0x000110 */ + uint64_t ca_debug_domain_sel; /* 0x000118 */ + + uint64_t ca_pad_000120[28]; /* 0x0001{20..F8} */ + + uint64_t ca_gart_ptr_table; /* 0x200 */ + uint64_t ca_gart_tlb_addr[8]; /* 0x2{08..40} */ +}; + +/* + * Mask/shift definitions for TIO:CA registers. The convention here is + * to mainly use the names as they appear in the "TIO AEGIS Programmers' + * Reference" with a CA_ prefix added. Some exceptions were made to fix + * duplicate field names or to generalize fields that are common to + * different registers (ca_debug_mux_core_sel and ca_debug_mux_pci_sel for + * example). + * + * Fields consisting of a single bit have a single #define have a single + * macro declaration to mask the bit. Fields consisting of multiple bits + * have two declarations: one to mask the proper bits in a register, and + * a second with the suffix "_SHFT" to identify how far the mask needs to + * be shifted right to get its base value. + */ + +/* ==== ca_control1 */ +#define CA_SYS_BIG_END (1ull << 0) +#define CA_DMA_AGP_SWAP (1ull << 1) +#define CA_DMA_PCI_SWAP (1ull << 2) +#define CA_PIO_IO_SWAP (1ull << 3) +#define CA_PIO_MEM_SWAP (1ull << 4) +#define CA_GFX_WR_SWAP (1ull << 5) +#define CA_AGP_FW_ENABLE (1ull << 6) +#define CA_AGP_CAL_CYCLE (0x7ull << 7) +#define CA_AGP_CAL_CYCLE_SHFT 7 +#define CA_AGP_CAL_PRSCL_BYP (1ull << 10) +#define CA_AGP_INIT_CAL_ENB (1ull << 11) +#define CA_INJ_ADDR_PERR (1ull << 12) +#define CA_INJ_DATA_PERR (1ull << 13) + /* bits 15:14 unused */ +#define CA_PCIM_IO_NBE_AD (0x7ull << 16) +#define CA_PCIM_IO_NBE_AD_SHFT 16 +#define CA_PCIM_FAST_BTB_ENB (1ull << 19) + /* bits 23:20 unused */ +#define CA_PIO_ADDR_OFFSET (0xffull << 24) +#define CA_PIO_ADDR_OFFSET_SHFT 24 + /* bits 35:32 unused */ +#define CA_AGPDMA_OP_COMBDELAY (0x1full << 36) +#define CA_AGPDMA_OP_COMBDELAY_SHFT 36 + /* bit 41 unused */ +#define CA_AGPDMA_OP_ENB_COMBDELAY (1ull << 42) +#define CA_PCI_INT_LPCNT (0xffull << 44) +#define CA_PCI_INT_LPCNT_SHFT 44 + /* bits 63:52 unused */ + +/* ==== ca_control2 */ +#define CA_AGP_LATENCY_TO (0xffull << 0) +#define CA_AGP_LATENCY_TO_SHFT 0 +#define CA_PCI_LATENCY_TO (0xffull << 8) +#define CA_PCI_LATENCY_TO_SHFT 8 +#define CA_PCI_MAX_RETRY (0x3ffull << 16) +#define CA_PCI_MAX_RETRY_SHFT 16 + /* bits 27:26 unused */ +#define CA_RT_INT_EN (0x3ull << 28) +#define CA_RT_INT_EN_SHFT 28 +#define CA_MSI_INT_ENB (1ull << 30) +#define CA_PCI_ARB_ERR_ENB (1ull << 31) +#define CA_GART_MEM_PARAM (0x3ull << 32) +#define CA_GART_MEM_PARAM_SHFT 32 +#define CA_GART_RD_PREFETCH_ENB (1ull << 34) +#define CA_GART_WR_PREFETCH_ENB (1ull << 35) +#define CA_GART_FLUSH_TLB (1ull << 36) + /* bits 39:37 unused */ +#define CA_CRM_TNUMTO_PERIOD (0x1fffull << 40) +#define CA_CRM_TNUMTO_PERIOD_SHFT 40 + /* bits 55:53 unused */ +#define CA_CRM_TNUMTO_ENB (1ull << 56) +#define CA_CRM_PRESCALER_BYP (1ull << 57) + /* bits 59:58 unused */ +#define CA_CRM_MAX_CREDIT (0x7ull << 60) +#define CA_CRM_MAX_CREDIT_SHFT 60 + /* bit 63 unused */ + +/* ==== ca_status1 */ +#define CA_CORELET_ID (0x3ull << 0) +#define CA_CORELET_ID_SHFT 0 +#define CA_INTA_N (1ull << 2) +#define CA_INTB_N (1ull << 3) +#define CA_CRM_CREDIT_AVAIL (0x7ull << 4) +#define CA_CRM_CREDIT_AVAIL_SHFT 4 + /* bit 7 unused */ +#define CA_CRM_SPACE_AVAIL (0x7full << 8) +#define CA_CRM_SPACE_AVAIL_SHFT 8 + /* bit 15 unused */ +#define CA_GART_TLB_VAL (0xffull << 16) +#define CA_GART_TLB_VAL_SHFT 16 + /* bits 63:24 unused */ + +/* ==== ca_status2 */ +#define CA_GFX_CREDIT_AVAIL (0xffull << 0) +#define CA_GFX_CREDIT_AVAIL_SHFT 0 +#define CA_GFX_OPQ_AVAIL (0xffull << 8) +#define CA_GFX_OPQ_AVAIL_SHFT 8 +#define CA_GFX_WRBUFF_AVAIL (0xffull << 16) +#define CA_GFX_WRBUFF_AVAIL_SHFT 16 +#define CA_ADMA_OPQ_AVAIL (0xffull << 24) +#define CA_ADMA_OPQ_AVAIL_SHFT 24 +#define CA_ADMA_WRBUFF_AVAIL (0xffull << 32) +#define CA_ADMA_WRBUFF_AVAIL_SHFT 32 +#define CA_ADMA_RDBUFF_AVAIL (0x7full << 40) +#define CA_ADMA_RDBUFF_AVAIL_SHFT 40 +#define CA_PCI_PIO_OP_STAT (1ull << 47) +#define CA_PDMA_OPQ_AVAIL (0xfull << 48) +#define CA_PDMA_OPQ_AVAIL_SHFT 48 +#define CA_PDMA_WRBUFF_AVAIL (0xfull << 52) +#define CA_PDMA_WRBUFF_AVAIL_SHFT 52 +#define CA_PDMA_RDBUFF_AVAIL (0x3ull << 56) +#define CA_PDMA_RDBUFF_AVAIL_SHFT 56 + /* bits 63:58 unused */ + +/* ==== ca_gart_aperature */ +#define CA_GART_AP_ENB_AGP (1ull << 0) +#define CA_GART_PAGE_SIZE (1ull << 1) +#define CA_GART_AP_ENB_PCI (1ull << 2) + /* bits 11:3 unused */ +#define CA_GART_AP_SIZE (0x3ffull << 12) +#define CA_GART_AP_SIZE_SHFT 12 +#define CA_GART_AP_BASE (0x3ffffffffffull << 22) +#define CA_GART_AP_BASE_SHFT 22 + +/* ==== ca_inta_dest_addr + ==== ca_intb_dest_addr + ==== ca_err_int_dest_addr */ + /* bits 2:0 unused */ +#define CA_INT_DEST_ADDR (0x7ffffffffffffull << 3) +#define CA_INT_DEST_ADDR_SHFT 3 + /* bits 55:54 unused */ +#define CA_INT_DEST_VECT (0xffull << 56) +#define CA_INT_DEST_VECT_SHFT 56 + +/* ==== ca_int_status */ +/* ==== ca_int_status_alias */ +/* ==== ca_mult_error */ +/* ==== ca_mult_error_alias */ +/* ==== ca_first_error */ +/* ==== ca_int_mask */ +#define CA_PCI_ERR (1ull << 0) + /* bits 3:1 unused */ +#define CA_GART_FETCH_ERR (1ull << 4) +#define CA_GFX_WR_OVFLW (1ull << 5) +#define CA_PIO_REQ_OVFLW (1ull << 6) +#define CA_CRM_PKTERR (1ull << 7) +#define CA_CRM_DVERR (1ull << 8) +#define CA_TNUMTO (1ull << 9) +#define CA_CXM_RSP_CRED_OVFLW (1ull << 10) +#define CA_CXM_REQ_CRED_OVFLW (1ull << 11) +#define CA_PIO_INVALID_ADDR (1ull << 12) +#define CA_PCI_ARB_TO (1ull << 13) +#define CA_AGP_REQ_OFLOW (1ull << 14) +#define CA_SBA_TYPE1_ERR (1ull << 15) + /* bit 16 unused */ +#define CA_INTA (1ull << 17) +#define CA_INTB (1ull << 18) +#define CA_MULT_INTA (1ull << 19) +#define CA_MULT_INTB (1ull << 20) +#define CA_GFX_CREDIT_OVFLW (1ull << 21) + /* bits 63:22 unused */ + +/* ==== ca_crm_pkterr_type */ +/* ==== ca_crm_pkterr_type_alias */ +#define CA_CRM_PKTERR_SBERR_HDR (1ull << 0) +#define CA_CRM_PKTERR_DIDN (1ull << 1) +#define CA_CRM_PKTERR_PACTYPE (1ull << 2) +#define CA_CRM_PKTERR_INV_TNUM (1ull << 3) +#define CA_CRM_PKTERR_ADDR_RNG (1ull << 4) +#define CA_CRM_PKTERR_ADDR_ALGN (1ull << 5) +#define CA_CRM_PKTERR_HDR_PARAM (1ull << 6) +#define CA_CRM_PKTERR_CW_ERR (1ull << 7) +#define CA_CRM_PKTERR_SBERR_NH (1ull << 8) +#define CA_CRM_PKTERR_EARLY_TERM (1ull << 9) +#define CA_CRM_PKTERR_EARLY_TAIL (1ull << 10) +#define CA_CRM_PKTERR_MSSNG_TAIL (1ull << 11) +#define CA_CRM_PKTERR_MSSNG_HDR (1ull << 12) + /* bits 15:13 unused */ +#define CA_FIRST_CRM_PKTERR_SBERR_HDR (1ull << 16) +#define CA_FIRST_CRM_PKTERR_DIDN (1ull << 17) +#define CA_FIRST_CRM_PKTERR_PACTYPE (1ull << 18) +#define CA_FIRST_CRM_PKTERR_INV_TNUM (1ull << 19) +#define CA_FIRST_CRM_PKTERR_ADDR_RNG (1ull << 20) +#define CA_FIRST_CRM_PKTERR_ADDR_ALGN (1ull << 21) +#define CA_FIRST_CRM_PKTERR_HDR_PARAM (1ull << 22) +#define CA_FIRST_CRM_PKTERR_CW_ERR (1ull << 23) +#define CA_FIRST_CRM_PKTERR_SBERR_NH (1ull << 24) +#define CA_FIRST_CRM_PKTERR_EARLY_TERM (1ull << 25) +#define CA_FIRST_CRM_PKTERR_EARLY_TAIL (1ull << 26) +#define CA_FIRST_CRM_PKTERR_MSSNG_TAIL (1ull << 27) +#define CA_FIRST_CRM_PKTERR_MSSNG_HDR (1ull << 28) + /* bits 63:29 unused */ + +/* ==== ca_crm_ct_error_detail_1 */ +#define CA_PKT_TYPE (0xfull << 0) +#define CA_PKT_TYPE_SHFT 0 +#define CA_SRC_ID (0x3ull << 4) +#define CA_SRC_ID_SHFT 4 +#define CA_DATA_SZ (0x3ull << 6) +#define CA_DATA_SZ_SHFT 6 +#define CA_TNUM (0xffull << 8) +#define CA_TNUM_SHFT 8 +#define CA_DW_DATA_EN (0xffull << 16) +#define CA_DW_DATA_EN_SHFT 16 +#define CA_GFX_CRED (0xffull << 24) +#define CA_GFX_CRED_SHFT 24 +#define CA_MEM_RD_PARAM (0x3ull << 32) +#define CA_MEM_RD_PARAM_SHFT 32 +#define CA_PIO_OP (1ull << 34) +#define CA_CW_ERR (1ull << 35) + /* bits 62:36 unused */ +#define CA_VALID (1ull << 63) + +/* ==== ca_crm_ct_error_detail_2 */ + /* bits 2:0 unused */ +#define CA_PKT_ADDR (0x1fffffffffffffull << 3) +#define CA_PKT_ADDR_SHFT 3 + /* bits 63:56 unused */ + +/* ==== ca_crm_tnumto */ +#define CA_CRM_TNUMTO_VAL (0xffull << 0) +#define CA_CRM_TNUMTO_VAL_SHFT 0 +#define CA_CRM_TNUMTO_WR (1ull << 8) + /* bits 63:9 unused */ + +/* ==== ca_gart_err */ +#define CA_GART_ERR_SOURCE (0x3ull << 0) +#define CA_GART_ERR_SOURCE_SHFT 0 + /* bits 3:2 unused */ +#define CA_GART_ERR_ADDR (0xfffffffffull << 4) +#define CA_GART_ERR_ADDR_SHFT 4 + /* bits 63:40 unused */ + +/* ==== ca_pcierr_type */ +#define CA_PCIERR_DATA (0xffffffffull << 0) +#define CA_PCIERR_DATA_SHFT 0 +#define CA_PCIERR_ENB (0xfull << 32) +#define CA_PCIERR_ENB_SHFT 32 +#define CA_PCIERR_CMD (0xfull << 36) +#define CA_PCIERR_CMD_SHFT 36 +#define CA_PCIERR_A64 (1ull << 40) +#define CA_PCIERR_SLV_SERR (1ull << 41) +#define CA_PCIERR_SLV_WR_PERR (1ull << 42) +#define CA_PCIERR_SLV_RD_PERR (1ull << 43) +#define CA_PCIERR_MST_SERR (1ull << 44) +#define CA_PCIERR_MST_WR_PERR (1ull << 45) +#define CA_PCIERR_MST_RD_PERR (1ull << 46) +#define CA_PCIERR_MST_MABT (1ull << 47) +#define CA_PCIERR_MST_TABT (1ull << 48) +#define CA_PCIERR_MST_RETRY_TOUT (1ull << 49) + +#define CA_PCIERR_TYPES \ + (CA_PCIERR_A64|CA_PCIERR_SLV_SERR| \ + CA_PCIERR_SLV_WR_PERR|CA_PCIERR_SLV_RD_PERR| \ + CA_PCIERR_MST_SERR|CA_PCIERR_MST_WR_PERR|CA_PCIERR_MST_RD_PERR| \ + CA_PCIERR_MST_MABT|CA_PCIERR_MST_TABT|CA_PCIERR_MST_RETRY_TOUT) + + /* bits 63:50 unused */ + +/* ==== ca_pci_dma_addr_extn */ +#define CA_UPPER_NODE_OFFSET (0x3full << 0) +#define CA_UPPER_NODE_OFFSET_SHFT 0 + /* bits 7:6 unused */ +#define CA_CHIPLET_ID (0x3ull << 8) +#define CA_CHIPLET_ID_SHFT 8 + /* bits 11:10 unused */ +#define CA_PCI_DMA_NODE_ID (0xffffull << 12) +#define CA_PCI_DMA_NODE_ID_SHFT 12 + /* bits 27:26 unused */ +#define CA_PCI_DMA_PIO_MEM_TYPE (1ull << 28) + /* bits 63:29 unused */ + + +/* ==== ca_agp_dma_addr_extn */ + /* bits 19:0 unused */ +#define CA_AGP_DMA_NODE_ID (0xffffull << 20) +#define CA_AGP_DMA_NODE_ID_SHFT 20 + /* bits 27:26 unused */ +#define CA_AGP_DMA_PIO_MEM_TYPE (1ull << 28) + /* bits 63:29 unused */ + +/* ==== ca_debug_vector_sel */ +#define CA_DEBUG_MN_VSEL (0xfull << 0) +#define CA_DEBUG_MN_VSEL_SHFT 0 +#define CA_DEBUG_PP_VSEL (0xfull << 4) +#define CA_DEBUG_PP_VSEL_SHFT 4 +#define CA_DEBUG_GW_VSEL (0xfull << 8) +#define CA_DEBUG_GW_VSEL_SHFT 8 +#define CA_DEBUG_GT_VSEL (0xfull << 12) +#define CA_DEBUG_GT_VSEL_SHFT 12 +#define CA_DEBUG_PD_VSEL (0xfull << 16) +#define CA_DEBUG_PD_VSEL_SHFT 16 +#define CA_DEBUG_AD_VSEL (0xfull << 20) +#define CA_DEBUG_AD_VSEL_SHFT 20 +#define CA_DEBUG_CX_VSEL (0xfull << 24) +#define CA_DEBUG_CX_VSEL_SHFT 24 +#define CA_DEBUG_CR_VSEL (0xfull << 28) +#define CA_DEBUG_CR_VSEL_SHFT 28 +#define CA_DEBUG_BA_VSEL (0xfull << 32) +#define CA_DEBUG_BA_VSEL_SHFT 32 +#define CA_DEBUG_PE_VSEL (0xfull << 36) +#define CA_DEBUG_PE_VSEL_SHFT 36 +#define CA_DEBUG_BO_VSEL (0xfull << 40) +#define CA_DEBUG_BO_VSEL_SHFT 40 +#define CA_DEBUG_BI_VSEL (0xfull << 44) +#define CA_DEBUG_BI_VSEL_SHFT 44 +#define CA_DEBUG_AS_VSEL (0xfull << 48) +#define CA_DEBUG_AS_VSEL_SHFT 48 +#define CA_DEBUG_PS_VSEL (0xfull << 52) +#define CA_DEBUG_PS_VSEL_SHFT 52 +#define CA_DEBUG_PM_VSEL (0xfull << 56) +#define CA_DEBUG_PM_VSEL_SHFT 56 + /* bits 63:60 unused */ + +/* ==== ca_debug_mux_core_sel */ +/* ==== ca_debug_mux_pci_sel */ +#define CA_DEBUG_MSEL0 (0x7ull << 0) +#define CA_DEBUG_MSEL0_SHFT 0 + /* bit 3 unused */ +#define CA_DEBUG_NSEL0 (0x7ull << 4) +#define CA_DEBUG_NSEL0_SHFT 4 + /* bit 7 unused */ +#define CA_DEBUG_MSEL1 (0x7ull << 8) +#define CA_DEBUG_MSEL1_SHFT 8 + /* bit 11 unused */ +#define CA_DEBUG_NSEL1 (0x7ull << 12) +#define CA_DEBUG_NSEL1_SHFT 12 + /* bit 15 unused */ +#define CA_DEBUG_MSEL2 (0x7ull << 16) +#define CA_DEBUG_MSEL2_SHFT 16 + /* bit 19 unused */ +#define CA_DEBUG_NSEL2 (0x7ull << 20) +#define CA_DEBUG_NSEL2_SHFT 20 + /* bit 23 unused */ +#define CA_DEBUG_MSEL3 (0x7ull << 24) +#define CA_DEBUG_MSEL3_SHFT 24 + /* bit 27 unused */ +#define CA_DEBUG_NSEL3 (0x7ull << 28) +#define CA_DEBUG_NSEL3_SHFT 28 + /* bit 31 unused */ +#define CA_DEBUG_MSEL4 (0x7ull << 32) +#define CA_DEBUG_MSEL4_SHFT 32 + /* bit 35 unused */ +#define CA_DEBUG_NSEL4 (0x7ull << 36) +#define CA_DEBUG_NSEL4_SHFT 36 + /* bit 39 unused */ +#define CA_DEBUG_MSEL5 (0x7ull << 40) +#define CA_DEBUG_MSEL5_SHFT 40 + /* bit 43 unused */ +#define CA_DEBUG_NSEL5 (0x7ull << 44) +#define CA_DEBUG_NSEL5_SHFT 44 + /* bit 47 unused */ +#define CA_DEBUG_MSEL6 (0x7ull << 48) +#define CA_DEBUG_MSEL6_SHFT 48 + /* bit 51 unused */ +#define CA_DEBUG_NSEL6 (0x7ull << 52) +#define CA_DEBUG_NSEL6_SHFT 52 + /* bit 55 unused */ +#define CA_DEBUG_MSEL7 (0x7ull << 56) +#define CA_DEBUG_MSEL7_SHFT 56 + /* bit 59 unused */ +#define CA_DEBUG_NSEL7 (0x7ull << 60) +#define CA_DEBUG_NSEL7_SHFT 60 + /* bit 63 unused */ + + +/* ==== ca_debug_domain_sel */ +#define CA_DEBUG_DOMAIN_L (1ull << 0) +#define CA_DEBUG_DOMAIN_H (1ull << 1) + /* bits 63:2 unused */ + +/* ==== ca_gart_ptr_table */ +#define CA_GART_PTR_VAL (1ull << 0) + /* bits 11:1 unused */ +#define CA_GART_PTR_ADDR (0xfffffffffffull << 12) +#define CA_GART_PTR_ADDR_SHFT 12 + /* bits 63:56 unused */ + +/* ==== ca_gart_tlb_addr[0-7] */ +#define CA_GART_TLB_ADDR (0xffffffffffffffull << 0) +#define CA_GART_TLB_ADDR_SHFT 0 + /* bits 62:56 unused */ +#define CA_GART_TLB_ENTRY_VAL (1ull << 63) + +/* + * PIO address space ranges for TIO:CA + */ + +/* CA internal registers */ +#define CA_PIO_ADMIN 0x00000000 +#define CA_PIO_ADMIN_LEN 0x00010000 + +/* GFX Write Buffer - Diagnostics */ +#define CA_PIO_GFX 0x00010000 +#define CA_PIO_GFX_LEN 0x00010000 + +/* AGP DMA Write Buffer - Diagnostics */ +#define CA_PIO_AGP_DMAWRITE 0x00020000 +#define CA_PIO_AGP_DMAWRITE_LEN 0x00010000 + +/* AGP DMA READ Buffer - Diagnostics */ +#define CA_PIO_AGP_DMAREAD 0x00030000 +#define CA_PIO_AGP_DMAREAD_LEN 0x00010000 + +/* PCI Config Type 0 */ +#define CA_PIO_PCI_TYPE0_CONFIG 0x01000000 +#define CA_PIO_PCI_TYPE0_CONFIG_LEN 0x01000000 + +/* PCI Config Type 1 */ +#define CA_PIO_PCI_TYPE1_CONFIG 0x02000000 +#define CA_PIO_PCI_TYPE1_CONFIG_LEN 0x01000000 + +/* PCI I/O Cycles - mapped to PCI Address 0x00000000-0x04ffffff */ +#define CA_PIO_PCI_IO 0x03000000 +#define CA_PIO_PCI_IO_LEN 0x05000000 + +/* PCI MEM Cycles - mapped to PCI with CA_PIO_ADDR_OFFSET of ca_control1 */ +/* use Fast Write if enabled and coretalk packet type is a GFX request */ +#define CA_PIO_PCI_MEM_OFFSET 0x08000000 +#define CA_PIO_PCI_MEM_OFFSET_LEN 0x08000000 + +/* PCI MEM Cycles - mapped to PCI Address 0x00000000-0xbfffffff */ +/* use Fast Write if enabled and coretalk packet type is a GFX request */ +#define CA_PIO_PCI_MEM 0x40000000 +#define CA_PIO_PCI_MEM_LEN 0xc0000000 + +/* + * DMA space + * + * The CA aperature (ie. bus address range) mapped by the GART is segmented into + * two parts. The lower portion of the aperature is used for mapping 32 bit + * PCI addresses which are managed by the dma interfaces in this file. The + * upper poprtion of the aperature is used for mapping 48 bit AGP addresses. + * The AGP portion of the aperature is managed by the agpgart_be.c driver + * in drivers/linux/agp. There are ca-specific hooks in that driver to + * manipulate the gart, but management of the AGP portion of the aperature + * is the responsibility of that driver. + * + * CA allows three main types of DMA mapping: + * + * PCI 64-bit Managed by this driver + * PCI 32-bit Managed by this driver + * AGP 48-bit Managed by hooks in the /dev/agpgart driver + * + * All of the above can optionally be remapped through the GART. The following + * table lists the combinations of addressing types and GART remapping that + * is currently supported by the driver (h/w supports all, s/w limits this): + * + * PCI64 PCI32 AGP48 + * GART no yes yes + * Direct yes yes no + * + * GART remapping of PCI64 is not done because there is no need to. The + * 64 bit PCI address holds all of the information necessary to target any + * memory in the system. + * + * AGP48 is always mapped through the GART. Management of the AGP48 portion + * of the aperature is the responsibility of code in the agpgart_be driver. + * + * The non-64 bit bus address space will currently be partitioned like this: + * + * 0xffff_ffff_ffff +-------- + * | AGP48 direct + * | Space managed by this driver + * CA_AGP_DIRECT_BASE +-------- + * | AGP GART mapped (gfx aperature) + * | Space managed by /dev/agpgart driver + * | This range is exposed to the agpgart + * | driver as the "graphics aperature" + * CA_AGP_MAPPED_BASE +----- + * | PCI GART mapped + * | Space managed by this driver + * CA_PCI32_MAPPED_BASE +---- + * | PCI32 direct + * | Space managed by this driver + * 0xC000_0000 +-------- + * (CA_PCI32_DIRECT_BASE) + * + * The bus address range CA_PCI32_MAPPED_BASE through CA_AGP_DIRECT_BASE + * is what we call the CA aperature. Addresses falling in this range will + * be remapped using the GART. + * + * The bus address range CA_AGP_MAPPED_BASE through CA_AGP_DIRECT_BASE + * is what we call the graphics aperature. This is a subset of the CA + * aperature and is under the control of the agpgart_be driver. + * + * CA_PCI32_MAPPED_BASE, CA_AGP_MAPPED_BASE, and CA_AGP_DIRECT_BASE are + * somewhat arbitrary values. The known constraints on choosing these is: + * + * 1) CA_AGP_DIRECT_BASE-CA_PCI32_MAPPED_BASE+1 (the CA aperature size) + * must be one of the values supported by the ca_gart_aperature register. + * Currently valid values are: 4MB through 4096MB in powers of 2 increments + * + * 2) CA_AGP_DIRECT_BASE-CA_AGP_MAPPED_BASE+1 (the gfx aperature size) + * must be in MB units since that's what the agpgart driver assumes. + */ + +/* + * Define Bus DMA ranges. These are configurable (see constraints above) + * and will probably need tuning based on experience. + */ + + +/* + * 11/24/03 + * CA has an addressing glitch w.r.t. PCI direct 32 bit DMA that makes it + * generally unusable. The problem is that for PCI direct 32 + * DMA's, all 32 bits of the bus address are used to form the lower 32 bits + * of the coretalk address, and coretalk bits 38:32 come from a register. + * Since only PCI bus addresses 0xC0000000-0xFFFFFFFF (1GB) are available + * for DMA (the rest is allocated to PIO), host node addresses need to be + * such that their lower 32 bits fall in the 0xC0000000-0xffffffff range + * as well. So there can be no PCI32 direct DMA below 3GB!! For this + * reason we set the CA_PCI32_DIRECT_SIZE to 0 which essentially makes + * tioca_dma_direct32() a noop but preserves the code flow should this issue + * be fixed in a respin. + * + * For now, all PCI32 DMA's must be mapped through the GART. + */ + +#define CA_PCI32_DIRECT_BASE 0xC0000000UL /* BASE not configurable */ +#define CA_PCI32_DIRECT_SIZE 0x00000000UL /* 0 MB */ + +#define CA_PCI32_MAPPED_BASE 0xC0000000UL +#define CA_PCI32_MAPPED_SIZE 0x40000000UL /* 2GB */ + +#define CA_AGP_MAPPED_BASE 0x80000000UL +#define CA_AGP_MAPPED_SIZE 0x40000000UL /* 2GB */ + +#define CA_AGP_DIRECT_BASE 0x40000000UL /* 2GB */ +#define CA_AGP_DIRECT_SIZE 0x40000000UL + +#define CA_APERATURE_BASE (CA_AGP_MAPPED_BASE) +#define CA_APERATURE_SIZE (CA_AGP_MAPPED_SIZE+CA_PCI32_MAPPED_SIZE) + +#endif /* _ASM_IA64_SN_TIO_TIOCA_H */ diff --git a/include/asm-ia64/sn/tioca_provider.h b/include/asm-ia64/sn/tioca_provider.h new file mode 100644 index 000000000000..b6acc22ab239 --- /dev/null +++ b/include/asm-ia64/sn/tioca_provider.h @@ -0,0 +1,206 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2003-2005 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H +#define _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H + +#include + +/* + * WAR enables + * Defines for individual WARs. Each is a bitmask of applicable + * part revision numbers. (1 << 1) == rev A, (1 << 2) == rev B, + * (3 << 1) == (rev A or rev B), etc + */ + +#define TIOCA_WAR_ENABLED(pv, tioca_common) \ + ((1 << tioca_common->ca_rev) & pv) + + /* TIO:ICE:FRZ:Freezer loses a PIO data ucred on PIO RD RSP with CW error */ +#define PV907908 (1 << 1) + /* ATI config space problems after BIOS execution starts */ +#define PV908234 (1 << 1) + /* CA:AGPDMA write request data mismatch with ABC1CL merge */ +#define PV895469 (1 << 1) + /* TIO:CA TLB invalidate of written GART entries possibly not occuring in CA*/ +#define PV910244 (1 << 1) + +struct tioca_dmamap{ + struct list_head cad_list; /* headed by ca_list */ + + dma_addr_t cad_dma_addr; /* Linux dma handle */ + uint cad_gart_entry; /* start entry in ca_gart_pagemap */ + uint cad_gart_size; /* #entries for this map */ +}; + +/* + * Kernel only fields. Prom may look at this stuff for debugging only. + * Access this structure through the ca_kernel_private ptr. + */ + +struct tioca_common ; + +struct tioca_kernel { + struct tioca_common *ca_common; /* tioca this belongs to */ + struct list_head ca_list; /* list of all ca's */ + struct list_head ca_dmamaps; + spinlock_t ca_lock; /* Kernel lock */ + cnodeid_t ca_closest_node; + struct list_head *ca_devices; /* bus->devices */ + + /* + * General GART stuff + */ + uint64_t ca_ap_size; /* size of aperature in bytes */ + uint32_t ca_gart_entries; /* # uint64_t entries in gart */ + uint32_t ca_ap_pagesize; /* aperature page size in bytes */ + uint64_t ca_ap_bus_base; /* bus address of CA aperature */ + uint64_t ca_gart_size; /* gart size in bytes */ + uint64_t *ca_gart; /* gart table vaddr */ + uint64_t ca_gart_coretalk_addr; /* gart coretalk addr */ + uint8_t ca_gart_iscoherent; /* used in tioca_tlbflush */ + + /* PCI GART convenience values */ + uint64_t ca_pciap_base; /* pci aperature bus base address */ + uint64_t ca_pciap_size; /* pci aperature size (bytes) */ + uint64_t ca_pcigart_base; /* gfx GART bus base address */ + uint64_t *ca_pcigart; /* gfx GART vm address */ + uint32_t ca_pcigart_entries; + uint32_t ca_pcigart_start; /* PCI start index in ca_gart */ + void *ca_pcigart_pagemap; + + /* AGP GART convenience values */ + uint64_t ca_gfxap_base; /* gfx aperature bus base address */ + uint64_t ca_gfxap_size; /* gfx aperature size (bytes) */ + uint64_t ca_gfxgart_base; /* gfx GART bus base address */ + uint64_t *ca_gfxgart; /* gfx GART vm address */ + uint32_t ca_gfxgart_entries; + uint32_t ca_gfxgart_start; /* agpgart start index in ca_gart */ +}; + +/* + * Common tioca info shared between kernel and prom + * + * DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES + * TO THE PROM VERSION. + */ + +struct tioca_common { + struct pcibus_bussoft ca_common; /* common pciio header */ + + uint32_t ca_rev; + uint32_t ca_closest_nasid; + + uint64_t ca_prom_private; + uint64_t ca_kernel_private; +}; + +/** + * tioca_paddr_to_gart - Convert an SGI coretalk address to a CA GART entry + * @paddr: page address to convert + * + * Convert a system [coretalk] address to a GART entry. GART entries are + * formed using the following: + * + * data = ( (1<<63) | ( (REMAP_NODE_ID << 40) | (MD_CHIPLET_ID << 38) | + * (REMAP_SYS_ADDR) ) >> 12 ) + * + * DATA written to 1 GART TABLE Entry in system memory is remapped system + * addr for 1 page + * + * The data is for coretalk address format right shifted 12 bits with a + * valid bit. + * + * GART_TABLE_ENTRY [ 25:0 ] -- REMAP_SYS_ADDRESS[37:12]. + * GART_TABLE_ENTRY [ 27:26 ] -- SHUB MD chiplet id. + * GART_TABLE_ENTRY [ 41:28 ] -- REMAP_NODE_ID. + * GART_TABLE_ENTRY [ 63 ] -- Valid Bit + */ +static inline u64 +tioca_paddr_to_gart(unsigned long paddr) +{ + /* + * We are assuming right now that paddr already has the correct + * format since the address from xtalk_dmaXXX should already have + * NODE_ID, CHIPLET_ID, and SYS_ADDR in the correct locations. + */ + + return ((paddr) >> 12) | (1UL << 63); +} + +/** + * tioca_physpage_to_gart - Map a host physical page for SGI CA based DMA + * @page_addr: system page address to map + */ + +static inline unsigned long +tioca_physpage_to_gart(uint64_t page_addr) +{ + uint64_t coretalk_addr; + + coretalk_addr = PHYS_TO_TIODMA(page_addr); + if (!coretalk_addr) { + return 0; + } + + return tioca_paddr_to_gart(coretalk_addr); +} + +/** + * tioca_tlbflush - invalidate cached SGI CA GART TLB entries + * @tioca_kernel: CA context + * + * Invalidate tlb entries for a given CA GART. Main complexity is to account + * for revA bug. + */ +static inline void +tioca_tlbflush(struct tioca_kernel *tioca_kernel) +{ + volatile uint64_t tmp; + volatile struct tioca *ca_base; + struct tioca_common *tioca_common; + + tioca_common = tioca_kernel->ca_common; + ca_base = (struct tioca *)tioca_common->ca_common.bs_base; + + /* + * Explicit flushes not needed if GART is in cached mode + */ + if (tioca_kernel->ca_gart_iscoherent) { + if (TIOCA_WAR_ENABLED(PV910244, tioca_common)) { + /* + * PV910244: RevA CA needs explicit flushes. + * Need to put GART into uncached mode before + * flushing otherwise the explicit flush is ignored. + * + * Alternate WAR would be to leave GART cached and + * touch every CL aligned GART entry. + */ + + ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM); + ca_base->ca_control2 |= CA_GART_FLUSH_TLB; + ca_base->ca_control2 |= + (0x2ull << CA_GART_MEM_PARAM_SHFT); + tmp = ca_base->ca_control2; + } + + return; + } + + /* + * Gart in uncached mode ... need an explicit flush. + */ + + ca_base->ca_control2 |= CA_GART_FLUSH_TLB; + tmp = ca_base->ca_control2; +} + +extern uint32_t tioca_gart_found; +extern int tioca_init_provider(void); +extern void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern); +#endif /* _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H */ -- cgit v1.2.3 From bf1cf98fa941fea5e630e341db4a294d531aaa3e Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Mon, 25 Apr 2005 11:42:39 -0700 Subject: [IA64-SGI] Change SAL call request code for SN systems Change the value of the SAL call number for a new SAL request. The initial implementation in the PROM did not match what the OS expected. Since the OS can run on PROMs that do not implement the new call, changing the call number avoids the issue. New PROMs will implement the new call number. (This avoids problems with the 4.05 PROM). Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- include/asm-ia64/sn/sn_sal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 88c31b53dc09..81a1cf1e4f5a 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -35,8 +35,8 @@ #define SN_SAL_PRINT_ERROR 0x02000012 #define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant #define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant -#define SN_SAL_GET_SN_INFO 0x0200001c #define SN_SAL_GET_SAPIC_INFO 0x0200001d +#define SN_SAL_GET_SN_INFO 0x0200001e #define SN_SAL_CONSOLE_PUTC 0x02000021 #define SN_SAL_CONSOLE_GETC 0x02000022 #define SN_SAL_CONSOLE_PUTS 0x02000023 -- cgit v1.2.3 From 4a5c13c7eb0d55bfd2cf3100c55f1e3d8df37576 Mon Sep 17 00:00:00 2001 From: Mark Goodwin Date: Mon, 25 Apr 2005 13:04:22 -0700 Subject: [IA64-SGI] Altix SN topology support for new chipsets and pci topology please accept this patch to the Altix SN platform topology export interface to support new chipsets and to export PCI topology. This follows on top of Jack Steiner's patch dated March 1st ("New chipset support for SN platform"). Signed-off-by: Mark Goodwin Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/sn2/sn_hwperf.c | 133 +++++++++++++++++++++++++++++++++--- include/asm-ia64/sn/sn_sal.h | 11 +++ 2 files changed, 135 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 197356460ee1..3bff99130d5e 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include static void *sn_hwperf_salheap = NULL; static int sn_hwperf_obj_cnt = 0; @@ -81,26 +83,45 @@ out: return e; } +static int sn_hwperf_location_to_bpos(char *location, + int *rack, int *bay, int *slot, int *slab) +{ + char type; + + /* first scan for an old style geoid string */ + if (sscanf(location, "%03d%c%02d#%d", + rack, &type, bay, slab) == 4) + *slot = 0; + else /* scan for a new bladed geoid string */ + if (sscanf(location, "%03d%c%02d^%02d#%d", + rack, &type, bay, slot, slab) != 5) + return -1; + /* success */ + return 0; +} + static int sn_hwperf_geoid_to_cnode(char *location) { int cnode; geoid_t geoid; moduleid_t module_id; - char type; - int rack, slot, slab; - int this_rack, this_slot, this_slab; + int rack, bay, slot, slab; + int this_rack, this_bay, this_slot, this_slab; - if (sscanf(location, "%03d%c%02d#%d", &rack, &type, &slot, &slab) != 4) + if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) return -1; for (cnode = 0; cnode < numionodes; cnode++) { geoid = cnodeid_get_geoid(cnode); module_id = geo_module(geoid); this_rack = MODULE_GET_RACK(module_id); - this_slot = MODULE_GET_BPOS(module_id); + this_bay = MODULE_GET_BPOS(module_id); + this_slot = 0; /* XXX */ this_slab = geo_slab(geoid); - if (rack == this_rack && slot == this_slot && slab == this_slab) + if (rack == this_rack && bay == this_bay && + slot == this_slot && slab == this_slab) { break; + } } return cnode < numionodes ? cnode : -1; @@ -153,11 +174,29 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj, return slabname; } +static void print_pci_topology(struct seq_file *s, + struct sn_hwperf_object_info *obj, int *ordinal, + char *pci_topo_buf, int len) +{ + char *p1; + char *p2; + + for (p1=pci_topo_buf; *p1 && p1 < pci_topo_buf + len;) { + if (!(p2 = strchr(p1, '\n'))) + break; + *p2 = '\0'; + seq_printf(s, "pcibus %d %s-%s\n", + *ordinal, obj->location, p1); + (*ordinal)++; + p1 = p2 + 1; + } +} + static int sn_topology_show(struct seq_file *s, void *d) { int sz; int pt; - int e; + int e = 0; int i; int j; const char *slabname; @@ -169,11 +208,46 @@ static int sn_topology_show(struct seq_file *s, void *d) struct sn_hwperf_object_info *p; struct sn_hwperf_object_info *obj = d; /* this object */ struct sn_hwperf_object_info *objs = s->private; /* all objects */ + int rack, bay, slot, slab; + u8 shubtype; + u8 system_size; + u8 sharing_size; + u8 partid; + u8 coher; + u8 nasid_shift; + u8 region_size; + u16 nasid_mask; + int nasid_msb; + char *pci_topo_buf; + int pci_bus_ordinal = 0; + static int pci_topo_buf_len = 256; if (obj == objs) { - seq_printf(s, "# sn_topology version 1\n"); + seq_printf(s, "# sn_topology version 2\n"); seq_printf(s, "# objtype ordinal location partition" " [attribute value [, ...]]\n"); + + if (ia64_sn_get_sn_info(0, + &shubtype, &nasid_mask, &nasid_shift, &system_size, + &sharing_size, &partid, &coher, ®ion_size)) + BUG(); + for (nasid_msb=63; nasid_msb > 0; nasid_msb--) { + if (((u64)nasid_mask << nasid_shift) & (1ULL << nasid_msb)) + break; + } + seq_printf(s, "partition %u %s local " + "shubtype %s, " + "nasid_mask 0x%016lx, " + "nasid_bits %d:%d, " + "system_size %d, " + "sharing_size %d, " + "coherency_domain %d, " + "region_size %d\n", + + partid, system_utsname.nodename, + shubtype ? "shub2" : "shub1", + (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift, + system_size, sharing_size, coher, region_size); } if (SN_HWPERF_FOREIGN(obj)) { @@ -181,7 +255,7 @@ static int sn_topology_show(struct seq_file *s, void *d) return 0; } - for (i = 0; obj->name[i]; i++) { + for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) { if (obj->name[i] == ' ') obj->name[i] = '_'; } @@ -221,6 +295,43 @@ static int sn_topology_show(struct seq_file *s, void *d) seq_putc(s, '\n'); } } + + /* + * PCI busses attached to this node, if any + */ + do { + if (!(pci_topo_buf = vmalloc(pci_topo_buf_len))) { + printk("sn_topology_show: kmalloc failed\n"); + break; + } + + if (sn_hwperf_location_to_bpos(obj->location, + &rack, &bay, &slot, &slab) != 0) + continue; + + e = ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab, + pci_topo_buf, pci_topo_buf_len); + + switch (e) { + case SALRET_NOT_IMPLEMENTED: + case SALRET_INVALID_ARG: + /* ignore, don't print anything */ + e = SN_HWPERF_OP_OK; + break; + + case SALRET_ERROR: + /* retry with a bigger buffer */ + pci_topo_buf_len += 256; + break; + + case SN_HWPERF_OP_OK: + /* export pci bus info */ + print_pci_topology(s, obj, &pci_bus_ordinal, + pci_topo_buf, pci_topo_buf_len); + break; + } + vfree(pci_topo_buf); + } while (e != SN_HWPERF_OP_OK && pci_topo_buf_len < 0x200000); } if (obj->ports) { @@ -397,6 +508,9 @@ static int sn_hwperf_map_err(int hwperf_err) break; case SN_HWPERF_OP_BUSY: + e = -EBUSY; + break; + case SN_HWPERF_OP_RECONFIGURE: e = -EAGAIN; break; @@ -549,6 +663,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) r = sn_hwperf_op_cpu(&op_info); if (r) { r = sn_hwperf_map_err(r); + a.v0 = v0; goto error; } break; diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 81a1cf1e4f5a..410d356b40da 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -74,6 +74,7 @@ #define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 #define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 #define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 +#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000059 #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 @@ -1012,4 +1013,14 @@ ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2, return (int) rv.status; } +static inline int +ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab, + char *buf, u64 len) +{ + struct ia64_sal_retval rv; + SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY, + rack, bay, slot, slab, buf, len, 0); + return (int) rv.status; +} + #endif /* _ASM_IA64_SN_SN_SAL_H */ -- cgit v1.2.3 From be539c73b54dcc9f54fb2c2b70e204c93b616c9b Mon Sep 17 00:00:00 2001 From: Colin Ngam Date: Mon, 25 Apr 2005 13:06:28 -0700 Subject: [IA64-SGI] Shub2 provides an addition of 2 External Interrupt events. Signed-off-by: Colin Ngam Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/irq.c | 15 ++------------- include/asm-ia64/sn/shub_mmr.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index b52d32975f2b..0f4e8138658f 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -82,20 +82,9 @@ static void sn_ack_irq(unsigned int irq) nasid = get_nasid(); event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED)); - if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) { - mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT); - } - if (event_occurred & SH_EVENT_OCCURRED_IPI_INT_MASK) { - mask |= (1 << SH_EVENT_OCCURRED_IPI_INT_SHFT); - } - if (event_occurred & SH_EVENT_OCCURRED_II_INT0_MASK) { - mask |= (1 << SH_EVENT_OCCURRED_II_INT0_SHFT); - } - if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) { - mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT); - } + mask = event_occurred & SH_ALL_INT_MASK; HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), - mask); + mask); __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); move_irq(irq); diff --git a/include/asm-ia64/sn/shub_mmr.h b/include/asm-ia64/sn/shub_mmr.h index 5c2fcf13d5ce..6ec37e816a9e 100644 --- a/include/asm-ia64/sn/shub_mmr.h +++ b/include/asm-ia64/sn/shub_mmr.h @@ -129,6 +129,23 @@ #define SH_EVENT_OCCURRED_II_INT1_SHFT 30 #define SH_EVENT_OCCURRED_II_INT1_MASK 0x0000000040000000 +/* SH2_EVENT_OCCURRED_EXTIO_INT2 */ +/* Description: Pending SHUB 2 EXT IO INT2 */ +#define SH2_EVENT_OCCURRED_EXTIO_INT2_SHFT 33 +#define SH2_EVENT_OCCURRED_EXTIO_INT2_MASK 0x0000000200000000 + +/* SH2_EVENT_OCCURRED_EXTIO_INT3 */ +/* Description: Pending SHUB 2 EXT IO INT3 */ +#define SH2_EVENT_OCCURRED_EXTIO_INT3_SHFT 34 +#define SH2_EVENT_OCCURRED_EXTIO_INT3_MASK 0x0000000400000000 + +#define SH_ALL_INT_MASK \ + (SH_EVENT_OCCURRED_UART_INT_MASK | SH_EVENT_OCCURRED_IPI_INT_MASK | \ + SH_EVENT_OCCURRED_II_INT0_MASK | SH_EVENT_OCCURRED_II_INT1_MASK | \ + SH_EVENT_OCCURRED_II_INT1_MASK | SH2_EVENT_OCCURRED_EXTIO_INT2_MASK | \ + SH2_EVENT_OCCURRED_EXTIO_INT3_MASK) + + /* ==================================================================== */ /* LEDS */ /* ==================================================================== */ -- cgit v1.2.3 From 658b32cad9ae087bd34f35a925fd75b76d663d4e Mon Sep 17 00:00:00 2001 From: Colin Ngam Date: Mon, 25 Apr 2005 13:07:00 -0700 Subject: [IA64-SGI] support variable length nasids in shub2 This patch enables our TIO IO chipset to support variable length nasids in Shub2 chipset. Signed-off-by: Colin Ngam Signed-off-by: Tony Luck --- include/asm-ia64/sn/addrs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h index c916bd22767a..ae0bc99d573e 100644 --- a/include/asm-ia64/sn/addrs.h +++ b/include/asm-ia64/sn/addrs.h @@ -154,8 +154,9 @@ * the chiplet id is zero. If we implement TIO-TIO dma, we might need * to insert a chiplet id into this macro. However, it is our belief * right now that this chiplet id will be ICE, which is also zero. + * Nasid starts on bit 40. */ -#define PHYS_TO_TIODMA(x) ( (((u64)(x) & NASID_MASK) << 2) | NODE_OFFSET(x)) +#define PHYS_TO_TIODMA(x) ( (((u64)(NASID_GET(x))) << 40) | NODE_OFFSET(x)) #define PHYS_TO_DMA(x) ( (((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x)) -- cgit v1.2.3 From 4944930ab748942e41ea4dc313fcb0946aee3f17 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 25 Apr 2005 13:08:30 -0700 Subject: [IA64] perfmon: make pfm_sysctl a global, and other cleanup - make pfm_sysctl a global such that it is possible to enable/disable debug printk in sampling formats using PFM_DEBUG. - remove unused pfm_debug_var variable - fix a bug in pfm_handle_work where an BUG_ON() could be triggered. There is a path where pfm_handle_work() can be called with interrupts enabled, i.e., when TIF_NEED_RESCHED is set. The fix correct the masking and unmasking of interrupts in pfm_handle_work() such that we restore the interrupt mask as it was upon entry. signed-off-by: stephane eranian Signed-off-by: Tony Luck --- arch/ia64/kernel/perfmon.c | 59 ++++++++++++++++----------------- arch/ia64/kernel/perfmon_default_smpl.c | 13 ++------ include/asm-ia64/perfmon.h | 12 +++++++ 3 files changed, 42 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 71147be3279c..376fcbc3f8da 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -479,14 +479,6 @@ typedef struct { #define PFM_CMD_ARG_MANY -1 /* cannot be zero */ -typedef struct { - int debug; /* turn on/off debugging via syslog */ - int debug_ovfl; /* turn on/off debug printk in overflow handler */ - int fastctxsw; /* turn on/off fast (unsecure) ctxsw */ - int expert_mode; /* turn on/off value checking */ - int debug_pfm_read; -} pfm_sysctl_t; - typedef struct { unsigned long pfm_spurious_ovfl_intr_count; /* keep track of spurious ovfl interrupts */ unsigned long pfm_replay_ovfl_intr_count; /* keep track of replayed ovfl interrupts */ @@ -514,8 +506,8 @@ static LIST_HEAD(pfm_buffer_fmt_list); static pmu_config_t *pmu_conf; /* sysctl() controls */ -static pfm_sysctl_t pfm_sysctl; -int pfm_debug_var; +pfm_sysctl_t pfm_sysctl; +EXPORT_SYMBOL(pfm_sysctl); static ctl_table pfm_ctl_table[]={ {1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,}, @@ -1576,7 +1568,7 @@ pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) goto abort_locked; } - DPRINT(("[%d] fd=%d type=%d\n", current->pid, msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type)); + DPRINT(("fd=%d type=%d\n", msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type)); ret = -EFAULT; if(copy_to_user(buf, msg, sizeof(pfm_msg_t)) == 0) ret = sizeof(pfm_msg_t); @@ -3695,8 +3687,6 @@ pfm_debug(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) pfm_sysctl.debug = m == 0 ? 0 : 1; - pfm_debug_var = pfm_sysctl.debug; - printk(KERN_INFO "perfmon debugging %s (timing reset)\n", pfm_sysctl.debug ? "on" : "off"); if (m == 0) { @@ -4996,13 +4986,21 @@ pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs) } static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds); - + /* + * pfm_handle_work() can be called with interrupts enabled + * (TIF_NEED_RESCHED) or disabled. The down_interruptible + * call may sleep, therefore we must re-enable interrupts + * to avoid deadlocks. It is safe to do so because this function + * is called ONLY when returning to user level (PUStk=1), in which case + * there is no risk of kernel stack overflow due to deep + * interrupt nesting. + */ void pfm_handle_work(void) { pfm_context_t *ctx; struct pt_regs *regs; - unsigned long flags; + unsigned long flags, dummy_flags; unsigned long ovfl_regs; unsigned int reason; int ret; @@ -5039,18 +5037,15 @@ pfm_handle_work(void) //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking; if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking; + /* + * restore interrupt mask to what it was on entry. + * Could be enabled/diasbled. + */ UNPROTECT_CTX(ctx, flags); - /* - * pfm_handle_work() is currently called with interrupts disabled. - * The down_interruptible call may sleep, therefore we - * must re-enable interrupts to avoid deadlocks. It is - * safe to do so because this function is called ONLY - * when returning to user level (PUStk=1), in which case - * there is no risk of kernel stack overflow due to deep - * interrupt nesting. - */ - BUG_ON(flags & IA64_PSR_I); + /* + * force interrupt enable because of down_interruptible() + */ local_irq_enable(); DPRINT(("before block sleeping\n")); @@ -5064,12 +5059,12 @@ pfm_handle_work(void) DPRINT(("after block sleeping ret=%d\n", ret)); /* - * disable interrupts to restore state we had upon entering - * this function + * lock context and mask interrupts again + * We save flags into a dummy because we may have + * altered interrupts mask compared to entry in this + * function. */ - local_irq_disable(); - - PROTECT_CTX(ctx, flags); + PROTECT_CTX(ctx, dummy_flags); /* * we need to read the ovfl_regs only after wake-up @@ -5095,7 +5090,9 @@ skip_blocking: ctx->ctx_ovfl_regs[0] = 0UL; nothing_to_do: - + /* + * restore flags as they were upon entry + */ UNPROTECT_CTX(ctx, flags); } diff --git a/arch/ia64/kernel/perfmon_default_smpl.c b/arch/ia64/kernel/perfmon_default_smpl.c index 965d29004555..344941db0a9e 100644 --- a/arch/ia64/kernel/perfmon_default_smpl.c +++ b/arch/ia64/kernel/perfmon_default_smpl.c @@ -20,24 +20,17 @@ MODULE_AUTHOR("Stephane Eranian "); MODULE_DESCRIPTION("perfmon default sampling format"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "debug"); - -MODULE_PARM(debug_ovfl, "i"); -MODULE_PARM_DESC(debug_ovfl, "debug ovfl"); - - #define DEFAULT_DEBUG 1 #ifdef DEFAULT_DEBUG #define DPRINT(a) \ do { \ - if (unlikely(debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ + if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ } while (0) #define DPRINT_ovfl(a) \ do { \ - if (unlikely(debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ + if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ } while (0) #else @@ -45,8 +38,6 @@ MODULE_PARM_DESC(debug_ovfl, "debug ovfl"); #define DPRINT_ovfl(a) #endif -static int debug, debug_ovfl; - static int default_validate(struct task_struct *task, unsigned int flags, int cpu, void *data) { diff --git a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h index 136c60e6bfcc..ed5416c5b1ac 100644 --- a/include/asm-ia64/perfmon.h +++ b/include/asm-ia64/perfmon.h @@ -254,6 +254,18 @@ extern int pfm_mod_write_dbrs(struct task_struct *task, void *req, unsigned int #define PFM_CPUINFO_DCR_PP 0x2 /* if set the system wide session has started */ #define PFM_CPUINFO_EXCL_IDLE 0x4 /* the system wide session excludes the idle task */ +/* + * sysctl control structure. visible to sampling formats + */ +typedef struct { + int debug; /* turn on/off debugging via syslog */ + int debug_ovfl; /* turn on/off debug printk in overflow handler */ + int fastctxsw; /* turn on/off fast (unsecure) ctxsw */ + int expert_mode; /* turn on/off value checking */ +} pfm_sysctl_t; +extern pfm_sysctl_t pfm_sysctl; + + #endif /* __KERNEL__ */ #endif /* _ASM_IA64_PERFMON_H */ -- cgit v1.2.3 From e1e19747ecce9117610b8f3b57a3e95734230319 Mon Sep 17 00:00:00 2001 From: Bruce Losure Date: Mon, 25 Apr 2005 13:09:41 -0700 Subject: [IA64-SGI] Bus driver for the CX port of SGI's TIO chip. This patch is to provide CX port infrastructure for SGI TIO-based h/w. Also a 'core services' driver for SGI FPGA-based h/w. Signed-off-by: Bruce Losure Signed-off-by: Tony Luck --- arch/ia64/configs/sn2_defconfig | 2 + arch/ia64/sn/kernel/Makefile | 1 + drivers/char/Kconfig | 14 + drivers/char/Makefile | 1 + drivers/char/mbcs.c | 849 ++++++++++++++++++++++++++++++++++++++++ drivers/char/mbcs.h | 553 ++++++++++++++++++++++++++ include/asm-ia64/sn/addrs.h | 3 + include/asm-ia64/sn/tiocx.h | 71 ++++ 8 files changed, 1494 insertions(+) create mode 100644 drivers/char/mbcs.c create mode 100644 drivers/char/mbcs.h create mode 100644 include/asm-ia64/sn/tiocx.h (limited to 'include') diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index bfeb952fe8e2..6ff7107fee4d 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -574,6 +574,8 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_N_HDLC is not set # CONFIG_STALDRV is not set CONFIG_SGI_SNSC=y +CONFIG_SGI_TIOCX=y +CONFIG_SGI_MBCS=m # # Serial drivers diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 6c7f4d9e8ea0..4f381fb25049 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile @@ -10,3 +10,4 @@ obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ huberror.o io_init.o iomv.o klconflib.o sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o +obj-$(CONFIG_SGI_TIOCX) += tiocx.o diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 096a1202ea07..97ac4edf4655 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -399,6 +399,20 @@ config SGI_SNSC controller communication from user space (you want this!), say Y. Otherwise, say N. +config SGI_TIOCX + bool "SGI TIO CX driver support" + depends on (IA64_SGI_SN2 || IA64_GENERIC) + help + If you have an SGI Altix and you have fpga devices attached + to your TIO, say Y here, otherwise say N. + +config SGI_MBCS + tristate "SGI FPGA Core Services driver support" + depends on (IA64_SGI_SN2 || IA64_GENERIC) + help + If you have an SGI Altix with an attached SABrick + say Y or M here, otherwise say N. + source "drivers/serial/Kconfig" config UNIX98_PTYS diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 54ed76af1a47..3ea8cc80ea3d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_MMTIMER) += mmtimer.o obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o +obj-$(CONFIG_SGI_MBCS) += mbcs.o obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c new file mode 100644 index 000000000000..ec7100556c50 --- /dev/null +++ b/drivers/char/mbcs.c @@ -0,0 +1,849 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved. + */ + +/* + * MOATB Core Services driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mbcs.h" + +#define MBCS_DEBUG 0 +#if MBCS_DEBUG +#define DBG(fmt...) printk(KERN_ALERT fmt) +#else +#define DBG(fmt...) +#endif +int mbcs_major; + +LIST_HEAD(soft_list); + +/* + * file operations + */ +struct file_operations mbcs_ops = { + .open = mbcs_open, + .llseek = mbcs_sram_llseek, + .read = mbcs_sram_read, + .write = mbcs_sram_write, + .mmap = mbcs_gscr_mmap, +}; + +struct mbcs_callback_arg { + int minor; + struct cx_dev *cx_dev; +}; + +static inline void mbcs_getdma_init(struct getdma *gdma) +{ + memset(gdma, 0, sizeof(struct getdma)); + gdma->DoneIntEnable = 1; +} + +static inline void mbcs_putdma_init(struct putdma *pdma) +{ + memset(pdma, 0, sizeof(struct putdma)); + pdma->DoneIntEnable = 1; +} + +static inline void mbcs_algo_init(struct algoblock *algo_soft) +{ + memset(algo_soft, 0, sizeof(struct algoblock)); +} + +static inline void mbcs_getdma_set(void *mmr, + uint64_t hostAddr, + uint64_t localAddr, + uint64_t localRamSel, + uint64_t numPkts, + uint64_t amoEnable, + uint64_t intrEnable, + uint64_t peerIO, + uint64_t amoHostDest, + uint64_t amoModType, uint64_t intrHostDest, + uint64_t intrVector) +{ + union dma_control rdma_control; + union dma_amo_dest amo_dest; + union intr_dest intr_dest; + union dma_localaddr local_addr; + union dma_hostaddr host_addr; + + rdma_control.dma_control_reg = 0; + amo_dest.dma_amo_dest_reg = 0; + intr_dest.intr_dest_reg = 0; + local_addr.dma_localaddr_reg = 0; + host_addr.dma_hostaddr_reg = 0; + + host_addr.dma_sys_addr = hostAddr; + MBCS_MMR_SET(mmr, MBCS_RD_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg); + + local_addr.dma_ram_addr = localAddr; + local_addr.dma_ram_sel = localRamSel; + MBCS_MMR_SET(mmr, MBCS_RD_DMA_LOC_ADDR, local_addr.dma_localaddr_reg); + + rdma_control.dma_op_length = numPkts; + rdma_control.done_amo_en = amoEnable; + rdma_control.done_int_en = intrEnable; + rdma_control.pio_mem_n = peerIO; + MBCS_MMR_SET(mmr, MBCS_RD_DMA_CTRL, rdma_control.dma_control_reg); + + amo_dest.dma_amo_sys_addr = amoHostDest; + amo_dest.dma_amo_mod_type = amoModType; + MBCS_MMR_SET(mmr, MBCS_RD_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg); + + intr_dest.address = intrHostDest; + intr_dest.int_vector = intrVector; + MBCS_MMR_SET(mmr, MBCS_RD_DMA_INT_DEST, intr_dest.intr_dest_reg); + +} + +static inline void mbcs_putdma_set(void *mmr, + uint64_t hostAddr, + uint64_t localAddr, + uint64_t localRamSel, + uint64_t numPkts, + uint64_t amoEnable, + uint64_t intrEnable, + uint64_t peerIO, + uint64_t amoHostDest, + uint64_t amoModType, + uint64_t intrHostDest, uint64_t intrVector) +{ + union dma_control wdma_control; + union dma_amo_dest amo_dest; + union intr_dest intr_dest; + union dma_localaddr local_addr; + union dma_hostaddr host_addr; + + wdma_control.dma_control_reg = 0; + amo_dest.dma_amo_dest_reg = 0; + intr_dest.intr_dest_reg = 0; + local_addr.dma_localaddr_reg = 0; + host_addr.dma_hostaddr_reg = 0; + + host_addr.dma_sys_addr = hostAddr; + MBCS_MMR_SET(mmr, MBCS_WR_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg); + + local_addr.dma_ram_addr = localAddr; + local_addr.dma_ram_sel = localRamSel; + MBCS_MMR_SET(mmr, MBCS_WR_DMA_LOC_ADDR, local_addr.dma_localaddr_reg); + + wdma_control.dma_op_length = numPkts; + wdma_control.done_amo_en = amoEnable; + wdma_control.done_int_en = intrEnable; + wdma_control.pio_mem_n = peerIO; + MBCS_MMR_SET(mmr, MBCS_WR_DMA_CTRL, wdma_control.dma_control_reg); + + amo_dest.dma_amo_sys_addr = amoHostDest; + amo_dest.dma_amo_mod_type = amoModType; + MBCS_MMR_SET(mmr, MBCS_WR_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg); + + intr_dest.address = intrHostDest; + intr_dest.int_vector = intrVector; + MBCS_MMR_SET(mmr, MBCS_WR_DMA_INT_DEST, intr_dest.intr_dest_reg); + +} + +static inline void mbcs_algo_set(void *mmr, + uint64_t amoHostDest, + uint64_t amoModType, + uint64_t intrHostDest, + uint64_t intrVector, uint64_t algoStepCount) +{ + union dma_amo_dest amo_dest; + union intr_dest intr_dest; + union algo_step step; + + step.algo_step_reg = 0; + intr_dest.intr_dest_reg = 0; + amo_dest.dma_amo_dest_reg = 0; + + amo_dest.dma_amo_sys_addr = amoHostDest; + amo_dest.dma_amo_mod_type = amoModType; + MBCS_MMR_SET(mmr, MBCS_ALG_AMO_DEST, amo_dest.dma_amo_dest_reg); + + intr_dest.address = intrHostDest; + intr_dest.int_vector = intrVector; + MBCS_MMR_SET(mmr, MBCS_ALG_INT_DEST, intr_dest.intr_dest_reg); + + step.alg_step_cnt = algoStepCount; + MBCS_MMR_SET(mmr, MBCS_ALG_STEP, step.algo_step_reg); +} + +static inline int mbcs_getdma_start(struct mbcs_soft *soft) +{ + void *mmr_base; + struct getdma *gdma; + uint64_t numPkts; + union cm_control cm_control; + + mmr_base = soft->mmr_base; + gdma = &soft->getdma; + + /* check that host address got setup */ + if (!gdma->hostAddr) + return -1; + + numPkts = + (gdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE; + + /* program engine */ + mbcs_getdma_set(mmr_base, tiocx_dma_addr(gdma->hostAddr), + gdma->localAddr, + (gdma->localAddr < MB2) ? 0 : + (gdma->localAddr < MB4) ? 1 : + (gdma->localAddr < MB6) ? 2 : 3, + numPkts, + gdma->DoneAmoEnable, + gdma->DoneIntEnable, + gdma->peerIO, + gdma->amoHostDest, + gdma->amoModType, + gdma->intrHostDest, gdma->intrVector); + + /* start engine */ + cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL); + cm_control.rd_dma_go = 1; + MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg); + + return 0; + +} + +static inline int mbcs_putdma_start(struct mbcs_soft *soft) +{ + void *mmr_base; + struct putdma *pdma; + uint64_t numPkts; + union cm_control cm_control; + + mmr_base = soft->mmr_base; + pdma = &soft->putdma; + + /* check that host address got setup */ + if (!pdma->hostAddr) + return -1; + + numPkts = + (pdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE; + + /* program engine */ + mbcs_putdma_set(mmr_base, tiocx_dma_addr(pdma->hostAddr), + pdma->localAddr, + (pdma->localAddr < MB2) ? 0 : + (pdma->localAddr < MB4) ? 1 : + (pdma->localAddr < MB6) ? 2 : 3, + numPkts, + pdma->DoneAmoEnable, + pdma->DoneIntEnable, + pdma->peerIO, + pdma->amoHostDest, + pdma->amoModType, + pdma->intrHostDest, pdma->intrVector); + + /* start engine */ + cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL); + cm_control.wr_dma_go = 1; + MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg); + + return 0; + +} + +static inline int mbcs_algo_start(struct mbcs_soft *soft) +{ + struct algoblock *algo_soft = &soft->algo; + void *mmr_base = soft->mmr_base; + union cm_control cm_control; + + if (down_interruptible(&soft->algolock)) + return -ERESTARTSYS; + + atomic_set(&soft->algo_done, 0); + + mbcs_algo_set(mmr_base, + algo_soft->amoHostDest, + algo_soft->amoModType, + algo_soft->intrHostDest, + algo_soft->intrVector, algo_soft->algoStepCount); + + /* start algorithm */ + cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL); + cm_control.alg_done_int_en = 1; + cm_control.alg_go = 1; + MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg); + + up(&soft->algolock); + + return 0; +} + +static inline ssize_t +do_mbcs_sram_dmawrite(struct mbcs_soft *soft, uint64_t hostAddr, + size_t len, loff_t * off) +{ + int rv = 0; + + if (down_interruptible(&soft->dmawritelock)) + return -ERESTARTSYS; + + atomic_set(&soft->dmawrite_done, 0); + + soft->putdma.hostAddr = hostAddr; + soft->putdma.localAddr = *off; + soft->putdma.bytes = len; + + if (mbcs_putdma_start(soft) < 0) { + DBG(KERN_ALERT "do_mbcs_sram_dmawrite: " + "mbcs_putdma_start failed\n"); + rv = -EAGAIN; + goto dmawrite_exit; + } + + if (wait_event_interruptible(soft->dmawrite_queue, + atomic_read(&soft->dmawrite_done))) { + rv = -ERESTARTSYS; + goto dmawrite_exit; + } + + rv = len; + *off += len; + +dmawrite_exit: + up(&soft->dmawritelock); + + return rv; +} + +static inline ssize_t +do_mbcs_sram_dmaread(struct mbcs_soft *soft, uint64_t hostAddr, + size_t len, loff_t * off) +{ + int rv = 0; + + if (down_interruptible(&soft->dmareadlock)) + return -ERESTARTSYS; + + atomic_set(&soft->dmawrite_done, 0); + + soft->getdma.hostAddr = hostAddr; + soft->getdma.localAddr = *off; + soft->getdma.bytes = len; + + if (mbcs_getdma_start(soft) < 0) { + DBG(KERN_ALERT "mbcs_strategy: mbcs_getdma_start failed\n"); + rv = -EAGAIN; + goto dmaread_exit; + } + + if (wait_event_interruptible(soft->dmaread_queue, + atomic_read(&soft->dmaread_done))) { + rv = -ERESTARTSYS; + goto dmaread_exit; + } + + rv = len; + *off += len; + +dmaread_exit: + up(&soft->dmareadlock); + + return rv; +} + +int mbcs_open(struct inode *ip, struct file *fp) +{ + struct mbcs_soft *soft; + int minor; + + minor = iminor(ip); + + list_for_each_entry(soft, &soft_list, list) { + if (soft->nasid == minor) { + fp->private_data = soft->cxdev; + return 0; + } + } + + return -ENODEV; +} + +ssize_t mbcs_sram_read(struct file * fp, char *buf, size_t len, loff_t * off) +{ + struct cx_dev *cx_dev = fp->private_data; + struct mbcs_soft *soft = cx_dev->soft; + uint64_t hostAddr; + int rv = 0; + + hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len)); + if (hostAddr == 0) + return -ENOMEM; + + rv = do_mbcs_sram_dmawrite(soft, hostAddr, len, off); + if (rv < 0) + goto exit; + + if (copy_to_user(buf, (void *)hostAddr, len)) + rv = -EFAULT; + + exit: + free_pages(hostAddr, get_order(len)); + + return rv; +} + +ssize_t +mbcs_sram_write(struct file * fp, const char *buf, size_t len, loff_t * off) +{ + struct cx_dev *cx_dev = fp->private_data; + struct mbcs_soft *soft = cx_dev->soft; + uint64_t hostAddr; + int rv = 0; + + hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len)); + if (hostAddr == 0) + return -ENOMEM; + + if (copy_from_user((void *)hostAddr, buf, len)) { + rv = -EFAULT; + goto exit; + } + + rv = do_mbcs_sram_dmaread(soft, hostAddr, len, off); + + exit: + free_pages(hostAddr, get_order(len)); + + return rv; +} + +loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence) +{ + loff_t newpos; + + switch (whence) { + case 0: /* SEEK_SET */ + newpos = off; + break; + + case 1: /* SEEK_CUR */ + newpos = filp->f_pos + off; + break; + + case 2: /* SEEK_END */ + newpos = MBCS_SRAM_SIZE + off; + break; + + default: /* can't happen */ + return -EINVAL; + } + + if (newpos < 0) + return -EINVAL; + + filp->f_pos = newpos; + + return newpos; +} + +static uint64_t mbcs_pioaddr(struct mbcs_soft *soft, uint64_t offset) +{ + uint64_t mmr_base; + + mmr_base = (uint64_t) (soft->mmr_base + offset); + + return mmr_base; +} + +static void mbcs_debug_pioaddr_set(struct mbcs_soft *soft) +{ + soft->debug_addr = mbcs_pioaddr(soft, MBCS_DEBUG_START); +} + +static void mbcs_gscr_pioaddr_set(struct mbcs_soft *soft) +{ + soft->gscr_addr = mbcs_pioaddr(soft, MBCS_GSCR_START); +} + +int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma) +{ + struct cx_dev *cx_dev = fp->private_data; + struct mbcs_soft *soft = cx_dev->soft; + + if (vma->vm_pgoff != 0) + return -EINVAL; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ + if (remap_pfn_range(vma, + vma->vm_start, + __pa(soft->gscr_addr) >> PAGE_SHIFT, + PAGE_SIZE, + vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} + +/** + * mbcs_completion_intr_handler - Primary completion handler. + * @irq: irq + * @arg: soft struct for device + * @ep: regs + * + */ +static irqreturn_t +mbcs_completion_intr_handler(int irq, void *arg, struct pt_regs *ep) +{ + struct mbcs_soft *soft = (struct mbcs_soft *)arg; + void *mmr_base; + union cm_status cm_status; + union cm_control cm_control; + + mmr_base = soft->mmr_base; + cm_status.cm_status_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_STATUS); + + if (cm_status.rd_dma_done) { + /* stop dma-read engine, clear status */ + cm_control.cm_control_reg = + MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL); + cm_control.rd_dma_clr = 1; + MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, + cm_control.cm_control_reg); + atomic_set(&soft->dmaread_done, 1); + wake_up(&soft->dmaread_queue); + } + if (cm_status.wr_dma_done) { + /* stop dma-write engine, clear status */ + cm_control.cm_control_reg = + MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL); + cm_control.wr_dma_clr = 1; + MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, + cm_control.cm_control_reg); + atomic_set(&soft->dmawrite_done, 1); + wake_up(&soft->dmawrite_queue); + } + if (cm_status.alg_done) { + /* clear status */ + cm_control.cm_control_reg = + MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL); + cm_control.alg_done_clr = 1; + MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, + cm_control.cm_control_reg); + atomic_set(&soft->algo_done, 1); + wake_up(&soft->algo_queue); + } + + return IRQ_HANDLED; +} + +/** + * mbcs_intr_alloc - Allocate interrupts. + * @dev: device pointer + * + */ +static int mbcs_intr_alloc(struct cx_dev *dev) +{ + struct sn_irq_info *sn_irq; + struct mbcs_soft *soft; + struct getdma *getdma; + struct putdma *putdma; + struct algoblock *algo; + + soft = dev->soft; + getdma = &soft->getdma; + putdma = &soft->putdma; + algo = &soft->algo; + + soft->get_sn_irq = NULL; + soft->put_sn_irq = NULL; + soft->algo_sn_irq = NULL; + + sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1); + if (sn_irq == NULL) + return -EAGAIN; + soft->get_sn_irq = sn_irq; + getdma->intrHostDest = sn_irq->irq_xtalkaddr; + getdma->intrVector = sn_irq->irq_irq; + if (request_irq(sn_irq->irq_irq, + (void *)mbcs_completion_intr_handler, SA_SHIRQ, + "MBCS get intr", (void *)soft)) { + tiocx_irq_free(soft->get_sn_irq); + return -EAGAIN; + } + + sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1); + if (sn_irq == NULL) { + free_irq(soft->get_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->get_sn_irq); + return -EAGAIN; + } + soft->put_sn_irq = sn_irq; + putdma->intrHostDest = sn_irq->irq_xtalkaddr; + putdma->intrVector = sn_irq->irq_irq; + if (request_irq(sn_irq->irq_irq, + (void *)mbcs_completion_intr_handler, SA_SHIRQ, + "MBCS put intr", (void *)soft)) { + tiocx_irq_free(soft->put_sn_irq); + free_irq(soft->get_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->get_sn_irq); + return -EAGAIN; + } + + sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1); + if (sn_irq == NULL) { + free_irq(soft->put_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->put_sn_irq); + free_irq(soft->get_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->get_sn_irq); + return -EAGAIN; + } + soft->algo_sn_irq = sn_irq; + algo->intrHostDest = sn_irq->irq_xtalkaddr; + algo->intrVector = sn_irq->irq_irq; + if (request_irq(sn_irq->irq_irq, + (void *)mbcs_completion_intr_handler, SA_SHIRQ, + "MBCS algo intr", (void *)soft)) { + tiocx_irq_free(soft->algo_sn_irq); + free_irq(soft->put_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->put_sn_irq); + free_irq(soft->get_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->get_sn_irq); + return -EAGAIN; + } + + return 0; +} + +/** + * mbcs_intr_dealloc - Remove interrupts. + * @dev: device pointer + * + */ +static void mbcs_intr_dealloc(struct cx_dev *dev) +{ + struct mbcs_soft *soft; + + soft = dev->soft; + + free_irq(soft->get_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->get_sn_irq); + free_irq(soft->put_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->put_sn_irq); + free_irq(soft->algo_sn_irq->irq_irq, soft); + tiocx_irq_free(soft->algo_sn_irq); +} + +static inline int mbcs_hw_init(struct mbcs_soft *soft) +{ + void *mmr_base = soft->mmr_base; + union cm_control cm_control; + union cm_req_timeout cm_req_timeout; + uint64_t err_stat; + + cm_req_timeout.cm_req_timeout_reg = + MBCS_MMR_GET(mmr_base, MBCS_CM_REQ_TOUT); + + cm_req_timeout.time_out = MBCS_CM_CONTROL_REQ_TOUT_MASK; + MBCS_MMR_SET(mmr_base, MBCS_CM_REQ_TOUT, + cm_req_timeout.cm_req_timeout_reg); + + mbcs_gscr_pioaddr_set(soft); + mbcs_debug_pioaddr_set(soft); + + /* clear errors */ + err_stat = MBCS_MMR_GET(mmr_base, MBCS_CM_ERR_STAT); + MBCS_MMR_SET(mmr_base, MBCS_CM_CLR_ERR_STAT, err_stat); + MBCS_MMR_ZERO(mmr_base, MBCS_CM_ERROR_DETAIL1); + + /* enable interrupts */ + /* turn off 2^23 (INT_EN_PIO_REQ_ADDR_INV) */ + MBCS_MMR_SET(mmr_base, MBCS_CM_ERR_INT_EN, 0x3ffffff7e00ffUL); + + /* arm status regs and clear engines */ + cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL); + cm_control.rearm_stat_regs = 1; + cm_control.alg_clr = 1; + cm_control.wr_dma_clr = 1; + cm_control.rd_dma_clr = 1; + + MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg); + + return 0; +} + +static ssize_t show_algo(struct device *dev, char *buf) +{ + struct cx_dev *cx_dev = to_cx_dev(dev); + struct mbcs_soft *soft = cx_dev->soft; + uint64_t debug0; + + /* + * By convention, the first debug register contains the + * algorithm number and revision. + */ + debug0 = *(uint64_t *) soft->debug_addr; + + return sprintf(buf, "0x%lx 0x%lx\n", + (debug0 >> 32), (debug0 & 0xffffffff)); +} + +static ssize_t store_algo(struct device *dev, const char *buf, size_t count) +{ + int n; + struct cx_dev *cx_dev = to_cx_dev(dev); + struct mbcs_soft *soft = cx_dev->soft; + + if (count <= 0) + return 0; + + n = simple_strtoul(buf, NULL, 0); + + if (n == 1) { + mbcs_algo_start(soft); + if (wait_event_interruptible(soft->algo_queue, + atomic_read(&soft->algo_done))) + return -ERESTARTSYS; + } + + return count; +} + +DEVICE_ATTR(algo, 0644, show_algo, store_algo); + +/** + * mbcs_probe - Initialize for device + * @dev: device pointer + * @device_id: id table pointer + * + */ +static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id) +{ + struct mbcs_soft *soft; + + dev->soft = NULL; + + soft = kcalloc(1, sizeof(struct mbcs_soft), GFP_KERNEL); + if (soft == NULL) + return -ENOMEM; + + soft->nasid = dev->cx_id.nasid; + list_add(&soft->list, &soft_list); + soft->mmr_base = (void *)tiocx_swin_base(dev->cx_id.nasid); + dev->soft = soft; + soft->cxdev = dev; + + init_waitqueue_head(&soft->dmawrite_queue); + init_waitqueue_head(&soft->dmaread_queue); + init_waitqueue_head(&soft->algo_queue); + + init_MUTEX(&soft->dmawritelock); + init_MUTEX(&soft->dmareadlock); + init_MUTEX(&soft->algolock); + + mbcs_getdma_init(&soft->getdma); + mbcs_putdma_init(&soft->putdma); + mbcs_algo_init(&soft->algo); + + mbcs_hw_init(soft); + + /* Allocate interrupts */ + mbcs_intr_alloc(dev); + + device_create_file(&dev->dev, &dev_attr_algo); + + return 0; +} + +static int mbcs_remove(struct cx_dev *dev) +{ + if (dev->soft) { + mbcs_intr_dealloc(dev); + kfree(dev->soft); + } + + device_remove_file(&dev->dev, &dev_attr_algo); + + return 0; +} + +const struct cx_device_id __devinitdata mbcs_id_table[] = { + { + .part_num = MBCS_PART_NUM, + .mfg_num = MBCS_MFG_NUM, + }, + { + .part_num = MBCS_PART_NUM_ALG0, + .mfg_num = MBCS_MFG_NUM, + }, + {0, 0} +}; + +MODULE_DEVICE_TABLE(cx, mbcs_id_table); + +struct cx_drv mbcs_driver = { + .name = DEVICE_NAME, + .id_table = mbcs_id_table, + .probe = mbcs_probe, + .remove = mbcs_remove, +}; + +static void __exit mbcs_exit(void) +{ + int rv; + + rv = unregister_chrdev(mbcs_major, DEVICE_NAME); + if (rv < 0) + DBG(KERN_ALERT "Error in unregister_chrdev: %d\n", rv); + + cx_driver_unregister(&mbcs_driver); +} + +static int __init mbcs_init(void) +{ + int rv; + + // Put driver into chrdevs[]. Get major number. + rv = register_chrdev(mbcs_major, DEVICE_NAME, &mbcs_ops); + if (rv < 0) { + DBG(KERN_ALERT "mbcs_init: can't get major number. %d\n", rv); + return rv; + } + mbcs_major = rv; + + return cx_driver_register(&mbcs_driver); +} + +module_init(mbcs_init); +module_exit(mbcs_exit); + +MODULE_AUTHOR("Bruce Losure "); +MODULE_DESCRIPTION("Driver for MOATB Core Services"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/mbcs.h b/drivers/char/mbcs.h new file mode 100644 index 000000000000..844644d201c5 --- /dev/null +++ b/drivers/char/mbcs.h @@ -0,0 +1,553 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef __MBCS_H__ +#define __MBCS_H__ + +/* + * General macros + */ +#define MB (1024*1024) +#define MB2 (2*MB) +#define MB4 (4*MB) +#define MB6 (6*MB) + +/* + * Offsets and masks + */ +#define MBCS_CM_ID 0x0000 /* Identification */ +#define MBCS_CM_STATUS 0x0008 /* Status */ +#define MBCS_CM_ERROR_DETAIL1 0x0010 /* Error Detail1 */ +#define MBCS_CM_ERROR_DETAIL2 0x0018 /* Error Detail2 */ +#define MBCS_CM_CONTROL 0x0020 /* Control */ +#define MBCS_CM_REQ_TOUT 0x0028 /* Request Time-out */ +#define MBCS_CM_ERR_INT_DEST 0x0038 /* Error Interrupt Destination */ +#define MBCS_CM_TARG_FL 0x0050 /* Target Flush */ +#define MBCS_CM_ERR_STAT 0x0060 /* Error Status */ +#define MBCS_CM_CLR_ERR_STAT 0x0068 /* Clear Error Status */ +#define MBCS_CM_ERR_INT_EN 0x0070 /* Error Interrupt Enable */ +#define MBCS_RD_DMA_SYS_ADDR 0x0100 /* Read DMA System Address */ +#define MBCS_RD_DMA_LOC_ADDR 0x0108 /* Read DMA Local Address */ +#define MBCS_RD_DMA_CTRL 0x0110 /* Read DMA Control */ +#define MBCS_RD_DMA_AMO_DEST 0x0118 /* Read DMA AMO Destination */ +#define MBCS_RD_DMA_INT_DEST 0x0120 /* Read DMA Interrupt Destination */ +#define MBCS_RD_DMA_AUX_STAT 0x0130 /* Read DMA Auxillary Status */ +#define MBCS_WR_DMA_SYS_ADDR 0x0200 /* Write DMA System Address */ +#define MBCS_WR_DMA_LOC_ADDR 0x0208 /* Write DMA Local Address */ +#define MBCS_WR_DMA_CTRL 0x0210 /* Write DMA Control */ +#define MBCS_WR_DMA_AMO_DEST 0x0218 /* Write DMA AMO Destination */ +#define MBCS_WR_DMA_INT_DEST 0x0220 /* Write DMA Interrupt Destination */ +#define MBCS_WR_DMA_AUX_STAT 0x0230 /* Write DMA Auxillary Status */ +#define MBCS_ALG_AMO_DEST 0x0300 /* Algorithm AMO Destination */ +#define MBCS_ALG_INT_DEST 0x0308 /* Algorithm Interrupt Destination */ +#define MBCS_ALG_OFFSETS 0x0310 +#define MBCS_ALG_STEP 0x0318 /* Algorithm Step */ + +#define MBCS_GSCR_START 0x0000000 +#define MBCS_DEBUG_START 0x0100000 +#define MBCS_RAM0_START 0x0200000 +#define MBCS_RAM1_START 0x0400000 +#define MBCS_RAM2_START 0x0600000 + +#define MBCS_CM_CONTROL_REQ_TOUT_MASK 0x0000000000ffffffUL +//#define PIO_BASE_ADDR_BASE_OFFSET_MASK 0x00fffffffff00000UL + +#define MBCS_SRAM_SIZE (1024*1024) +#define MBCS_CACHELINE_SIZE 128 + +/* + * MMR get's and put's + */ +#define MBCS_MMR_ADDR(mmr_base, offset)((uint64_t *)(mmr_base + offset)) +#define MBCS_MMR_SET(mmr_base, offset, value) { \ + uint64_t *mbcs_mmr_set_u64p, readback; \ + mbcs_mmr_set_u64p = (uint64_t *)(mmr_base + offset); \ + *mbcs_mmr_set_u64p = value; \ + readback = *mbcs_mmr_set_u64p; \ +} +#define MBCS_MMR_GET(mmr_base, offset) *(uint64_t *)(mmr_base + offset) +#define MBCS_MMR_ZERO(mmr_base, offset) MBCS_MMR_SET(mmr_base, offset, 0) + +/* + * MBCS mmr structures + */ +union cm_id { + uint64_t cm_id_reg; + struct { + uint64_t always_one:1, // 0 + mfg_id:11, // 11:1 + part_num:16, // 27:12 + bitstream_rev:8, // 35:28 + :28; // 63:36 + }; +}; + +union cm_status { + uint64_t cm_status_reg; + struct { + uint64_t pending_reads:8, // 7:0 + pending_writes:8, // 15:8 + ice_rsp_credits:8, // 23:16 + ice_req_credits:8, // 31:24 + cm_req_credits:8, // 39:32 + :1, // 40 + rd_dma_in_progress:1, // 41 + rd_dma_done:1, // 42 + :1, // 43 + wr_dma_in_progress:1, // 44 + wr_dma_done:1, // 45 + alg_waiting:1, // 46 + alg_pipe_running:1, // 47 + alg_done:1, // 48 + :3, // 51:49 + pending_int_reqs:8, // 59:52 + :3, // 62:60 + alg_half_speed_sel:1; // 63 + }; +}; + +union cm_error_detail1 { + uint64_t cm_error_detail1_reg; + struct { + uint64_t packet_type:4, // 3:0 + source_id:2, // 5:4 + data_size:2, // 7:6 + tnum:8, // 15:8 + byte_enable:8, // 23:16 + gfx_cred:8, // 31:24 + read_type:2, // 33:32 + pio_or_memory:1, // 34 + head_cw_error:1, // 35 + :12, // 47:36 + head_error_bit:1, // 48 + data_error_bit:1, // 49 + :13, // 62:50 + valid:1; // 63 + }; +}; + +union cm_error_detail2 { + uint64_t cm_error_detail2_reg; + struct { + uint64_t address:56, // 55:0 + :8; // 63:56 + }; +}; + +union cm_control { + uint64_t cm_control_reg; + struct { + uint64_t cm_id:2, // 1:0 + :2, // 3:2 + max_trans:5, // 8:4 + :3, // 11:9 + address_mode:1, // 12 + :7, // 19:13 + credit_limit:8, // 27:20 + :5, // 32:28 + rearm_stat_regs:1, // 33 + prescalar_byp:1, // 34 + force_gap_war:1, // 35 + rd_dma_go:1, // 36 + wr_dma_go:1, // 37 + alg_go:1, // 38 + rd_dma_clr:1, // 39 + wr_dma_clr:1, // 40 + alg_clr:1, // 41 + :2, // 43:42 + alg_wait_step:1, // 44 + alg_done_amo_en:1, // 45 + alg_done_int_en:1, // 46 + :1, // 47 + alg_sram0_locked:1, // 48 + alg_sram1_locked:1, // 49 + alg_sram2_locked:1, // 50 + alg_done_clr:1, // 51 + :12; // 63:52 + }; +}; + +union cm_req_timeout { + uint64_t cm_req_timeout_reg; + struct { + uint64_t time_out:24, // 23:0 + :40; // 63:24 + }; +}; + +union intr_dest { + uint64_t intr_dest_reg; + struct { + uint64_t address:56, // 55:0 + int_vector:8; // 63:56 + }; +}; + +union cm_error_status { + uint64_t cm_error_status_reg; + struct { + uint64_t ecc_sbe:1, // 0 + ecc_mbe:1, // 1 + unsupported_req:1, // 2 + unexpected_rsp:1, // 3 + bad_length:1, // 4 + bad_datavalid:1, // 5 + buffer_overflow:1, // 6 + request_timeout:1, // 7 + :8, // 15:8 + head_inv_data_size:1, // 16 + rsp_pactype_inv:1, // 17 + head_sb_err:1, // 18 + missing_head:1, // 19 + head_inv_rd_type:1, // 20 + head_cmd_err_bit:1, // 21 + req_addr_align_inv:1, // 22 + pio_req_addr_inv:1, // 23 + req_range_dsize_inv:1, // 24 + early_term:1, // 25 + early_tail:1, // 26 + missing_tail:1, // 27 + data_flit_sb_err:1, // 28 + cm2hcm_req_cred_of:1, // 29 + cm2hcm_rsp_cred_of:1, // 30 + rx_bad_didn:1, // 31 + rd_dma_err_rsp:1, // 32 + rd_dma_tnum_tout:1, // 33 + rd_dma_multi_tnum_tou:1, // 34 + wr_dma_err_rsp:1, // 35 + wr_dma_tnum_tout:1, // 36 + wr_dma_multi_tnum_tou:1, // 37 + alg_data_overflow:1, // 38 + alg_data_underflow:1, // 39 + ram0_access_conflict:1, // 40 + ram1_access_conflict:1, // 41 + ram2_access_conflict:1, // 42 + ram0_perr:1, // 43 + ram1_perr:1, // 44 + ram2_perr:1, // 45 + int_gen_rsp_err:1, // 46 + int_gen_tnum_tout:1, // 47 + rd_dma_prog_err:1, // 48 + wr_dma_prog_err:1, // 49 + :14; // 63:50 + }; +}; + +union cm_clr_error_status { + uint64_t cm_clr_error_status_reg; + struct { + uint64_t clr_ecc_sbe:1, // 0 + clr_ecc_mbe:1, // 1 + clr_unsupported_req:1, // 2 + clr_unexpected_rsp:1, // 3 + clr_bad_length:1, // 4 + clr_bad_datavalid:1, // 5 + clr_buffer_overflow:1, // 6 + clr_request_timeout:1, // 7 + :8, // 15:8 + clr_head_inv_data_siz:1, // 16 + clr_rsp_pactype_inv:1, // 17 + clr_head_sb_err:1, // 18 + clr_missing_head:1, // 19 + clr_head_inv_rd_type:1, // 20 + clr_head_cmd_err_bit:1, // 21 + clr_req_addr_align_in:1, // 22 + clr_pio_req_addr_inv:1, // 23 + clr_req_range_dsize_i:1, // 24 + clr_early_term:1, // 25 + clr_early_tail:1, // 26 + clr_missing_tail:1, // 27 + clr_data_flit_sb_err:1, // 28 + clr_cm2hcm_req_cred_o:1, // 29 + clr_cm2hcm_rsp_cred_o:1, // 30 + clr_rx_bad_didn:1, // 31 + clr_rd_dma_err_rsp:1, // 32 + clr_rd_dma_tnum_tout:1, // 33 + clr_rd_dma_multi_tnum:1, // 34 + clr_wr_dma_err_rsp:1, // 35 + clr_wr_dma_tnum_tout:1, // 36 + clr_wr_dma_multi_tnum:1, // 37 + clr_alg_data_overflow:1, // 38 + clr_alg_data_underflo:1, // 39 + clr_ram0_access_confl:1, // 40 + clr_ram1_access_confl:1, // 41 + clr_ram2_access_confl:1, // 42 + clr_ram0_perr:1, // 43 + clr_ram1_perr:1, // 44 + clr_ram2_perr:1, // 45 + clr_int_gen_rsp_err:1, // 46 + clr_int_gen_tnum_tout:1, // 47 + clr_rd_dma_prog_err:1, // 48 + clr_wr_dma_prog_err:1, // 49 + :14; // 63:50 + }; +}; + +union cm_error_intr_enable { + uint64_t cm_error_intr_enable_reg; + struct { + uint64_t int_en_ecc_sbe:1, // 0 + int_en_ecc_mbe:1, // 1 + int_en_unsupported_re:1, // 2 + int_en_unexpected_rsp:1, // 3 + int_en_bad_length:1, // 4 + int_en_bad_datavalid:1, // 5 + int_en_buffer_overflo:1, // 6 + int_en_request_timeou:1, // 7 + :8, // 15:8 + int_en_head_inv_data_:1, // 16 + int_en_rsp_pactype_in:1, // 17 + int_en_head_sb_err:1, // 18 + int_en_missing_head:1, // 19 + int_en_head_inv_rd_ty:1, // 20 + int_en_head_cmd_err_b:1, // 21 + int_en_req_addr_align:1, // 22 + int_en_pio_req_addr_i:1, // 23 + int_en_req_range_dsiz:1, // 24 + int_en_early_term:1, // 25 + int_en_early_tail:1, // 26 + int_en_missing_tail:1, // 27 + int_en_data_flit_sb_e:1, // 28 + int_en_cm2hcm_req_cre:1, // 29 + int_en_cm2hcm_rsp_cre:1, // 30 + int_en_rx_bad_didn:1, // 31 + int_en_rd_dma_err_rsp:1, // 32 + int_en_rd_dma_tnum_to:1, // 33 + int_en_rd_dma_multi_t:1, // 34 + int_en_wr_dma_err_rsp:1, // 35 + int_en_wr_dma_tnum_to:1, // 36 + int_en_wr_dma_multi_t:1, // 37 + int_en_alg_data_overf:1, // 38 + int_en_alg_data_under:1, // 39 + int_en_ram0_access_co:1, // 40 + int_en_ram1_access_co:1, // 41 + int_en_ram2_access_co:1, // 42 + int_en_ram0_perr:1, // 43 + int_en_ram1_perr:1, // 44 + int_en_ram2_perr:1, // 45 + int_en_int_gen_rsp_er:1, // 46 + int_en_int_gen_tnum_t:1, // 47 + int_en_rd_dma_prog_er:1, // 48 + int_en_wr_dma_prog_er:1, // 49 + :14; // 63:50 + }; +}; + +struct cm_mmr { + union cm_id id; + union cm_status status; + union cm_error_detail1 err_detail1; + union cm_error_detail2 err_detail2; + union cm_control control; + union cm_req_timeout req_timeout; + uint64_t reserved1[1]; + union intr_dest int_dest; + uint64_t reserved2[2]; + uint64_t targ_flush; + uint64_t reserved3[1]; + union cm_error_status err_status; + union cm_clr_error_status clr_err_status; + union cm_error_intr_enable int_enable; +}; + +union dma_hostaddr { + uint64_t dma_hostaddr_reg; + struct { + uint64_t dma_sys_addr:56, // 55:0 + :8; // 63:56 + }; +}; + +union dma_localaddr { + uint64_t dma_localaddr_reg; + struct { + uint64_t dma_ram_addr:21, // 20:0 + dma_ram_sel:2, // 22:21 + :41; // 63:23 + }; +}; + +union dma_control { + uint64_t dma_control_reg; + struct { + uint64_t dma_op_length:16, // 15:0 + :18, // 33:16 + done_amo_en:1, // 34 + done_int_en:1, // 35 + :1, // 36 + pio_mem_n:1, // 37 + :26; // 63:38 + }; +}; + +union dma_amo_dest { + uint64_t dma_amo_dest_reg; + struct { + uint64_t dma_amo_sys_addr:56, // 55:0 + dma_amo_mod_type:3, // 58:56 + :5; // 63:59 + }; +}; + +union rdma_aux_status { + uint64_t rdma_aux_status_reg; + struct { + uint64_t op_num_pacs_left:17, // 16:0 + :5, // 21:17 + lrsp_buff_empty:1, // 22 + :17, // 39:23 + pending_reqs_left:6, // 45:40 + :18; // 63:46 + }; +}; + +struct rdma_mmr { + union dma_hostaddr host_addr; + union dma_localaddr local_addr; + union dma_control control; + union dma_amo_dest amo_dest; + union intr_dest intr_dest; + union rdma_aux_status aux_status; +}; + +union wdma_aux_status { + uint64_t wdma_aux_status_reg; + struct { + uint64_t op_num_pacs_left:17, // 16:0 + :4, // 20:17 + lreq_buff_empty:1, // 21 + :18, // 39:22 + pending_reqs_left:6, // 45:40 + :18; // 63:46 + }; +}; + +struct wdma_mmr { + union dma_hostaddr host_addr; + union dma_localaddr local_addr; + union dma_control control; + union dma_amo_dest amo_dest; + union intr_dest intr_dest; + union wdma_aux_status aux_status; +}; + +union algo_step { + uint64_t algo_step_reg; + struct { + uint64_t alg_step_cnt:16, // 15:0 + :48; // 63:16 + }; +}; + +struct algo_mmr { + union dma_amo_dest amo_dest; + union intr_dest intr_dest; + union { + uint64_t algo_offset_reg; + struct { + uint64_t sram0_offset:7, // 6:0 + reserved0:1, // 7 + sram1_offset:7, // 14:8 + reserved1:1, // 15 + sram2_offset:7, // 22:16 + reserved2:14; // 63:23 + }; + } sram_offset; + union algo_step step; +}; + +struct mbcs_mmr { + struct cm_mmr cm; + uint64_t reserved1[17]; + struct rdma_mmr rdDma; + uint64_t reserved2[25]; + struct wdma_mmr wrDma; + uint64_t reserved3[25]; + struct algo_mmr algo; + uint64_t reserved4[156]; +}; + +/* + * defines + */ +#define DEVICE_NAME "mbcs" +#define MBCS_PART_NUM 0xfff0 +#define MBCS_PART_NUM_ALG0 0xf001 +#define MBCS_MFG_NUM 0x1 + +struct algoblock { + uint64_t amoHostDest; + uint64_t amoModType; + uint64_t intrHostDest; + uint64_t intrVector; + uint64_t algoStepCount; +}; + +struct getdma { + uint64_t hostAddr; + uint64_t localAddr; + uint64_t bytes; + uint64_t DoneAmoEnable; + uint64_t DoneIntEnable; + uint64_t peerIO; + uint64_t amoHostDest; + uint64_t amoModType; + uint64_t intrHostDest; + uint64_t intrVector; +}; + +struct putdma { + uint64_t hostAddr; + uint64_t localAddr; + uint64_t bytes; + uint64_t DoneAmoEnable; + uint64_t DoneIntEnable; + uint64_t peerIO; + uint64_t amoHostDest; + uint64_t amoModType; + uint64_t intrHostDest; + uint64_t intrVector; +}; + +struct mbcs_soft { + struct list_head list; + struct cx_dev *cxdev; + int major; + int nasid; + void *mmr_base; + wait_queue_head_t dmawrite_queue; + wait_queue_head_t dmaread_queue; + wait_queue_head_t algo_queue; + struct sn_irq_info *get_sn_irq; + struct sn_irq_info *put_sn_irq; + struct sn_irq_info *algo_sn_irq; + struct getdma getdma; + struct putdma putdma; + struct algoblock algo; + uint64_t gscr_addr; // pio addr + uint64_t ram0_addr; // pio addr + uint64_t ram1_addr; // pio addr + uint64_t ram2_addr; // pio addr + uint64_t debug_addr; // pio addr + atomic_t dmawrite_done; + atomic_t dmaread_done; + atomic_t algo_done; + struct semaphore dmawritelock; + struct semaphore dmareadlock; + struct semaphore algolock; +}; + +extern int mbcs_open(struct inode *ip, struct file *fp); +extern ssize_t mbcs_sram_read(struct file *fp, char *buf, size_t len, + loff_t * off); +extern ssize_t mbcs_sram_write(struct file *fp, const char *buf, size_t len, + loff_t * off); +extern loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence); +extern int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma); + +#endif // __MBCS_H__ diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h index ae0bc99d573e..960d626ee589 100644 --- a/include/asm-ia64/sn/addrs.h +++ b/include/asm-ia64/sn/addrs.h @@ -169,7 +169,10 @@ #define TIO_BWIN_SIZE_BITS 30 /* big window size: 1G */ #define NODE_SWIN_BASE(n, w) ((w == 0) ? NODE_BWIN_BASE((n), SWIN0_BIGWIN) \ : RAW_NODE_SWIN_BASE(n, w)) +#define TIO_SWIN_BASE(n, w) (TIO_IO_BASE(n) + \ + ((u64) (w) << TIO_SWIN_SIZE_BITS)) #define NODE_IO_BASE(n) (GLOBAL_MMR_SPACE | NASID_SPACE(n)) +#define TIO_IO_BASE(n) (UNCACHED | NASID_SPACE(n)) #define BWIN_SIZE (1UL << BWIN_SIZE_BITS) #define NODE_BWIN_BASE0(n) (NODE_IO_BASE(n) + BWIN_SIZE) #define NODE_BWIN_BASE(n, w) (NODE_BWIN_BASE0(n) + ((u64) (w) << BWIN_SIZE_BITS)) diff --git a/include/asm-ia64/sn/tiocx.h b/include/asm-ia64/sn/tiocx.h new file mode 100644 index 000000000000..c5447a504509 --- /dev/null +++ b/include/asm-ia64/sn/tiocx.h @@ -0,0 +1,71 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef _ASM_IA64_SN_TIO_TIOCX_H +#define _ASM_IA64_SN_TIO_TIOCX_H + +#ifdef __KERNEL__ + +struct cx_id_s { + unsigned int part_num; + unsigned int mfg_num; + int nasid; +}; + +struct cx_dev { + struct cx_id_s cx_id; + void *soft; /* driver specific */ + struct hubdev_info *hubdev; + struct device dev; + struct cx_drv *driver; +}; + +struct cx_device_id { + unsigned int part_num; + unsigned int mfg_num; +}; + +struct cx_drv { + char *name; + const struct cx_device_id *id_table; + struct device_driver driver; + int (*probe) (struct cx_dev * dev, const struct cx_device_id * id); + int (*remove) (struct cx_dev * dev); +}; + +/* create DMA address by stripping AS bits */ +#define TIOCX_DMA_ADDR(a) (uint64_t)((uint64_t)(a) & 0xffffcfffffffffUL) + +#define TIOCX_TO_TIOCX_DMA_ADDR(a) (uint64_t)(((uint64_t)(a) & 0xfffffffff) | \ + ((((uint64_t)(a)) & 0xffffc000000000UL) <<2)) + +#define TIO_CE_ASIC_PARTNUM 0xce00 +#define TIOCX_CORELET 3 + +/* These are taken from tio_mmr_as.h */ +#define TIO_ICE_FRZ_CFG TIO_MMR_ADDR_MOD(0x00000000b0008100UL) +#define TIO_ICE_PMI_TX_CFG TIO_MMR_ADDR_MOD(0x00000000b000b100UL) +#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3 TIO_MMR_ADDR_MOD(0x00000000b000be18UL) +#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK 0x000000000000000fUL + +#define to_cx_dev(n) container_of(n, struct cx_dev, dev) +#define to_cx_driver(drv) container_of(drv, struct cx_drv, driver) + +extern struct sn_irq_info *tiocx_irq_alloc(nasid_t, int, int, nasid_t, int); +extern void tiocx_irq_free(struct sn_irq_info *); +extern int cx_device_unregister(struct cx_dev *); +extern int cx_device_register(nasid_t, int, int, struct hubdev_info *); +extern int cx_driver_unregister(struct cx_drv *); +extern int cx_driver_register(struct cx_drv *); +extern uint64_t tiocx_dma_addr(uint64_t addr); +extern uint64_t tiocx_swin_base(int nasid); +extern void tiocx_mmr_store(int nasid, uint64_t offset, uint64_t value); +extern uint64_t tiocx_mmr_load(int nasid, uint64_t offset); + +#endif // __KERNEL__ +#endif // _ASM_IA64_SN_TIO_TIOCX__ -- cgit v1.2.3 From fde740e4dd4a05ca8957490d468fa9b2770f5bd6 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Mon, 25 Apr 2005 13:13:16 -0700 Subject: [IA64] Percpu quicklist for combined allocator for pgd/pmd/pte. This patch introduces using the quicklists for pgd, pmd, and pte levels by combining the alloc and free functions into a common set of routines. This greatly simplifies the reading of this header file. This patch is simple but necessary for large numa configurations. It simply ensures that only pages from the local node are added to a cpus quicklist. This prevents the trapping of pages on a remote nodes quicklist by starting a process, touching a large number of pages to fill pmd and pte entries, migrating to another node, and then unmapping or exiting. With those conditions, the pages get trapped and if the machine has more than 100 nodes of the same size, the calculation of the pgtable high water mark will be larger than any single node so page table cache flushing will never occur. I ran lmbench lat_proc fork and lat_proc exec on a zx1 with and without this patch and did not notice any change. On an sn2 machine, there was a slight improvement which is possibly due to pages from other nodes trapped on the test node before starting the run. I did not investigate further. This patch shrinks the quicklist based upon free memory on the node instead of the high/low water marks. I have written it to enable preemption periodically and recalculate the amount to shrink every time we have freed enough pages that the quicklist size should have grown. I rescan the nodes zones each pass because other processess may be draining node memory at the same time as we are adding. Signed-off-by: Robin Holt Signed-off-by: Tony Luck --- arch/ia64/mm/contig.c | 3 +- arch/ia64/mm/discontig.c | 3 +- arch/ia64/mm/init.c | 74 ++++++++++++++-------- include/asm-ia64/pgalloc.h | 144 ++++++++++++++++++------------------------- include/asm-ia64/processor.h | 3 - 5 files changed, 112 insertions(+), 115 deletions(-) (limited to 'include') diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 6daf15ac8940..91a055f5731f 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -61,7 +61,8 @@ show_mem (void) printk("%d reserved pages\n", reserved); printk("%d pages shared\n", shared); printk("%d pages swap cached\n", cached); - printk("%ld pages in page table cache\n", pgtable_cache_size); + printk("%ld pages in page table cache\n", + pgtable_quicklist_total_size()); } /* physical address where the bootmem map is located */ diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 3456a9b6971e..c00710929390 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -582,7 +582,8 @@ void show_mem(void) printk("%d reserved pages\n", total_reserved); printk("%d pages shared\n", total_shared); printk("%d pages swap cached\n", total_cached); - printk("Total of %ld pages in page table cache\n", pgtable_cache_size); + printk("Total of %ld pages in page table cache\n", + pgtable_quicklist_total_size()); printk("%d free buffer pages\n", nr_free_buffer_pages()); } diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 65cf839573ea..4892be53e227 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -39,6 +39,9 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +DEFINE_PER_CPU(unsigned long *, __pgtable_quicklist); +DEFINE_PER_CPU(long, __pgtable_quicklist_size); + extern void ia64_tlb_init (void); unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; @@ -50,27 +53,53 @@ struct page *vmem_map; EXPORT_SYMBOL(vmem_map); #endif -static int pgt_cache_water[2] = { 25, 50 }; - -struct page *zero_page_memmap_ptr; /* map entry for zero page */ +struct page *zero_page_memmap_ptr; /* map entry for zero page */ EXPORT_SYMBOL(zero_page_memmap_ptr); +#define MIN_PGT_PAGES 25UL +#define MAX_PGT_FREES_PER_PASS 16 +#define PGT_FRACTION_OF_NODE_MEM 16 + +static inline long +max_pgt_pages(void) +{ + u64 node_free_pages, max_pgt_pages; + +#ifndef CONFIG_NUMA + node_free_pages = nr_free_pages(); +#else + node_free_pages = nr_free_pages_pgdat(NODE_DATA(numa_node_id())); +#endif + max_pgt_pages = node_free_pages / PGT_FRACTION_OF_NODE_MEM; + max_pgt_pages = max(max_pgt_pages, MIN_PGT_PAGES); + return max_pgt_pages; +} + +static inline long +min_pages_to_free(void) +{ + long pages_to_free; + + pages_to_free = pgtable_quicklist_size - max_pgt_pages(); + pages_to_free = min(pages_to_free, MAX_PGT_FREES_PER_PASS); + return pages_to_free; +} + void -check_pgt_cache (void) +check_pgt_cache(void) { - int low, high; + long pages_to_free; - low = pgt_cache_water[0]; - high = pgt_cache_water[1]; + if (unlikely(pgtable_quicklist_size <= MIN_PGT_PAGES)) + return; preempt_disable(); - if (pgtable_cache_size > (u64) high) { - do { - if (pgd_quicklist) - free_page((unsigned long)pgd_alloc_one_fast(NULL)); - if (pmd_quicklist) - free_page((unsigned long)pmd_alloc_one_fast(NULL, 0)); - } while (pgtable_cache_size > (u64) low); + while (unlikely((pages_to_free = min_pages_to_free()) > 0)) { + while (pages_to_free--) { + free_page((unsigned long)pgtable_quicklist_alloc()); + } + preempt_enable(); + preempt_disable(); } preempt_enable(); } @@ -523,11 +552,14 @@ void mem_init (void) { long reserved_pages, codesize, datasize, initsize; - unsigned long num_pgt_pages; pg_data_t *pgdat; int i; static struct kcore_list kcore_mem, kcore_vmem, kcore_kernel; + BUG_ON(PTRS_PER_PGD * sizeof(pgd_t) != PAGE_SIZE); + BUG_ON(PTRS_PER_PMD * sizeof(pmd_t) != PAGE_SIZE); + BUG_ON(PTRS_PER_PTE * sizeof(pte_t) != PAGE_SIZE); + #ifdef CONFIG_PCI /* * This needs to be called _after_ the command line has been parsed but _before_ @@ -564,18 +596,6 @@ mem_init (void) num_physpages << (PAGE_SHIFT - 10), codesize >> 10, reserved_pages << (PAGE_SHIFT - 10), datasize >> 10, initsize >> 10); - /* - * Allow for enough (cached) page table pages so that we can map the entire memory - * at least once. Each task also needs a couple of page tables pages, so add in a - * fudge factor for that (don't use "threads-max" here; that would be wrong!). - * Don't allow the cache to be more than 10% of total memory, though. - */ -# define NUM_TASKS 500 /* typical number of tasks */ - num_pgt_pages = nr_free_pages() / PTRS_PER_PGD + NUM_TASKS; - if (num_pgt_pages > nr_free_pages() / 10) - num_pgt_pages = nr_free_pages() / 10; - if (num_pgt_pages > (u64) pgt_cache_water[1]) - pgt_cache_water[1] = num_pgt_pages; /* * For fsyscall entrpoints with no light-weight handler, use the ordinary diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h index 0f05dc8bd460..e86a8c331ee6 100644 --- a/include/asm-ia64/pgalloc.h +++ b/include/asm-ia64/pgalloc.h @@ -22,146 +22,124 @@ #include -/* - * Very stupidly, we used to get new pgd's and pmd's, init their contents - * to point to the NULL versions of the next level page table, later on - * completely re-init them the same way, then free them up. This wasted - * a lot of work and caused unnecessary memory traffic. How broken... - * We fix this by caching them. - */ -#define pgd_quicklist (local_cpu_data->pgd_quick) -#define pmd_quicklist (local_cpu_data->pmd_quick) -#define pgtable_cache_size (local_cpu_data->pgtable_cache_sz) +DECLARE_PER_CPU(unsigned long *, __pgtable_quicklist); +#define pgtable_quicklist __ia64_per_cpu_var(__pgtable_quicklist) +DECLARE_PER_CPU(long, __pgtable_quicklist_size); +#define pgtable_quicklist_size __ia64_per_cpu_var(__pgtable_quicklist_size) -static inline pgd_t* -pgd_alloc_one_fast (struct mm_struct *mm) +static inline long pgtable_quicklist_total_size(void) +{ + long ql_size; + int cpuid; + + for_each_online_cpu(cpuid) { + ql_size += per_cpu(__pgtable_quicklist_size, cpuid); + } + return ql_size; +} + +static inline void *pgtable_quicklist_alloc(void) { unsigned long *ret = NULL; preempt_disable(); - ret = pgd_quicklist; + ret = pgtable_quicklist; if (likely(ret != NULL)) { - pgd_quicklist = (unsigned long *)(*ret); + pgtable_quicklist = (unsigned long *)(*ret); ret[0] = 0; - --pgtable_cache_size; - } else - ret = NULL; + --pgtable_quicklist_size; + } else { + ret = (unsigned long *)__get_free_page(GFP_KERNEL | __GFP_ZERO); + } preempt_enable(); - return (pgd_t *) ret; + return ret; } -static inline pgd_t* -pgd_alloc (struct mm_struct *mm) +static inline void pgtable_quicklist_free(void *pgtable_entry) { - /* the VM system never calls pgd_alloc_one_fast(), so we do it here. */ - pgd_t *pgd = pgd_alloc_one_fast(mm); +#ifdef CONFIG_NUMA + unsigned long nid = page_to_nid(virt_to_page(pgtable_entry)); - if (unlikely(pgd == NULL)) { - pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO); + if (unlikely(nid != numa_node_id())) { + free_page((unsigned long)pgtable_entry); + return; } - return pgd; -} +#endif -static inline void -pgd_free (pgd_t *pgd) -{ preempt_disable(); - *(unsigned long *)pgd = (unsigned long) pgd_quicklist; - pgd_quicklist = (unsigned long *) pgd; - ++pgtable_cache_size; + *(unsigned long *)pgtable_entry = (unsigned long)pgtable_quicklist; + pgtable_quicklist = (unsigned long *)pgtable_entry; + ++pgtable_quicklist_size; preempt_enable(); } -static inline void -pud_populate (struct mm_struct *mm, pud_t *pud_entry, pmd_t *pmd) +static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - pud_val(*pud_entry) = __pa(pmd); + return pgtable_quicklist_alloc(); } -static inline pmd_t* -pmd_alloc_one_fast (struct mm_struct *mm, unsigned long addr) +static inline void pgd_free(pgd_t * pgd) { - unsigned long *ret = NULL; - - preempt_disable(); - - ret = (unsigned long *)pmd_quicklist; - if (likely(ret != NULL)) { - pmd_quicklist = (unsigned long *)(*ret); - ret[0] = 0; - --pgtable_cache_size; - } - - preempt_enable(); - - return (pmd_t *)ret; + pgtable_quicklist_free(pgd); } -static inline pmd_t* -pmd_alloc_one (struct mm_struct *mm, unsigned long addr) +static inline void +pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd) { - pmd_t *pmd = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); + pud_val(*pud_entry) = __pa(pmd); +} - return pmd; +static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) +{ + return pgtable_quicklist_alloc(); } -static inline void -pmd_free (pmd_t *pmd) +static inline void pmd_free(pmd_t * pmd) { - preempt_disable(); - *(unsigned long *)pmd = (unsigned long) pmd_quicklist; - pmd_quicklist = (unsigned long *) pmd; - ++pgtable_cache_size; - preempt_enable(); + pgtable_quicklist_free(pmd); } #define __pmd_free_tlb(tlb, pmd) pmd_free(pmd) static inline void -pmd_populate (struct mm_struct *mm, pmd_t *pmd_entry, struct page *pte) +pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte) { pmd_val(*pmd_entry) = page_to_phys(pte); } static inline void -pmd_populate_kernel (struct mm_struct *mm, pmd_t *pmd_entry, pte_t *pte) +pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte) { pmd_val(*pmd_entry) = __pa(pte); } -static inline struct page * -pte_alloc_one (struct mm_struct *mm, unsigned long addr) +static inline struct page *pte_alloc_one(struct mm_struct *mm, + unsigned long addr) { - struct page *pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); - - return pte; + return virt_to_page(pgtable_quicklist_alloc()); } -static inline pte_t * -pte_alloc_one_kernel (struct mm_struct *mm, unsigned long addr) +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long addr) { - pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); - - return pte; + return pgtable_quicklist_alloc(); } -static inline void -pte_free (struct page *pte) +static inline void pte_free(struct page *pte) { - __free_page(pte); + pgtable_quicklist_free(page_address(pte)); } -static inline void -pte_free_kernel (pte_t *pte) +static inline void pte_free_kernel(pte_t * pte) { - free_page((unsigned long) pte); + pgtable_quicklist_free(pte); } -#define __pte_free_tlb(tlb, pte) tlb_remove_page((tlb), (pte)) +#define __pte_free_tlb(tlb, pte) pte_free(pte) -extern void check_pgt_cache (void); +extern void check_pgt_cache(void); -#endif /* _ASM_IA64_PGALLOC_H */ +#endif /* _ASM_IA64_PGALLOC_H */ diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 2807f8d766d4..983798ec1791 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -137,9 +137,6 @@ struct cpuinfo_ia64 { __u64 nsec_per_cyc; /* (1000000000< Date: Mon, 25 Apr 2005 13:16:16 -0700 Subject: [IA64] fix: warning: `ql_size' might be used uninitialized Oops. Should have caught this before I checked it in. Signed-off-by: Tony Luck --- include/asm-ia64/pgalloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h index e86a8c331ee6..2b7127330ae1 100644 --- a/include/asm-ia64/pgalloc.h +++ b/include/asm-ia64/pgalloc.h @@ -29,7 +29,7 @@ DECLARE_PER_CPU(long, __pgtable_quicklist_size); static inline long pgtable_quicklist_total_size(void) { - long ql_size; + long ql_size = 0; int cpuid; for_each_online_cpu(cpuid) { -- cgit v1.2.3 From 95ff439a517835aa2bdf725fafbb025a63984289 Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Mon, 25 Apr 2005 13:19:11 -0700 Subject: [IA64-SGI] Add new MMR definitions/Modify BTE initialiation©. patch 1: Add new MMR definitions. Modify BTE initialiation. Modify BTE copy. Signed-off-by: Russ Anderson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/bte.c | 20 +++++++++------- include/asm-ia64/sn/bte.h | 53 +++++++++++++++++++++++++++++++++++++----- include/asm-ia64/sn/nodepda.h | 4 ++-- include/asm-ia64/sn/pda.h | 3 +-- include/asm-ia64/sn/shub_mmr.h | 20 +++++++++++++++- 5 files changed, 80 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index ce0bc4085eae..647deae9bfcd 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. */ #include @@ -170,10 +170,6 @@ retry_bteop: /* Initialize the notification to a known value. */ *bte->most_rcnt_na = BTE_WORD_BUSY; - /* Set the status reg busy bit and transfer length */ - BTE_PRINTKV(("IBLS = 0x%lx\n", IBLS_BUSY | transfer_size)); - BTE_LNSTAT_STORE(bte, IBLS_BUSY | transfer_size); - /* Set the source and destination registers */ BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src)))); BTE_SRC_STORE(bte, TO_PHYS(src)); @@ -188,7 +184,7 @@ retry_bteop: /* Initiate the transfer */ BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode))); - BTE_CTRL_STORE(bte, BTE_VALID_MODE(mode)); + BTE_START_TRANSFER(bte, transfer_size, BTE_VALID_MODE(mode)); itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec); @@ -429,10 +425,16 @@ void bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode) mynodepda->bte_recovery_timer.data = (unsigned long)mynodepda; for (i = 0; i < BTES_PER_NODE; i++) { + u64 *base_addr; + /* Which link status register should we use? */ - unsigned long link_status = (i == 0 ? IIO_IBLS0 : IIO_IBLS1); - mynodepda->bte_if[i].bte_base_addr = (u64 *) - REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), link_status); + base_addr = (u64 *) + REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), BTE_BASE_ADDR(i)); + mynodepda->bte_if[i].bte_base_addr = base_addr; + mynodepda->bte_if[i].bte_source_addr = BTE_SOURCE_ADDR(base_addr); + mynodepda->bte_if[i].bte_destination_addr = BTE_DEST_ADDR(base_addr); + mynodepda->bte_if[i].bte_control_addr = BTE_CTRL_ADDR(base_addr); + mynodepda->bte_if[i].bte_notify_addr = BTE_NOTIF_ADDR(base_addr); /* * Initialize the notification and spinlock diff --git a/include/asm-ia64/sn/bte.h b/include/asm-ia64/sn/bte.h index 0ec27f99c181..f50da3d91d07 100644 --- a/include/asm-ia64/sn/bte.h +++ b/include/asm-ia64/sn/bte.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. */ @@ -13,8 +13,12 @@ #include #include #include +#include #include +#include +#define IBCT_NOTIFY (0x1UL << 4) +#define IBCT_ZFIL_MODE (0x1UL << 0) /* #define BTE_DEBUG */ /* #define BTE_DEBUG_VERBOSE */ @@ -39,8 +43,36 @@ /* Define hardware */ -#define BTES_PER_NODE 2 +#define BTES_PER_NODE (is_shub2() ? 4 : 2) +#define MAX_BTES_PER_NODE 4 +#define BTE2OFF_CTRL (0) +#define BTE2OFF_SRC (SH2_BT_ENG_SRC_ADDR_0 - SH2_BT_ENG_CSR_0) +#define BTE2OFF_DEST (SH2_BT_ENG_DEST_ADDR_0 - SH2_BT_ENG_CSR_0) +#define BTE2OFF_NOTIFY (SH2_BT_ENG_NOTIF_ADDR_0 - SH2_BT_ENG_CSR_0) + +#define BTE_BASE_ADDR(interface) \ + (is_shub2() ? (interface == 0) ? SH2_BT_ENG_CSR_0 : \ + (interface == 1) ? SH2_BT_ENG_CSR_1 : \ + (interface == 2) ? SH2_BT_ENG_CSR_2 : \ + SH2_BT_ENG_CSR_3 \ + : (interface == 0) ? IIO_IBLS0 : IIO_IBLS1) + +#define BTE_SOURCE_ADDR(base) \ + (is_shub2() ? base + (BTE2OFF_SRC/8) \ + : base + (BTEOFF_SRC/8)) + +#define BTE_DEST_ADDR(base) \ + (is_shub2() ? base + (BTE2OFF_DEST/8) \ + : base + (BTEOFF_DEST/8)) + +#define BTE_CTRL_ADDR(base) \ + (is_shub2() ? base + (BTE2OFF_CTRL/8) \ + : base + (BTEOFF_CTRL/8)) + +#define BTE_NOTIF_ADDR(base) \ + (is_shub2() ? base + (BTE2OFF_NOTIFY/8) \ + : base + (BTEOFF_NOTIFY/8)) /* Define hardware modes */ #define BTE_NOTIFY (IBCT_NOTIFY) @@ -68,14 +100,18 @@ #define BTE_LNSTAT_STORE(_bte, _x) \ HUB_S(_bte->bte_base_addr, (_x)) #define BTE_SRC_STORE(_bte, _x) \ - HUB_S(_bte->bte_base_addr + (BTEOFF_SRC/8), (_x)) + HUB_S(_bte->bte_source_addr, (_x)) #define BTE_DEST_STORE(_bte, _x) \ - HUB_S(_bte->bte_base_addr + (BTEOFF_DEST/8), (_x)) + HUB_S(_bte->bte_destination_addr, (_x)) #define BTE_CTRL_STORE(_bte, _x) \ - HUB_S(_bte->bte_base_addr + (BTEOFF_CTRL/8), (_x)) + HUB_S(_bte->bte_control_addr, (_x)) #define BTE_NOTIF_STORE(_bte, _x) \ - HUB_S(_bte->bte_base_addr + (BTEOFF_NOTIFY/8), (_x)) + HUB_S(_bte->bte_notify_addr, (_x)) +#define BTE_START_TRANSFER(_bte, _len, _mode) \ + is_shub2() ? BTE_CTRL_STORE(_bte, IBLS_BUSY | (_mode << 24) | _len) \ + : BTE_LNSTAT_STORE(_bte, _len); \ + BTE_CTRL_STORE(_bte, _mode) /* Possible results from bte_copy and bte_unaligned_copy */ /* The following error codes map into the BTE hardware codes @@ -110,6 +146,10 @@ typedef enum { struct bteinfo_s { volatile u64 notify ____cacheline_aligned; u64 *bte_base_addr ____cacheline_aligned; + u64 *bte_source_addr; + u64 *bte_destination_addr; + u64 *bte_control_addr; + u64 *bte_notify_addr; spinlock_t spinlock; cnodeid_t bte_cnode; /* cnode */ int bte_error_count; /* Number of errors encountered */ @@ -117,6 +157,7 @@ struct bteinfo_s { int cleanup_active; /* Interface is locked for cleanup */ volatile bte_result_t bh_error; /* error while processing */ volatile u64 *most_rcnt_na; + struct bteinfo_s *btes_to_try[MAX_BTES_PER_NODE]; }; diff --git a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h index 2fbde33656e6..13cc1002b294 100644 --- a/include/asm-ia64/sn/nodepda.h +++ b/include/asm-ia64/sn/nodepda.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_NODEPDA_H #define _ASM_IA64_SN_NODEPDA_H @@ -43,7 +43,7 @@ struct nodepda_s { /* * The BTEs on this node are shared by the local cpus */ - struct bteinfo_s bte_if[BTES_PER_NODE]; /* Virtual Interface */ + struct bteinfo_s bte_if[MAX_BTES_PER_NODE]; /* Virtual Interface */ struct timer_list bte_recovery_timer; spinlock_t bte_recovery_lock; diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index e940d3647c80..cd19f17bf91a 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_PDA_H #define _ASM_IA64_SN_PDA_H @@ -11,7 +11,6 @@ #include #include #include -#include /* diff --git a/include/asm-ia64/sn/shub_mmr.h b/include/asm-ia64/sn/shub_mmr.h index 6ec37e816a9e..2f885088e095 100644 --- a/include/asm-ia64/sn/shub_mmr.h +++ b/include/asm-ia64/sn/shub_mmr.h @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2001-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2001-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_SHUB_MMR_H @@ -455,4 +455,22 @@ #define SH_INT_CMPC shubmmr(SH, INT_CMPC) #define SH_INT_CMPD shubmmr(SH, INT_CMPD) +/* ========================================================================== */ +/* Register "SH2_BT_ENG_CSR_0" */ +/* Engine 0 Control and Status Register */ +/* ========================================================================== */ + +#define SH2_BT_ENG_CSR_0 0x0000000030040000 +#define SH2_BT_ENG_SRC_ADDR_0 0x0000000030040080 +#define SH2_BT_ENG_DEST_ADDR_0 0x0000000030040100 +#define SH2_BT_ENG_NOTIF_ADDR_0 0x0000000030040180 + +/* ========================================================================== */ +/* BTE interfaces 1-3 */ +/* ========================================================================== */ + +#define SH2_BT_ENG_CSR_1 0x0000000030050000 +#define SH2_BT_ENG_CSR_2 0x0000000030060000 +#define SH2_BT_ENG_CSR_3 0x0000000030070000 + #endif /* _ASM_IA64_SN_SHUB_MMR_H */ -- cgit v1.2.3 From 93a07d0a0e7b013ee73fb39d4edb07b47288912e Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Mon, 25 Apr 2005 13:19:52 -0700 Subject: [IA64-SGI] Shub2 BTE support - BTE recovery code patch 2: Shub2 BTE recovery code will be implemented in SAL. Define the SAL interface. Modify bte_error to call SAL for shub2. Signed-off-by: Russ Anderson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/bte_error.c | 76 ++++++++++++++++++++++++++--------------- arch/ia64/sn/kernel/huberror.c | 9 +++-- include/asm-ia64/sn/sn_sal.h | 19 +++++++++-- 3 files changed, 71 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c index fd104312c6bd..fcbc748ae433 100644 --- a/arch/ia64/sn/kernel/bte_error.c +++ b/arch/ia64/sn/kernel/bte_error.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. */ #include @@ -33,48 +33,28 @@ void bte_error_handler(unsigned long); * Wait until all BTE related CRBs are completed * and then reset the interfaces. */ -void bte_error_handler(unsigned long _nodepda) +void shub1_bte_error_handler(unsigned long _nodepda) { struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; - spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; nasid_t nasid; int i; int valid_crbs; - unsigned long irq_flags; - volatile u64 *notify; - bte_result_t bh_error; ii_imem_u_t imem; /* II IMEM Register */ ii_icrb0_d_u_t icrbd; /* II CRB Register D */ ii_ibcr_u_t ibcr; ii_icmr_u_t icmr; ii_ieclr_u_t ieclr; - BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda, + BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda, smp_processor_id())); - spin_lock_irqsave(recovery_lock, irq_flags); - if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) && (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, smp_processor_id())); - spin_unlock_irqrestore(recovery_lock, irq_flags); return; } - /* - * Lock all interfaces on this node to prevent new transfers - * from being queued. - */ - for (i = 0; i < BTES_PER_NODE; i++) { - if (err_nodepda->bte_if[i].cleanup_active) { - continue; - } - spin_lock(&err_nodepda->bte_if[i].spinlock); - BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda, - smp_processor_id(), i)); - err_nodepda->bte_if[i].cleanup_active = 1; - } /* Determine information about our hub */ nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); @@ -101,7 +81,6 @@ void 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())); - spin_unlock_irqrestore(recovery_lock, irq_flags); return; } if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { @@ -120,8 +99,6 @@ void bte_error_handler(unsigned long _nodepda) BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", err_nodepda, smp_processor_id(), i)); - spin_unlock_irqrestore(recovery_lock, - irq_flags); return; } } @@ -146,6 +123,51 @@ void bte_error_handler(unsigned long _nodepda) ibcr.ii_ibcr_fld_s.i_soft_reset = 1; REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); + del_timer(recovery_timer); +} + +/* + * Wait until all BTE related CRBs are completed + * and then reset the interfaces. + */ +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; + + BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda, + smp_processor_id())); + + spin_lock_irqsave(recovery_lock, irq_flags); + + /* + * Lock all interfaces on this node to prevent new transfers + * from being queued. + */ + for (i = 0; i < BTES_PER_NODE; i++) { + if (err_nodepda->bte_if[i].cleanup_active) { + continue; + } + spin_lock(&err_nodepda->bte_if[i].spinlock); + BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda, + smp_processor_id(), i)); + err_nodepda->bte_if[i].cleanup_active = 1; + } + + if (is_shub1()) { + shub1_bte_error_handler(_nodepda); + } 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"); + } + for (i = 0; i < BTES_PER_NODE; i++) { bh_error = err_nodepda->bte_if[i].bh_error; if (bh_error != BTE_SUCCESS) { @@ -165,8 +187,6 @@ void bte_error_handler(unsigned long _nodepda) spin_unlock(&err_nodepda->bte_if[i].spinlock); } - del_timer(recovery_timer); - spin_unlock_irqrestore(recovery_lock, irq_flags); } diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index 2bdf684c5066..5c39b43ba3c0 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000,2002-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights reserved. */ #include @@ -38,8 +38,11 @@ static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep) if ((int)ret_stuff.v0) panic("hubii_eint_handler(): Fatal TIO Error"); - if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ - (void)hubiio_crb_error_handler(hubdev_info); + if (is_shub1()) { + if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ + (void)hubiio_crb_error_handler(hubdev_info); + } else + bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid))); return IRQ_HANDLED; } diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 410d356b40da..581f9a783045 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -8,7 +8,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2000-2005 Silicon Graphics, Inc. All rights reserved. */ @@ -77,7 +77,7 @@ #define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000059 #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 - +#define SN_SAL_BTE_RECOVER 0x02000061 /* * Service-specific constants @@ -1023,4 +1023,19 @@ ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab, return (int) rv.status; } +/* + * BTE error recovery is implemented in SAL + */ +static inline int +ia64_sn_bte_recovery(nasid_t nasid) +{ + struct ia64_sal_retval rv; + + rv.status = 0; + SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, 0, 0, 0, 0, 0, 0, 0); + if (rv.status == SALRET_NOT_IMPLEMENTED) + return 0; + return (int) rv.status; +} + #endif /* _ASM_IA64_SN_SN_SAL_H */ -- cgit v1.2.3 From 0985ea8f2db87d32b0b750229889e55fed7458ef Mon Sep 17 00:00:00 2001 From: Mark Goodwin Date: Mon, 25 Apr 2005 13:21:54 -0700 Subject: [IA64-SGI] Altix SN add support for slots in geoid_t locator This patch against ia64-test-2.6.12 is needed for forthcoming Altix chipsets. It renames geoid_any_t to geoid_common_t and splits the 8bit 'slab' field into two 4bit fields for 'slab' and 'slot'. Similar changes in the Altix SAL will retain backward compatibility for old kernels. Signed-off-by: Mark Goodwin Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/sn2/sn_hwperf.c | 71 +++++++++++++------------------------ include/asm-ia64/sn/geo.h | 45 +++++++++++++---------- include/asm-ia64/sn/sn_sal.h | 4 +-- include/asm-ia64/sn/types.h | 3 +- 4 files changed, 55 insertions(+), 68 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index e731fcb95f90..833e700fdac9 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -116,7 +116,7 @@ static int sn_hwperf_geoid_to_cnode(char *location) module_id = geo_module(geoid); this_rack = MODULE_GET_RACK(module_id); this_bay = MODULE_GET_BPOS(module_id); - this_slot = 0; /* XXX */ + this_slot = geo_slot(geoid); this_slab = geo_slab(geoid); if (rack == this_rack && bay == this_bay && slot == this_slot && slab == this_slab) { @@ -176,20 +176,27 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj, static void print_pci_topology(struct seq_file *s, struct sn_hwperf_object_info *obj, int *ordinal, - char *pci_topo_buf, int len) + u64 rack, u64 bay, u64 slot, u64 slab) { char *p1; char *p2; - - for (p1=pci_topo_buf; *p1 && p1 < pci_topo_buf + len;) { - if (!(p2 = strchr(p1, '\n'))) - break; - *p2 = '\0'; - seq_printf(s, "pcibus %d %s-%s\n", - *ordinal, obj->location, p1); - (*ordinal)++; - p1 = p2 + 1; + char *pg; + + if (!(pg = (char *)get_zeroed_page(GFP_KERNEL))) + return; /* ignore */ + if (ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab, + __pa(pg), PAGE_SIZE) == SN_HWPERF_OP_OK) { + for (p1=pg; *p1 && p1 < pg + PAGE_SIZE;) { + if (!(p2 = strchr(p1, '\n'))) + break; + *p2 = '\0'; + seq_printf(s, "pcibus %d %s-%s\n", + *ordinal, obj->location, p1); + (*ordinal)++; + p1 = p2 + 1; + } } + free_page((unsigned long)pg); } static int sn_topology_show(struct seq_file *s, void *d) @@ -218,9 +225,7 @@ static int sn_topology_show(struct seq_file *s, void *d) u8 region_size; u16 nasid_mask; int nasid_msb; - char *pci_topo_buf; int pci_bus_ordinal = 0; - static int pci_topo_buf_len = 256; if (obj == objs) { seq_printf(s, "# sn_topology version 2\n"); @@ -299,41 +304,13 @@ static int sn_topology_show(struct seq_file *s, void *d) /* * PCI busses attached to this node, if any */ - do { - if (sn_hwperf_location_to_bpos(obj->location, - &rack, &bay, &slot, &slab)) { - break; - } - - if (!(pci_topo_buf = vmalloc(pci_topo_buf_len))) { - printk("sn_topology_show: vmalloc failed\n"); - break; - } + if (sn_hwperf_location_to_bpos(obj->location, + &rack, &bay, &slot, &slab)) { + /* export pci bus info */ + print_pci_topology(s, obj, &pci_bus_ordinal, + rack, bay, slot, slab); - e = ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab, - pci_topo_buf, pci_topo_buf_len); - - switch (e) { - case SALRET_NOT_IMPLEMENTED: - case SALRET_INVALID_ARG: - /* ignore, don't print anything */ - e = SN_HWPERF_OP_OK; - break; - - case SALRET_ERROR: - /* retry with a bigger buffer */ - pci_topo_buf_len += 256; - break; - - case SN_HWPERF_OP_OK: - default: - /* export pci bus info */ - print_pci_topology(s, obj, &pci_bus_ordinal, - pci_topo_buf, pci_topo_buf_len); - break; - } - vfree(pci_topo_buf); - } while (e != SN_HWPERF_OP_OK && pci_topo_buf_len < 0x200000); + } } if (obj->ports) { diff --git a/include/asm-ia64/sn/geo.h b/include/asm-ia64/sn/geo.h index f566343d25f8..84b254603b8d 100644 --- a/include/asm-ia64/sn/geo.h +++ b/include/asm-ia64/sn/geo.h @@ -18,32 +18,34 @@ #define GEOID_SIZE 8 /* Would 16 be better? The size can be different on different platforms. */ -#define MAX_SLABS 0xe /* slabs per module */ +#define MAX_SLOTS 0xf /* slots per module */ +#define MAX_SLABS 0xf /* slabs per slot */ typedef unsigned char geo_type_t; /* Fields common to all substructures */ -typedef struct geo_any_s { +typedef struct geo_common_s { moduleid_t module; /* The module (box) this h/w lives in */ geo_type_t type; /* What type of h/w is named by this geoid_t */ - slabid_t slab; /* The logical assembly within the module */ -} geo_any_t; + slabid_t slab:4; /* slab (ASIC), 0 .. 15 within slot */ + slotid_t slot:4; /* slot (Blade), 0 .. 15 within module */ +} geo_common_t; /* Additional fields for particular types of hardware */ typedef struct geo_node_s { - geo_any_t any; /* No additional fields needed */ + geo_common_t common; /* No additional fields needed */ } geo_node_t; typedef struct geo_rtr_s { - geo_any_t any; /* No additional fields needed */ + geo_common_t common; /* No additional fields needed */ } geo_rtr_t; typedef struct geo_iocntl_s { - geo_any_t any; /* No additional fields needed */ + geo_common_t common; /* No additional fields needed */ } geo_iocntl_t; typedef struct geo_pcicard_s { - geo_iocntl_t any; + geo_iocntl_t common; char bus; /* Bus/widget number */ char slot; /* PCI slot number */ } geo_pcicard_t; @@ -62,14 +64,14 @@ typedef struct geo_mem_s { typedef union geoid_u { - geo_any_t any; - geo_node_t node; + geo_common_t common; + geo_node_t node; geo_iocntl_t iocntl; geo_pcicard_t pcicard; - geo_rtr_t rtr; - geo_cpu_t cpu; - geo_mem_t mem; - char padsize[GEOID_SIZE]; + geo_rtr_t rtr; + geo_cpu_t cpu; + geo_mem_t mem; + char padsize[GEOID_SIZE]; } geoid_t; @@ -104,19 +106,26 @@ typedef union geoid_u { #define INVALID_CNODEID ((cnodeid_t)-1) #define INVALID_PNODEID ((pnodeid_t)-1) #define INVALID_SLAB (slabid_t)-1 +#define INVALID_SLOT (slotid_t)-1 #define INVALID_MODULE ((moduleid_t)-1) #define INVALID_PARTID ((partid_t)-1) static inline slabid_t geo_slab(geoid_t g) { - return (g.any.type == GEO_TYPE_INVALID) ? - INVALID_SLAB : g.any.slab; + return (g.common.type == GEO_TYPE_INVALID) ? + INVALID_SLAB : g.common.slab; +} + +static inline slotid_t geo_slot(geoid_t g) +{ + return (g.common.type == GEO_TYPE_INVALID) ? + INVALID_SLOT : g.common.slot; } static inline moduleid_t geo_module(geoid_t g) { - return (g.any.type == GEO_TYPE_INVALID) ? - INVALID_MODULE : g.any.module; + return (g.common.type == GEO_TYPE_INVALID) ? + INVALID_MODULE : g.common.module; } extern geoid_t cnodeid_get_geoid(cnodeid_t cnode); diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 581f9a783045..123c1a50a9dc 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -74,10 +74,10 @@ #define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 #define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 #define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 -#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000059 #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 #define SN_SAL_BTE_RECOVER 0x02000061 +#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000062 /* * Service-specific constants @@ -1015,7 +1015,7 @@ ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2, static inline int ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab, - char *buf, u64 len) + u64 buf, u64 len) { struct ia64_sal_retval rv; SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY, diff --git a/include/asm-ia64/sn/types.h b/include/asm-ia64/sn/types.h index 586ed47cae9c..8e04ee211e59 100644 --- a/include/asm-ia64/sn/types.h +++ b/include/asm-ia64/sn/types.h @@ -16,7 +16,8 @@ typedef signed short nasid_t; /* node id in numa-as-id space */ typedef signed char partid_t; /* partition ID type */ typedef unsigned int moduleid_t; /* user-visible module number type */ typedef unsigned int cmoduleid_t; /* kernel compact module id type */ -typedef signed char slabid_t; +typedef unsigned char slotid_t; /* slot (blade) within module */ +typedef unsigned char slabid_t; /* slab (asic) within slot */ typedef u64 nic_t; typedef unsigned long iopaddr_t; typedef unsigned long paddr_t; -- cgit v1.2.3 From e927ecb05e1ce4bbb1e10f57008c94994e2160f5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 25 Apr 2005 13:25:06 -0700 Subject: [IA64] multi-core/multi-thread identification Version 3 - rediffed to apply on top of Ashok's hotplug cpu patch. /proc/cpuinfo output in step with x86. This is an updated MC/MT identification patch based on the previous discussions on list. Add the Multi-core and Multi-threading detection for IPF. - Add new core and threading related fields in /proc/cpuinfo. Physical id Core id Thread id Siblings - setup the cpu_core_map and cpu_sibling_map appropriately - Handles Hot plug CPU Signed-off-by: Suresh Siddha Signed-off-by: Gordon Jin Signed-off-by: Rohit Seth Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 69 ++++++++++++++- arch/ia64/kernel/smpboot.c | 206 +++++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/pal.h | 68 ++++++++++++++ include/asm-ia64/processor.h | 7 ++ include/asm-ia64/sal.h | 12 +++ include/asm-ia64/smp.h | 5 ++ 6 files changed, 365 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index f05650c801d2..88043841fb8a 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -4,10 +4,15 @@ * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co * David Mosberger-Tang * Stephane Eranian - * Copyright (C) 2000, Rohit Seth + * Copyright (C) 2000, 2004 Intel Corp + * Rohit Seth + * Suresh Siddha + * Gordon Jin * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond * + * 12/26/04 S.Siddha, G.Jin, R.Seth + * Add multi-threading and multi-core detection * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo(). * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map * 03/31/00 R.Seth cpu_initialized and current->processor fixes @@ -296,6 +301,34 @@ mark_bsp_online (void) #endif } +#ifdef CONFIG_SMP +static void +check_for_logical_procs (void) +{ + pal_logical_to_physical_t info; + s64 status; + + status = ia64_pal_logical_to_phys(0, &info); + if (status == -1) { + printk(KERN_INFO "No logical to physical processor mapping " + "available\n"); + return; + } + if (status) { + printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n", + status); + return; + } + /* + * Total number of siblings that BSP has. Though not all of them + * may have booted successfully. The correct number of siblings + * booted is in info.overview_num_log. + */ + smp_num_siblings = info.overview_tpc; + smp_num_cpucores = info.overview_cpp; +} +#endif + void __init setup_arch (char **cmdline_p) { @@ -356,6 +389,19 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); + + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); + + check_for_logical_procs(); + if (smp_num_cpucores > 1) + printk(KERN_INFO + "cpu package is Multi-Core capable: number of cores=%d\n", + smp_num_cpucores); + if (smp_num_siblings > 1) + printk(KERN_INFO + "cpu package is Multi-Threading capable: number of siblings=%d\n", + smp_num_siblings); #endif cpu_init(); /* initialize the bootstrap CPU */ @@ -459,12 +505,23 @@ show_cpuinfo (struct seq_file *m, void *v) "cpu regs : %u\n" "cpu MHz : %lu.%06lu\n" "itc MHz : %lu.%06lu\n" - "BogoMIPS : %lu.%02lu\n\n", + "BogoMIPS : %lu.%02lu\n", cpunum, c->vendor, family, c->model, c->revision, c->archrev, features, c->ppn, c->number, c->proc_freq / 1000000, c->proc_freq % 1000000, c->itc_freq / 1000000, c->itc_freq % 1000000, lpj*HZ/500000, (lpj*HZ/5000) % 100); +#ifdef CONFIG_SMP + if (c->threads_per_core > 1 || c->cores_per_socket > 1) + seq_printf(m, + "physical id: %u\n" + "core id : %u\n" + "thread id : %u\n", + c->socket_id, c->core_id, c->thread_id); + seq_printf(m, "siblings : %u\n", c->num_log); +#endif + seq_printf(m,"\n"); + return 0; } @@ -533,6 +590,14 @@ identify_cpu (struct cpuinfo_ia64 *c) memcpy(c->vendor, cpuid.field.vendor, 16); #ifdef CONFIG_SMP c->cpu = smp_processor_id(); + + /* below default values will be overwritten by identify_siblings() + * for Multi-Threading/Multi-Core capable cpu's + */ + c->threads_per_core = c->cores_per_socket = c->num_log = 1; + c->socket_id = -1; + + identify_siblings(c); #endif c->ppn = cpuid.field.ppn; c->number = cpuid.field.number; diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index dbc6b610cc64..0d5ee57c9865 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -3,6 +3,11 @@ * * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co * David Mosberger-Tang + * Copyright (C) 2001, 2004-2005 Intel Corp + * Rohit Seth + * Suresh Siddha + * Gordon Jin + * Ashok Raj * * 01/05/16 Rohit Seth Moved SMP booting functions from smp.c to here. * 01/04/27 David Mosberger Added ITC synching code. @@ -10,6 +15,11 @@ * smp_boot_cpus()/smp_commence() is replaced by * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). * 04/06/21 Ashok Raj Added CPU Hotplug Support + * 04/12/26 Jin Gordon + * 04/12/26 Rohit Seth + * Add multi-threading and multi-core detection + * 05/01/30 Suresh Siddha + * Setup cpu_sibling_map and cpu_core_map */ #include @@ -122,6 +132,11 @@ EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); +cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; +cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; +int smp_num_siblings = 1; +int smp_num_cpucores = 1; + /* which logical CPU number maps to which CPU (physical APIC ID) */ volatile int ia64_cpu_to_sapicid[NR_CPUS]; EXPORT_SYMBOL(ia64_cpu_to_sapicid); @@ -598,7 +613,68 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(smp_processor_id(), cpu_callin_map); } +/* + * mt_info[] is a temporary store for all info returned by + * PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the + * specific cpu comes. + */ +static struct { + __u32 socket_id; + __u16 core_id; + __u16 thread_id; + __u16 proc_fixed_addr; + __u8 valid; +}mt_info[NR_CPUS] __devinit; + #ifdef CONFIG_HOTPLUG_CPU +static inline void +remove_from_mtinfo(int cpu) +{ + int i; + + for_each_cpu(i) + if (mt_info[i].valid && mt_info[i].socket_id == + cpu_data(cpu)->socket_id) + mt_info[i].valid = 0; +} + +static inline void +clear_cpu_sibling_map(int cpu) +{ + int i; + + for_each_cpu_mask(i, cpu_sibling_map[cpu]) + cpu_clear(cpu, cpu_sibling_map[i]); + for_each_cpu_mask(i, cpu_core_map[cpu]) + cpu_clear(cpu, cpu_core_map[i]); + + cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE; +} + +static void +remove_siblinginfo(int cpu) +{ + int last = 0; + + if (cpu_data(cpu)->threads_per_core == 1 && + cpu_data(cpu)->cores_per_socket == 1) { + cpu_clear(cpu, cpu_core_map[cpu]); + cpu_clear(cpu, cpu_sibling_map[cpu]); + return; + } + + last = (cpus_weight(cpu_core_map[cpu]) == 1 ? 1 : 0); + + /* remove it from all sibling map's */ + clear_cpu_sibling_map(cpu); + + /* if this cpu is the last in the core group, remove all its info + * from mt_info structure + */ + if (last) + remove_from_mtinfo(cpu); +} + extern void fixup_irqs(void); /* must be called with cpucontrol mutex held */ int __cpu_disable(void) @@ -611,6 +687,7 @@ int __cpu_disable(void) if (cpu == 0) return -EBUSY; + remove_siblinginfo(cpu); fixup_irqs(); local_flush_tlb_all(); cpu_clear(cpu, cpu_callin_map); @@ -663,6 +740,23 @@ smp_cpus_done (unsigned int dummy) (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); } +static inline void __devinit +set_cpu_sibling_map(int cpu) +{ + int i; + + for_each_online_cpu(i) { + if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) { + cpu_set(i, cpu_core_map[cpu]); + cpu_set(cpu, cpu_core_map[i]); + if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) { + cpu_set(i, cpu_sibling_map[cpu]); + cpu_set(cpu, cpu_sibling_map[i]); + } + } + } +} + int __devinit __cpu_up (unsigned int cpu) { @@ -685,6 +779,15 @@ __cpu_up (unsigned int cpu) if (ret < 0) return ret; + if (cpu_data(cpu)->threads_per_core == 1 && + cpu_data(cpu)->cores_per_socket == 1) { + cpu_set(cpu, cpu_sibling_map[cpu]); + cpu_set(cpu, cpu_core_map[cpu]); + return 0; + } + + set_cpu_sibling_map(cpu); + return 0; } @@ -712,3 +815,106 @@ init_smp_config(void) ia64_sal_strerror(sal_ret)); } +static inline int __devinit +check_for_mtinfo_index(void) +{ + int i; + + for_each_cpu(i) + if (!mt_info[i].valid) + return i; + + return -1; +} + +/* + * Search the mt_info to find out if this socket's cid/tid information is + * cached or not. If the socket exists, fill in the core_id and thread_id + * in cpuinfo + */ +static int __devinit +check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c) +{ + int i; + __u32 sid = c->socket_id; + + for_each_cpu(i) { + if (mt_info[i].valid && mt_info[i].proc_fixed_addr == logical_address + && mt_info[i].socket_id == sid) { + c->core_id = mt_info[i].core_id; + c->thread_id = mt_info[i].thread_id; + return 1; /* not a new socket */ + } + } + return 0; +} + +/* + * identify_siblings(cpu) gets called from identify_cpu. This populates the + * information related to logical execution units in per_cpu_data structure. + */ +void __devinit +identify_siblings(struct cpuinfo_ia64 *c) +{ + s64 status; + u16 pltid; + u64 proc_fixed_addr; + int count, i; + pal_logical_to_physical_t info; + + if (smp_num_cpucores == 1 && smp_num_siblings == 1) + return; + + if ((status = ia64_pal_logical_to_phys(0, &info)) != PAL_STATUS_SUCCESS) { + printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n", + status); + return; + } + if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) { + printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status); + return; + } + if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != PAL_STATUS_SUCCESS) { + printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", status); + return; + } + + c->socket_id = (pltid << 8) | info.overview_ppid; + c->cores_per_socket = info.overview_cpp; + c->threads_per_core = info.overview_tpc; + count = c->num_log = info.overview_num_log; + + /* If the thread and core id information is already cached, then + * we will simply update cpu_info and return. Otherwise, we will + * do the PAL calls and cache core and thread id's of all the siblings. + */ + if (check_for_new_socket(proc_fixed_addr, c)) + return; + + for (i = 0; i < count; i++) { + int index; + + if (i && (status = ia64_pal_logical_to_phys(i, &info)) + != PAL_STATUS_SUCCESS) { + printk(KERN_ERR "ia64_pal_logical_to_phys failed" + " with %ld\n", status); + return; + } + if (info.log2_la == proc_fixed_addr) { + c->core_id = info.log1_cid; + c->thread_id = info.log1_tid; + } + + index = check_for_mtinfo_index(); + /* We will not do the mt_info caching optimization in this case. + */ + if (index < 0) + continue; + + mt_info[index].valid = 1; + mt_info[index].socket_id = c->socket_id; + mt_info[index].core_id = info.log1_cid; + mt_info[index].thread_id = info.log1_tid; + mt_info[index].proc_fixed_addr = info.log2_la; + } +} diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h index 5dd477ffb88e..2303a10ee595 100644 --- a/include/asm-ia64/pal.h +++ b/include/asm-ia64/pal.h @@ -67,6 +67,7 @@ #define PAL_REGISTER_INFO 39 /* return AR and CR register information*/ #define PAL_SHUTDOWN 40 /* enter processor shutdown state */ #define PAL_PREFETCH_VISIBILITY 41 /* Make Processor Prefetches Visible */ +#define PAL_LOGICAL_TO_PHYSICAL 42 /* returns information on logical to physical processor mapping */ #define PAL_COPY_PAL 256 /* relocate PAL procedures and PAL PMI */ #define PAL_HALT_INFO 257 /* return the low power capabilities of processor */ @@ -1559,6 +1560,73 @@ ia64_pal_prefetch_visibility (s64 trans_type) return iprv.status; } +/* data structure for getting information on logical to physical mappings */ +typedef union pal_log_overview_u { + struct { + u64 num_log :16, /* Total number of logical + * processors on this die + */ + tpc :8, /* Threads per core */ + reserved3 :8, /* Reserved */ + cpp :8, /* Cores per processor */ + reserved2 :8, /* Reserved */ + ppid :8, /* Physical processor ID */ + reserved1 :8; /* Reserved */ + } overview_bits; + u64 overview_data; +} pal_log_overview_t; + +typedef union pal_proc_n_log_info1_u{ + struct { + u64 tid :16, /* Thread id */ + reserved2 :16, /* Reserved */ + cid :16, /* Core id */ + reserved1 :16; /* Reserved */ + } ppli1_bits; + u64 ppli1_data; +} pal_proc_n_log_info1_t; + +typedef union pal_proc_n_log_info2_u { + struct { + u64 la :16, /* Logical address */ + reserved :48; /* Reserved */ + } ppli2_bits; + u64 ppli2_data; +} pal_proc_n_log_info2_t; + +typedef struct pal_logical_to_physical_s +{ + pal_log_overview_t overview; + pal_proc_n_log_info1_t ppli1; + pal_proc_n_log_info2_t ppli2; +} pal_logical_to_physical_t; + +#define overview_num_log overview.overview_bits.num_log +#define overview_tpc overview.overview_bits.tpc +#define overview_cpp overview.overview_bits.cpp +#define overview_ppid overview.overview_bits.ppid +#define log1_tid ppli1.ppli1_bits.tid +#define log1_cid ppli1.ppli1_bits.cid +#define log2_la ppli2.ppli2_bits.la + +/* Get information on logical to physical processor mappings. */ +static inline s64 +ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping) +{ + struct ia64_pal_retval iprv; + + PAL_CALL(iprv, PAL_LOGICAL_TO_PHYSICAL, proc_number, 0, 0); + + if (iprv.status == PAL_STATUS_SUCCESS) + { + if (proc_number == 0) + mapping->overview.overview_data = iprv.v0; + mapping->ppli1.ppli1_data = iprv.v1; + mapping->ppli2.ppli2_data = iprv.v2; + } + + return iprv.status; +} #endif /* __ASSEMBLY__ */ #endif /* _ASM_IA64_PAL_H */ diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 983798ec1791..9e1ba8b7fb68 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -148,6 +148,13 @@ struct cpuinfo_ia64 { #ifdef CONFIG_SMP __u64 loops_per_jiffy; int cpu; + __u32 socket_id; /* physical processor socket id */ + __u16 core_id; /* core id */ + __u16 thread_id; /* thread id */ + __u16 num_log; /* Total number of logical processors on + * this socket that were successfully booted */ + __u8 cores_per_socket; /* Cores per processor socket */ + __u8 threads_per_core; /* Threads per core */ #endif /* CPUID-derived information: */ diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index 240676f75390..29df88bdd2bc 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -91,6 +91,7 @@ extern spinlock_t sal_lock; #define SAL_PCI_CONFIG_READ 0x01000010 #define SAL_PCI_CONFIG_WRITE 0x01000011 #define SAL_FREQ_BASE 0x01000012 +#define SAL_PHYSICAL_ID_INFO 0x01000013 #define SAL_UPDATE_PAL 0x01000020 @@ -815,6 +816,17 @@ ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size, return isrv.status; } +/* Get physical processor die mapping in the platform. */ +static inline s64 +ia64_sal_physical_id_info(u16 *splid) +{ + struct ia64_sal_retval isrv; + SAL_CALL(isrv, SAL_PHYSICAL_ID_INFO, 0, 0, 0, 0, 0, 0, 0); + if (splid) + *splid = isrv.v0; + return isrv.status; +} + extern unsigned long sal_platform_features; extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *); diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h index c4a227acfeb0..3ba1a061e4ae 100644 --- a/include/asm-ia64/smp.h +++ b/include/asm-ia64/smp.h @@ -56,6 +56,10 @@ extern struct smp_boot_data { extern char no_int_routing __devinitdata; extern cpumask_t cpu_online_map; +extern cpumask_t cpu_core_map[NR_CPUS]; +extern cpumask_t cpu_sibling_map[NR_CPUS]; +extern int smp_num_siblings; +extern int smp_num_cpucores; extern void __iomem *ipi_base_addr; extern unsigned char smp_int_redirect; @@ -124,6 +128,7 @@ extern int smp_call_function_single (int cpuid, void (*func) (void *info), void extern void smp_send_reschedule (int cpu); extern void lock_ipi_calllock(void); extern void unlock_ipi_calllock(void); +extern void identify_siblings (struct cpuinfo_ia64 *); #else -- cgit v1.2.3 From 24eeb568aeeaee771b9f0a6fd6f5d01040a887da Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 25 Apr 2005 13:26:23 -0700 Subject: [IA64] vector sharing (Large I/O system support) Current ia64 linux cannot handle greater than 184 interrupt sources because of the lack of vectors. The following patch enables ia64 linux to handle greater than 184 interrupt sources by allowing the same vector number to be shared by multiple IOSAPIC's RTEs. The design of this patch is besed on "Intel(R) Itanium(R) Processor Family Interrupt Architecture Guide". Even if you don't have a large I/O system, you can see the behavior of vector sharing by changing IOSAPIC_LAST_DEVICE_VECTOR to fewer value. Signed-off-by: Kenji Kaneshige Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 358 +++++++++++++++++++++++++++++++++----------- arch/ia64/kernel/irq_ia64.c | 16 +- include/asm-ia64/hw_irq.h | 1 + 3 files changed, 286 insertions(+), 89 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index c15be5c38f56..11a221cc8dc3 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -98,19 +99,30 @@ #define DBG(fmt...) #endif +#define NR_PREALLOCATE_RTE_ENTRIES (PAGE_SIZE / sizeof(struct iosapic_rte_info)) +#define RTE_PREALLOCATED (1) + static DEFINE_SPINLOCK(iosapic_lock); /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ -static struct iosapic_intr_info { +struct iosapic_rte_info { + struct list_head rte_list; /* node in list of RTEs sharing the same vector */ char __iomem *addr; /* base address of IOSAPIC */ - u32 low32; /* current value of low word of Redirection table entry */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ - char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */ + char rte_index; /* IOSAPIC RTE index */ + int refcnt; /* reference counter */ + unsigned int flags; /* flags */ +} ____cacheline_aligned; + +static struct iosapic_intr_info { + struct list_head rtes; /* RTEs using this vector (empty => not an IOSAPIC interrupt) */ + int count; /* # of RTEs that shares this vector */ + u32 low32; /* current value of low word of Redirection table entry */ + unsigned int dest; /* destination CPU physical ID */ unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */ unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ - int refcnt; /* reference counter */ } iosapic_intr_info[IA64_NUM_VECTORS]; static struct iosapic { @@ -126,6 +138,8 @@ static int num_iosapic; static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */ +static int iosapic_kmalloc_ok; +static LIST_HEAD(free_rte_list); /* * Find an IOSAPIC associated with a GSI @@ -147,10 +161,12 @@ static inline int _gsi_to_vector (unsigned int gsi) { struct iosapic_intr_info *info; + struct iosapic_rte_info *rte; for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info) - if (info->gsi_base + info->rte_index == gsi) - return info - iosapic_intr_info; + list_for_each_entry(rte, &info->rtes, rte_list) + if (rte->gsi_base + rte->rte_index == gsi) + return info - iosapic_intr_info; return -1; } @@ -167,33 +183,52 @@ gsi_to_vector (unsigned int gsi) int gsi_to_irq (unsigned int gsi) { + unsigned long flags; + int irq; /* * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq * numbers... */ - return _gsi_to_vector(gsi); + spin_lock_irqsave(&iosapic_lock, flags); + { + irq = _gsi_to_vector(gsi); + } + spin_unlock_irqrestore(&iosapic_lock, flags); + + return irq; +} + +static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned int vec) +{ + struct iosapic_rte_info *rte; + + list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) + if (rte->gsi_base + rte->rte_index == gsi) + return rte; + return NULL; } static void -set_rte (unsigned int vector, unsigned int dest, int mask) +set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) { unsigned long pol, trigger, dmode; u32 low32, high32; char __iomem *addr; int rte_index; char redir; + struct iosapic_rte_info *rte; DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest); - rte_index = iosapic_intr_info[vector].rte_index; - if (rte_index < 0) + rte = gsi_vector_to_rte(gsi, vector); + if (!rte) return; /* not an IOSAPIC interrupt */ - addr = iosapic_intr_info[vector].addr; + rte_index = rte->rte_index; + addr = rte->addr; pol = iosapic_intr_info[vector].polarity; trigger = iosapic_intr_info[vector].trigger; dmode = iosapic_intr_info[vector].dmode; - vector &= (~IA64_IRQ_REDIRECTED); redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; @@ -221,6 +256,7 @@ set_rte (unsigned int vector, unsigned int dest, int mask) iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); iosapic_intr_info[vector].low32 = low32; + iosapic_intr_info[vector].dest = dest; } static void @@ -237,18 +273,20 @@ mask_irq (unsigned int irq) u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); + struct iosapic_rte_info *rte; - addr = iosapic_intr_info[vec].addr; - rte_index = iosapic_intr_info[vec].rte_index; - - if (rte_index < 0) + if (list_empty(&iosapic_intr_info[vec].rtes)) return; /* not an IOSAPIC interrupt! */ spin_lock_irqsave(&iosapic_lock, flags); { /* set only the mask bit */ low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { + addr = rte->addr; + rte_index = rte->rte_index; + iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + } } spin_unlock_irqrestore(&iosapic_lock, flags); } @@ -261,16 +299,19 @@ unmask_irq (unsigned int irq) u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); + struct iosapic_rte_info *rte; - addr = iosapic_intr_info[vec].addr; - rte_index = iosapic_intr_info[vec].rte_index; - if (rte_index < 0) + if (list_empty(&iosapic_intr_info[vec].rtes)) return; /* not an IOSAPIC interrupt! */ spin_lock_irqsave(&iosapic_lock, flags); { low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { + addr = rte->addr; + rte_index = rte->rte_index; + iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + } } spin_unlock_irqrestore(&iosapic_lock, flags); } @@ -286,6 +327,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) char __iomem *addr; int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; ia64_vector vec; + struct iosapic_rte_info *rte; irq &= (~IA64_IRQ_REDIRECTED); vec = irq_to_vector(irq); @@ -295,10 +337,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) dest = cpu_physical_id(first_cpu(mask)); - rte_index = iosapic_intr_info[vec].rte_index; - addr = iosapic_intr_info[vec].addr; - - if (rte_index < 0) + if (list_empty(&iosapic_intr_info[vec].rtes)) return; /* not an IOSAPIC interrupt */ set_irq_affinity_info(irq, dest, redir); @@ -318,8 +357,13 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); iosapic_intr_info[vec].low32 = low32; - iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); - iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + iosapic_intr_info[vec].dest = dest; + list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { + addr = rte->addr; + rte_index = rte->rte_index; + iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); + iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); + } } spin_unlock_irqrestore(&iosapic_lock, flags); #endif @@ -340,9 +384,11 @@ static void iosapic_end_level_irq (unsigned int irq) { ia64_vector vec = irq_to_vector(irq); + struct iosapic_rte_info *rte; move_irq(irq); - iosapic_eoi(iosapic_intr_info[vec].addr, vec); + list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) + iosapic_eoi(rte->addr, vec); } #define iosapic_shutdown_level_irq mask_irq @@ -422,6 +468,34 @@ iosapic_version (char __iomem *addr) return iosapic_read(addr, IOSAPIC_VERSION); } +static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol) +{ + int i, vector = -1, min_count = -1; + struct iosapic_intr_info *info; + + /* + * shared vectors for edge-triggered interrupts are not + * supported yet + */ + if (trigger == IOSAPIC_EDGE) + return -1; + + for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { + info = &iosapic_intr_info[i]; + if (info->trigger == trigger && info->polarity == pol && + (info->dmode == IOSAPIC_FIXED || info->dmode == IOSAPIC_LOWEST_PRIORITY)) { + if (min_count == -1 || info->count < min_count) { + vector = i; + min_count = info->count; + } + } + } + if (vector < 0) + panic("%s: out of interrupt vectors!\n", __FUNCTION__); + + return vector; +} + /* * if the given vector is already owned by other, * assign a new vector for the other and make the vector available @@ -431,19 +505,63 @@ iosapic_reassign_vector (int vector) { int new_vector; - if (iosapic_intr_info[vector].rte_index >= 0 || iosapic_intr_info[vector].addr - || iosapic_intr_info[vector].gsi_base || iosapic_intr_info[vector].dmode - || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger) - { + if (!list_empty(&iosapic_intr_info[vector].rtes)) { new_vector = assign_irq_vector(AUTO_ASSIGN); printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector); memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], sizeof(struct iosapic_intr_info)); + INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes); + list_move(iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes); memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); - iosapic_intr_info[vector].rte_index = -1; + iosapic_intr_info[vector].low32 = IOSAPIC_MASK; + INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); } } +static struct iosapic_rte_info *iosapic_alloc_rte (void) +{ + int i; + struct iosapic_rte_info *rte; + int preallocated = 0; + + if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) { + rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * NR_PREALLOCATE_RTE_ENTRIES); + if (!rte) + return NULL; + for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++) + list_add(&rte->rte_list, &free_rte_list); + } + + if (!list_empty(&free_rte_list)) { + rte = list_entry(free_rte_list.next, struct iosapic_rte_info, rte_list); + list_del(&rte->rte_list); + preallocated++; + } else { + rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC); + if (!rte) + return NULL; + } + + memset(rte, 0, sizeof(struct iosapic_rte_info)); + if (preallocated) + rte->flags |= RTE_PREALLOCATED; + + return rte; +} + +static void iosapic_free_rte (struct iosapic_rte_info *rte) +{ + if (rte->flags & RTE_PREALLOCATED) + list_add_tail(&rte->rte_list, &free_rte_list); + else + kfree(rte); +} + +static inline int vector_is_shared (int vector) +{ + return (iosapic_intr_info[vector].count > 1); +} + static void register_intr (unsigned int gsi, int vector, unsigned char delivery, unsigned long polarity, unsigned long trigger) @@ -454,6 +572,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, int index; unsigned long gsi_base; void __iomem *iosapic_address; + struct iosapic_rte_info *rte; index = find_iosapic(gsi); if (index < 0) { @@ -464,14 +583,33 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, iosapic_address = iosapic_lists[index].addr; gsi_base = iosapic_lists[index].gsi_base; - rte_index = gsi - gsi_base; - iosapic_intr_info[vector].rte_index = rte_index; + rte = gsi_vector_to_rte(gsi, vector); + if (!rte) { + rte = iosapic_alloc_rte(); + if (!rte) { + printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__); + return; + } + + rte_index = gsi - gsi_base; + rte->rte_index = rte_index; + rte->addr = iosapic_address; + rte->gsi_base = gsi_base; + rte->refcnt++; + list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes); + iosapic_intr_info[vector].count++; + } + else if (vector_is_shared(vector)) { + struct iosapic_intr_info *info = &iosapic_intr_info[vector]; + if (info->trigger != trigger || info->polarity != polarity) { + printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__); + return; + } + } + iosapic_intr_info[vector].polarity = polarity; iosapic_intr_info[vector].dmode = delivery; - iosapic_intr_info[vector].addr = iosapic_address; - iosapic_intr_info[vector].gsi_base = gsi_base; iosapic_intr_info[vector].trigger = trigger; - iosapic_intr_info[vector].refcnt++; if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; @@ -493,6 +631,13 @@ get_target_cpu (unsigned int gsi, int vector) #ifdef CONFIG_SMP static int cpu = -1; + /* + * In case of vector shared by multiple RTEs, all RTEs that + * share the vector need to use the same destination CPU. + */ + if (!list_empty(&iosapic_intr_info[vector].rtes)) + return iosapic_intr_info[vector].dest; + /* * If the platform supports redirection via XTP, let it * distribute interrupts. @@ -565,10 +710,12 @@ int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long trigger) { - int vector; + int vector, mask = 1; unsigned int dest; unsigned long flags; - + struct iosapic_rte_info *rte; + u32 low32; +again: /* * If this GSI has already been registered (i.e., it's a * shared interrupt, or we lost a race to register it), @@ -578,19 +725,45 @@ iosapic_register_intr (unsigned int gsi, { vector = gsi_to_vector(gsi); if (vector > 0) { - iosapic_intr_info[vector].refcnt++; + rte = gsi_vector_to_rte(gsi, vector); + rte->refcnt++; spin_unlock_irqrestore(&iosapic_lock, flags); return vector; } + } + spin_unlock_irqrestore(&iosapic_lock, flags); + + /* If vector is running out, we try to find a sharable vector */ + vector = assign_irq_vector_nopanic(AUTO_ASSIGN); + if (vector < 0) + vector = iosapic_find_sharable_vector(trigger, polarity); + + spin_lock_irqsave(&irq_descp(vector)->lock, flags); + spin_lock(&iosapic_lock); + { + if (gsi_to_vector(gsi) > 0) { + if (list_empty(&iosapic_intr_info[vector].rtes)) + free_irq_vector(vector); + spin_unlock(&iosapic_lock); + spin_unlock_irqrestore(&irq_descp(vector)->lock, flags); + goto again; + } - vector = assign_irq_vector(AUTO_ASSIGN); dest = get_target_cpu(gsi, vector); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - polarity, trigger); + polarity, trigger); - set_rte(vector, dest, 1); + /* + * If the vector is shared and already unmasked for + * other interrupt sources, don't mask it. + */ + low32 = iosapic_intr_info[vector].low32; + if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK)) + mask = 0; + set_rte(gsi, vector, dest, mask); } - spin_unlock_irqrestore(&iosapic_lock, flags); + spin_unlock_irq(&iosapic_lock); + spin_unlock_irqrestore(&irq_descp(vector)->lock, flags); printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), @@ -607,8 +780,10 @@ iosapic_unregister_intr (unsigned int gsi) unsigned long flags; int irq, vector; irq_desc_t *idesc; - int rte_index; + u32 low32; unsigned long trigger, polarity; + unsigned int dest; + struct iosapic_rte_info *rte; /* * If the irq associated with the gsi is not found, @@ -627,54 +802,56 @@ iosapic_unregister_intr (unsigned int gsi) spin_lock_irqsave(&idesc->lock, flags); spin_lock(&iosapic_lock); { - rte_index = iosapic_intr_info[vector].rte_index; - if (rte_index < 0) { - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&idesc->lock, flags); + if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi); WARN_ON(1); - return; + goto out; } - if (--iosapic_intr_info[vector].refcnt > 0) { - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&idesc->lock, flags); - return; - } + if (--rte->refcnt > 0) + goto out; - /* - * If interrupt handlers still exist on the irq - * associated with the gsi, don't unregister the - * interrupt. - */ - if (idesc->action) { - iosapic_intr_info[vector].refcnt++; - spin_unlock(&iosapic_lock); - spin_unlock_irqrestore(&idesc->lock, flags); - printk(KERN_WARNING "Cannot unregister GSI. IRQ %u is still in use.\n", irq); - return; - } + /* Mask the interrupt */ + low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; + iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32); - /* Clear the interrupt controller descriptor. */ - idesc->handler = &no_irq_type; + /* Remove the rte entry from the list */ + list_del(&rte->rte_list); + iosapic_intr_info[vector].count--; + iosapic_free_rte(rte); - trigger = iosapic_intr_info[vector].trigger; + trigger = iosapic_intr_info[vector].trigger; polarity = iosapic_intr_info[vector].polarity; + dest = iosapic_intr_info[vector].dest; + printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n", + gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), + (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + cpu_logical_id(dest), dest, vector); + + if (list_empty(&iosapic_intr_info[vector].rtes)) { + /* Sanity check */ + BUG_ON(iosapic_intr_info[vector].count); + + /* Clear the interrupt controller descriptor */ + idesc->handler = &no_irq_type; + + /* Clear the interrupt information */ + memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); + iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; + INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); + + if (idesc->action) { + printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq); + WARN_ON(1); + } - /* Clear the interrupt information. */ - memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); - iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ + /* Free the interrupt vector */ + free_irq_vector(vector); + } } + out: spin_unlock(&iosapic_lock); spin_unlock_irqrestore(&idesc->lock, flags); - - /* Free the interrupt vector */ - free_irq_vector(vector); - - printk(KERN_INFO "GSI %u (%s, %s) -> vector %d unregisterd.\n", - gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), - (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), - vector); } #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */ @@ -724,7 +901,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), cpu_logical_id(dest), dest, vector); - set_rte(vector, dest, mask); + set_rte(gsi, vector, dest, mask); return vector; } @@ -750,7 +927,7 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low", cpu_logical_id(dest), dest, vector); - set_rte(vector, dest, 1); + set_rte(gsi, vector, dest, 1); } void __init @@ -758,8 +935,10 @@ iosapic_system_init (int system_pcat_compat) { int vector; - for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) - iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ + for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { + iosapic_intr_info[vector].low32 = IOSAPIC_MASK; + INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); /* mark as unused */ + } pcat_compat = system_pcat_compat; if (pcat_compat) { @@ -825,3 +1004,10 @@ map_iosapic_to_node(unsigned int gsi_base, int node) return; } #endif + +static int __init iosapic_enable_kmalloc (void) +{ + iosapic_kmalloc_ok = 1; + return 0; +} +core_initcall (iosapic_enable_kmalloc); diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 5ba06ebe355b..4fe60c7a2e90 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -63,20 +63,30 @@ EXPORT_SYMBOL(isa_irq_to_vector_map); static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)]; int -assign_irq_vector (int irq) +assign_irq_vector_nopanic (int irq) { int pos, vector; again: pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS); vector = IA64_FIRST_DEVICE_VECTOR + pos; if (vector > IA64_LAST_DEVICE_VECTOR) - /* XXX could look for sharable vectors instead of panic'ing... */ - panic("assign_irq_vector: out of interrupt vectors!"); + return -1; if (test_and_set_bit(pos, ia64_vector_mask)) goto again; return vector; } +int +assign_irq_vector (int irq) +{ + int vector = assign_irq_vector_nopanic(irq); + + if (vector < 0) + panic("assign_irq_vector: out of interrupt vectors!"); + + return vector; +} + void free_irq_vector (int vector) { diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index 041ab8c51a64..cd4e06b74ab6 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h @@ -81,6 +81,7 @@ extern __u8 isa_irq_to_vector_map[16]; extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */ +extern int assign_irq_vector_nopanic (int irq); /* allocate a free vector without panic */ extern int assign_irq_vector (int irq); /* allocate a free vector */ extern void free_irq_vector (int vector); extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); -- cgit v1.2.3 From 67639deb099c6085acc447c1b7d6a17792dedad0 Mon Sep 17 00:00:00 2001 From: Greg Howard Date: Mon, 25 Apr 2005 13:28:52 -0700 Subject: [IA64] Altix system controller event handling The following is an update of the patch I sent yesterday (3/9/05) incorporating suggestions from Christoph Hellwig and Andreas Schwab. It allows Altix and Altix-like systems to handle environmental events generated by the system controllers, and should apply on top of Jack Steiner's patch of 3/1/05 ("New chipset support for SN platform") and Mark Goodwin's patch of 3/8/05 ("Altix SN topology support for new chipsets and pci topology"). Signed-off-by: Greg Howard Signed-off-by: Tony Luck --- drivers/char/Makefile | 2 +- drivers/char/snsc.c | 8 ++++++++ drivers/char/snsc.h | 40 ++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/sn/sn_sal.h | 14 ++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 3ea8cc80ea3d..e3f5c32aac55 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -42,7 +42,7 @@ obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o obj-$(CONFIG_RAW_DRIVER) += raw.o -obj-$(CONFIG_SGI_SNSC) += snsc.o +obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index ffb9143376bb..e3c0b52d943f 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -374,6 +374,7 @@ scdrv_init(void) void *salbuf; struct class_simple *snsc_class; dev_t first_dev, dev; + nasid_t event_nasid = ia64_sn_get_console_nasid(); if (alloc_chrdev_region(&first_dev, 0, numionodes, SYSCTL_BASENAME) < 0) { @@ -441,6 +442,13 @@ scdrv_init(void) ia64_sn_irtr_intr_enable(scd->scd_nasid, 0 /*ignored */ , SAL_IROUTER_INTR_RECV); + + /* on the console nasid, prepare to receive + * system controller environmental events + */ + if(scd->scd_nasid == event_nasid) { + scdrv_event_init(scd); + } } return 0; } diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h index c22c6c55e254..a9efc13cc858 100644 --- a/drivers/char/snsc.h +++ b/drivers/char/snsc.h @@ -47,4 +47,44 @@ struct sysctl_data_s { nasid_t scd_nasid; /* Node on which subchannels are opened. */ }; + +/* argument types */ +#define IR_ARG_INT 0x00 /* 4-byte integer (big-endian) */ +#define IR_ARG_ASCII 0x01 /* null-terminated ASCII string */ +#define IR_ARG_UNKNOWN 0x80 /* unknown data type. The low + * 7 bits will contain the data + * length. */ +#define IR_ARG_UNKNOWN_LENGTH_MASK 0x7f + + +/* system controller event codes */ +#define EV_CLASS_MASK 0xf000ul +#define EV_SEVERITY_MASK 0x0f00ul +#define EV_COMPONENT_MASK 0x00fful + +#define EV_CLASS_POWER 0x1000ul +#define EV_CLASS_FAN 0x2000ul +#define EV_CLASS_TEMP 0x3000ul +#define EV_CLASS_ENV 0x4000ul +#define EV_CLASS_TEST_FAULT 0x5000ul +#define EV_CLASS_TEST_WARNING 0x6000ul +#define EV_CLASS_PWRD_NOTIFY 0x8000ul + +#define EV_SEVERITY_POWER_STABLE 0x0000ul +#define EV_SEVERITY_POWER_LOW_WARNING 0x0100ul +#define EV_SEVERITY_POWER_HIGH_WARNING 0x0200ul +#define EV_SEVERITY_POWER_HIGH_FAULT 0x0300ul +#define EV_SEVERITY_POWER_LOW_FAULT 0x0400ul + +#define EV_SEVERITY_FAN_STABLE 0x0000ul +#define EV_SEVERITY_FAN_WARNING 0x0100ul +#define EV_SEVERITY_FAN_FAULT 0x0200ul + +#define EV_SEVERITY_TEMP_STABLE 0x0000ul +#define EV_SEVERITY_TEMP_ADVISORY 0x0100ul +#define EV_SEVERITY_TEMP_CRITICAL 0x0200ul +#define EV_SEVERITY_TEMP_FAULT 0x0300ul + +void scdrv_event_init(struct sysctl_data_s *); + #endif /* _SN_SYSCTL_H_ */ diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 123c1a50a9dc..f914f6da077c 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -64,6 +64,7 @@ #define SN_SAL_SYSCTL_IOBRICK_PCI_OP 0x02000042 // reentrant #define SN_SAL_IROUTER_OP 0x02000043 +#define SN_SAL_SYSCTL_EVENT 0x02000044 #define SN_SAL_IOIF_INTERRUPT 0x0200004a #define SN_SAL_HWPERF_OP 0x02000050 // lock #define SN_SAL_IOIF_ERROR_INTERRUPT 0x02000051 @@ -850,6 +851,19 @@ ia64_sn_irtr_intr_disable(nasid_t nasid, int subch, u64 intr) return (int) rv.v0; } +/* + * Set up a node as the point of contact for system controller + * environmental event delivery. + */ +static inline int +ia64_sn_sysctl_event_init(nasid_t nasid) +{ + struct ia64_sal_retval rv; + SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_EVENT, (u64) nasid, + 0, 0, 0, 0, 0, 0); + return (int) rv.v0; +} + /** * ia64_sn_get_fit_compt - read a FIT entry from the PROM header * @nasid: NASID of node to read -- cgit v1.2.3 From bd7b170201149fd82bc3212cb570a7a7386463a4 Mon Sep 17 00:00:00 2001 From: Lucas Correia Villa Real Date: Mon, 25 Apr 2005 23:12:50 +0100 Subject: [PATCH] ARM: 2644/1: Adds S3C2400 support to uncompress.h Patch from Lucas Correia Villa Real The S3C2400 doesn't have a cpuid information stored anywhere. This patch adds support to the S3C2400 at include/asm-arm/arch-s3c2400/uncompress.h by initializing the cpuid variable to the S3C2410, as they share the same routine. The GSTATUS1 pin is then used only if not compiling for the S3C2400. Signed-off-by: Lucas Correia Villa Real Signed-off-by: Ben Dooks Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/uncompress.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h index ad4252e27799..d7a4a8354fa9 100644 --- a/include/asm-arm/arch-s3c2410/uncompress.h +++ b/include/asm-arm/arch-s3c2410/uncompress.h @@ -16,6 +16,7 @@ * 12-Oct-2004 BJD Take account of debug uart configuration * 15-Nov-2004 BJD Fixed uart configuration * 22-Feb-2005 BJD Added watchdog to uncompress + * 04-Apr-2005 LCVR Added support to S3C2400 (no cpuid at GSTATUS1) */ #ifndef __ASM_ARCH_UNCOMPRESS_H @@ -69,9 +70,12 @@ uart_rd(unsigned int reg) static void putc(char ch) { - int cpuid = *((volatile unsigned int *)S3C2410_GSTATUS1); + int cpuid = S3C2410_GSTATUS1_2410; +#ifndef CONFIG_CPU_S3C2400 + cpuid = *((volatile unsigned int *)S3C2410_GSTATUS1); cpuid &= S3C2410_GSTATUS1_IDMASK; +#endif if (ch == '\n') putc('\r'); /* expand newline to \r\n */ -- cgit v1.2.3 From eec99e345e0568767009341ac35fb5a499301499 Mon Sep 17 00:00:00 2001 From: Lucas Correia Villa Real Date: Mon, 25 Apr 2005 23:13:15 +0100 Subject: [PATCH] ARM: 2645/1: Adds IIS definitions for the S3C2400 Patch from Lucas Correia Villa Real Adds IISFCON definitions for the S3C2400 at include/asm-arm/arch-s3c2400/regs-iis.h. Signed-off-by: Lucas Correia Villa Real Signed-off-by: Ben Dooks Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/regs-iis.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include') diff --git a/include/asm-arm/arch-s3c2410/regs-iis.h b/include/asm-arm/arch-s3c2410/regs-iis.h index 7ae8e1f45bc1..385b07d510da 100644 --- a/include/asm-arm/arch-s3c2410/regs-iis.h +++ b/include/asm-arm/arch-s3c2410/regs-iis.h @@ -14,6 +14,7 @@ * 26-06-2003 BJD Finished off definitions for register addresses * 12-03-2004 BJD Updated include protection * 07-03-2005 BJD Added FIFO size flags and S3C2440 MPLL + * 05-04-2005 LCVR Added IISFCON definitions for the S3C2400 */ #ifndef __ASM_ARCH_REGS_IIS_H @@ -68,5 +69,14 @@ #define S3C2410_IISFCON_RXMASK (0x3f) #define S3C2410_IISFCON_RXSHIFT (0) +#define S3C2400_IISFCON_TXDMA (1<<11) +#define S3C2400_IISFCON_RXDMA (1<<10) +#define S3C2400_IISFCON_TXENABLE (1<<9) +#define S3C2400_IISFCON_RXENABLE (1<<8) +#define S3C2400_IISFCON_TXMASK (0x07 << 4) +#define S3C2400_IISFCON_TXSHIFT (4) +#define S3C2400_IISFCON_RXMASK (0x07) +#define S3C2400_IISFCON_RXSHIFT (0) + #define S3C2410_IISFIFO (0x10) #endif /* __ASM_ARCH_REGS_IIS_H */ -- cgit v1.2.3 From 2fac6f3fec2303649e9cd572255776cb93d3f888 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 25 Apr 2005 23:40:05 +0100 Subject: [PATCH] ARM: 2653/1: Fix memset and memzero macro double-reference of parameters Patch from Deepak Saxena The current memset() and memzero() macros on ARM reference the incoming parameters more than once and this can cause uninted side-effects. The issue was found while debugging SCTP protocol and with the specific usage of memzero(skb_put(skb,size),size). This call would call skb_put(skb,size) twice leading to badness. The fixed version copies the incoming parameters into local variables and uses those instead. Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- include/asm-arm/string.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-arm/string.h b/include/asm-arm/string.h index 2a8ab162412f..e50c4a39b699 100644 --- a/include/asm-arm/string.h +++ b/include/asm-arm/string.h @@ -29,15 +29,22 @@ extern void __memzero(void *ptr, __kernel_size_t n); #define memset(p,v,n) \ ({ \ - if ((n) != 0) { \ + void *__p = (p); size_t __n = n; \ + if ((__n) != 0) { \ if (__builtin_constant_p((v)) && (v) == 0) \ - __memzero((p),(n)); \ + __memzero((__p),(__n)); \ else \ - memset((p),(v),(n)); \ + memset((__p),(v),(__n)); \ } \ - (p); \ + (__p); \ }) -#define memzero(p,n) ({ if ((n) != 0) __memzero((p),(n)); (p); }) +#define memzero(p,n) \ + ({ \ + void *__p = (p); size_t __n = n; \ + if ((__n) != 0) \ + __memzero((__p),(__n)); \ + (__p); \ + }) #endif -- cgit v1.2.3 From 94f2f715771d0aa5554451d1e2a920f11b8be3fe Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Apr 2005 18:32:12 -0700 Subject: [PATCH] isofs includes sanitized fs/isofs includes trimmed down to something resembling sanity. Kernel-only parts of linux/iso_fs.h and entire linux/iso_fs_{sb,i}.h moved to fs/isofs/isofs.h. A lot of useless #include in fs/isofs/*.c killed. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/isofs/compress.c | 21 +---- fs/isofs/dir.c | 13 +--- fs/isofs/export.c | 6 +- fs/isofs/inode.c | 19 +---- fs/isofs/isofs.h | 190 ++++++++++++++++++++++++++++++++++++++++++++++ fs/isofs/joliet.c | 6 +- fs/isofs/namei.c | 13 +--- fs/isofs/rock.c | 8 +- fs/isofs/util.c | 5 +- include/linux/iso_fs.h | 147 ----------------------------------- include/linux/iso_fs_i.h | 27 ------- include/linux/iso_fs_sb.h | 34 --------- 12 files changed, 203 insertions(+), 286 deletions(-) create mode 100644 fs/isofs/isofs.h delete mode 100644 include/linux/iso_fs_i.h delete mode 100644 include/linux/iso_fs_sb.h (limited to 'include') diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index fb42c3f3bf0d..34a44e451689 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c @@ -18,29 +18,12 @@ #include #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include + #include #include -#include - -#include -#include -#include +#include "isofs.h" #include "zisofs.h" /* This should probably be global. */ diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 14d86de6637d..6030956b894b 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -10,20 +10,9 @@ * * isofs directory handling functions */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include - -#include +#include "isofs.h" static int isofs_readdir(struct file *, void *, filldir_t); diff --git a/fs/isofs/export.c b/fs/isofs/export.c index e4252c960871..4af856a7fda7 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -13,11 +13,7 @@ * fs/exportfs/expfs.c. */ -#include -#include -#include -#include -#include +#include "isofs.h" static struct dentry * isofs_export_iget(struct super_block *sb, diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index b9256e65e144..abd7b12eeca7 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -12,29 +12,18 @@ */ #include +#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include #include -#include -#include -#include +#include +#include #include -#include -#include +#include "isofs.h" #include "zisofs.h" #define BEQUIET diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h new file mode 100644 index 000000000000..9ce7b51fb614 --- /dev/null +++ b/fs/isofs/isofs.h @@ -0,0 +1,190 @@ +#include +#include +#include +#include + +enum isofs_file_format { + isofs_file_normal = 0, + isofs_file_sparse = 1, + isofs_file_compressed = 2, +}; + +/* + * iso fs inode data in memory + */ +struct iso_inode_info { + unsigned long i_iget5_block; + unsigned long i_iget5_offset; + unsigned int i_first_extent; + unsigned char i_file_format; + unsigned char i_format_parm[3]; + unsigned long i_next_section_block; + unsigned long i_next_section_offset; + off_t i_section_size; + struct inode vfs_inode; +}; + +/* + * iso9660 super-block data in memory + */ +struct isofs_sb_info { + unsigned long s_ninodes; + unsigned long s_nzones; + unsigned long s_firstdatazone; + unsigned long s_log_zone_size; + unsigned long s_max_size; + + unsigned char s_high_sierra; /* A simple flag */ + unsigned char s_mapping; + int s_rock_offset; /* offset of SUSP fields within SU area */ + unsigned char s_rock; + unsigned char s_joliet_level; + unsigned char s_utf8; + unsigned char s_cruft; /* Broken disks with high + byte of length containing + junk */ + unsigned char s_unhide; + unsigned char s_nosuid; + unsigned char s_nodev; + unsigned char s_nocompress; + + mode_t s_mode; + gid_t s_gid; + uid_t s_uid; + struct nls_table *s_nls_iocharset; /* Native language support table */ +}; + +static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + +static inline struct iso_inode_info *ISOFS_I(struct inode *inode) +{ + return container_of(inode, struct iso_inode_info, vfs_inode); +} + +static inline int isonum_711(char *p) +{ + return *(u8 *)p; +} +static inline int isonum_712(char *p) +{ + return *(s8 *)p; +} +static inline unsigned int isonum_721(char *p) +{ + return le16_to_cpu(get_unaligned((__le16 *)p)); +} +static inline unsigned int isonum_722(char *p) +{ + return be16_to_cpu(get_unaligned((__le16 *)p)); +} +static inline unsigned int isonum_723(char *p) +{ + /* Ignore bigendian datum due to broken mastering programs */ + return le16_to_cpu(get_unaligned((__le16 *)p)); +} +static inline unsigned int isonum_731(char *p) +{ + return le32_to_cpu(get_unaligned((__le32 *)p)); +} +static inline unsigned int isonum_732(char *p) +{ + return be32_to_cpu(get_unaligned((__le32 *)p)); +} +static inline unsigned int isonum_733(char *p) +{ + /* Ignore bigendian datum due to broken mastering programs */ + return le32_to_cpu(get_unaligned((__le32 *)p)); +} +extern int iso_date(char *, int); + +struct inode; /* To make gcc happy */ + +extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); +extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); +extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); + +int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *); +int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); + +extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *); +extern struct buffer_head *isofs_bread(struct inode *, sector_t); +extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); + +extern struct inode *isofs_iget(struct super_block *sb, + unsigned long block, + unsigned long offset); + +/* Because the inode number is no longer relevant to finding the + * underlying meta-data for an inode, we are free to choose a more + * convenient 32-bit number as the inode number. The inode numbering + * scheme was recommended by Sergey Vlasov and Eric Lammerts. */ +static inline unsigned long isofs_get_ino(unsigned long block, + unsigned long offset, + unsigned long bufbits) +{ + return (block << (bufbits - 5)) | (offset >> 5); +} + +/* Every directory can have many redundant directory entries scattered + * throughout the directory tree. First there is the directory entry + * with the name of the directory stored in the parent directory. + * Then, there is the "." directory entry stored in the directory + * itself. Finally, there are possibly many ".." directory entries + * stored in all the subdirectories. + * + * In order for the NFS get_parent() method to work and for the + * general consistency of the dcache, we need to make sure the + * "i_iget5_block" and "i_iget5_offset" all point to exactly one of + * the many redundant entries for each directory. We normalize the + * block and offset by always making them point to the "." directory. + * + * Notice that we do not use the entry for the directory with the name + * that is located in the parent directory. Even though choosing this + * first directory is more natural, it is much easier to find the "." + * entry in the NFS get_parent() method because it is implicitly + * encoded in the "extent + ext_attr_length" fields of _all_ the + * redundant entries for the directory. Thus, it can always be + * reached regardless of which directory entry you have in hand. + * + * This works because the "." entry is simply the first directory + * record when you start reading the file that holds all the directory + * records, and this file starts at "extent + ext_attr_length" blocks. + * Because the "." entry is always the first entry listed in the + * directories file, the normalized "offset" value is always 0. + * + * You should pass the directory entry in "de". On return, "block" + * and "offset" will hold normalized values. Only directories are + * affected making it safe to call even for non-directory file + * types. */ +static inline void +isofs_normalize_block_and_offset(struct iso_directory_record* de, + unsigned long *block, + unsigned long *offset) +{ + /* Only directories are normalized. */ + if (de->flags[0] & 2) { + *offset = 0; + *block = (unsigned long)isonum_733(de->extent) + + (unsigned long)isonum_711(de->ext_attr_length); + } +} + +extern struct inode_operations isofs_dir_inode_operations; +extern struct file_operations isofs_dir_operations; +extern struct address_space_operations isofs_symlink_aops; +extern struct export_operations isofs_export_ops; + +/* The following macros are used to check for memory leaks. */ +#ifdef LEAK_CHECK +#define free_s leak_check_free_s +#define malloc leak_check_malloc +#define sb_bread leak_check_bread +#define brelse leak_check_brelse +extern void * leak_check_malloc(unsigned int size); +extern void leak_check_free_s(void * obj, int size); +extern struct buffer_head * leak_check_bread(struct super_block *sb, int block); +extern void leak_check_brelse(struct buffer_head * bh); +#endif /* LEAK_CHECK */ diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c index 86c50e22fc87..2931de7f1a6a 100644 --- a/fs/isofs/joliet.c +++ b/fs/isofs/joliet.c @@ -6,11 +6,9 @@ * Joliet: Microsoft's Unicode extensions to iso9660 */ -#include +#include #include -#include -#include -#include +#include "isofs.h" /* * Convert Unicode 16 to UTF8 or ASCII. diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 9569fc44102d..690edf37173c 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -6,20 +6,9 @@ * (C) 1991 Linus Torvalds - minix filesystem */ -#include -#include -#include -#include -#include -#include -#include -#include #include /* Joliet? */ #include -#include -#include - -#include +#include "isofs.h" /* * ok, we cannot use strncmp, as the name is not in our data space. diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 8bdd3e409543..089e79c65585 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -6,17 +6,11 @@ * Rock Ridge Extensions to iso9660 */ -#include -#include -#include -#include -#include #include #include #include -#include -#include +#include "isofs.h" #include "rock.h" /* These functions are designed to read the system areas of a directory record diff --git a/fs/isofs/util.c b/fs/isofs/util.c index 3f6d9c1ac95a..01e1ee7a998b 100644 --- a/fs/isofs/util.c +++ b/fs/isofs/util.c @@ -2,9 +2,7 @@ * linux/fs/isofs/util.c */ -#include -#include -#include +#include "isofs.h" /* * We have to convert from a MM/DD/YY format to the Unix ctime format. @@ -80,4 +78,3 @@ int iso_date(char * p, int flag) } return crtime; } - diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h index 099039d4b10d..47967878bfef 100644 --- a/include/linux/iso_fs.h +++ b/include/linux/iso_fs.h @@ -1,4 +1,3 @@ - #ifndef _ISOFS_FS_H #define _ISOFS_FS_H @@ -163,150 +162,4 @@ struct iso_directory_record { #define ISOFS_SUPER_MAGIC 0x9660 -#ifdef __KERNEL__ -/* Number conversion inlines, named after the section in ISO 9660 - they correspond to. */ - -#include -#include -#include -#include - -static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} - -static inline struct iso_inode_info *ISOFS_I(struct inode *inode) -{ - return container_of(inode, struct iso_inode_info, vfs_inode); -} - -static inline int isonum_711(char *p) -{ - return *(u8 *)p; -} -static inline int isonum_712(char *p) -{ - return *(s8 *)p; -} -static inline unsigned int isonum_721(char *p) -{ - return le16_to_cpu(get_unaligned((__le16 *)p)); -} -static inline unsigned int isonum_722(char *p) -{ - return be16_to_cpu(get_unaligned((__le16 *)p)); -} -static inline unsigned int isonum_723(char *p) -{ - /* Ignore bigendian datum due to broken mastering programs */ - return le16_to_cpu(get_unaligned((__le16 *)p)); -} -static inline unsigned int isonum_731(char *p) -{ - return le32_to_cpu(get_unaligned((__le32 *)p)); -} -static inline unsigned int isonum_732(char *p) -{ - return be32_to_cpu(get_unaligned((__le32 *)p)); -} -static inline unsigned int isonum_733(char *p) -{ - /* Ignore bigendian datum due to broken mastering programs */ - return le32_to_cpu(get_unaligned((__le32 *)p)); -} -extern int iso_date(char *, int); - -struct inode; /* To make gcc happy */ - -extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); -extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); -extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); - -int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *); -int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); - -extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *); -extern struct buffer_head *isofs_bread(struct inode *, sector_t); -extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); - -extern struct inode *isofs_iget(struct super_block *sb, - unsigned long block, - unsigned long offset); - -/* Because the inode number is no longer relevant to finding the - * underlying meta-data for an inode, we are free to choose a more - * convenient 32-bit number as the inode number. The inode numbering - * scheme was recommended by Sergey Vlasov and Eric Lammerts. */ -static inline unsigned long isofs_get_ino(unsigned long block, - unsigned long offset, - unsigned long bufbits) -{ - return (block << (bufbits - 5)) | (offset >> 5); -} - -/* Every directory can have many redundant directory entries scattered - * throughout the directory tree. First there is the directory entry - * with the name of the directory stored in the parent directory. - * Then, there is the "." directory entry stored in the directory - * itself. Finally, there are possibly many ".." directory entries - * stored in all the subdirectories. - * - * In order for the NFS get_parent() method to work and for the - * general consistency of the dcache, we need to make sure the - * "i_iget5_block" and "i_iget5_offset" all point to exactly one of - * the many redundant entries for each directory. We normalize the - * block and offset by always making them point to the "." directory. - * - * Notice that we do not use the entry for the directory with the name - * that is located in the parent directory. Even though choosing this - * first directory is more natural, it is much easier to find the "." - * entry in the NFS get_parent() method because it is implicitly - * encoded in the "extent + ext_attr_length" fields of _all_ the - * redundant entries for the directory. Thus, it can always be - * reached regardless of which directory entry you have in hand. - * - * This works because the "." entry is simply the first directory - * record when you start reading the file that holds all the directory - * records, and this file starts at "extent + ext_attr_length" blocks. - * Because the "." entry is always the first entry listed in the - * directories file, the normalized "offset" value is always 0. - * - * You should pass the directory entry in "de". On return, "block" - * and "offset" will hold normalized values. Only directories are - * affected making it safe to call even for non-directory file - * types. */ -static inline void -isofs_normalize_block_and_offset(struct iso_directory_record* de, - unsigned long *block, - unsigned long *offset) -{ - /* Only directories are normalized. */ - if (de->flags[0] & 2) { - *offset = 0; - *block = (unsigned long)isonum_733(de->extent) - + (unsigned long)isonum_711(de->ext_attr_length); - } -} - -extern struct inode_operations isofs_dir_inode_operations; -extern struct file_operations isofs_dir_operations; -extern struct address_space_operations isofs_symlink_aops; -extern struct export_operations isofs_export_ops; - -/* The following macros are used to check for memory leaks. */ -#ifdef LEAK_CHECK -#define free_s leak_check_free_s -#define malloc leak_check_malloc -#define sb_bread leak_check_bread -#define brelse leak_check_brelse -extern void * leak_check_malloc(unsigned int size); -extern void leak_check_free_s(void * obj, int size); -extern struct buffer_head * leak_check_bread(struct super_block *sb, int block); -extern void leak_check_brelse(struct buffer_head * bh); -#endif /* LEAK_CHECK */ - -#endif /* __KERNEL__ */ - #endif diff --git a/include/linux/iso_fs_i.h b/include/linux/iso_fs_i.h deleted file mode 100644 index 59065e939eaa..000000000000 --- a/include/linux/iso_fs_i.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _ISO_FS_I -#define _ISO_FS_I - -#include - -enum isofs_file_format { - isofs_file_normal = 0, - isofs_file_sparse = 1, - isofs_file_compressed = 2, -}; - -/* - * iso fs inode data in memory - */ -struct iso_inode_info { - unsigned long i_iget5_block; - unsigned long i_iget5_offset; - unsigned int i_first_extent; - unsigned char i_file_format; - unsigned char i_format_parm[3]; - unsigned long i_next_section_block; - unsigned long i_next_section_offset; - off_t i_section_size; - struct inode vfs_inode; -}; - -#endif diff --git a/include/linux/iso_fs_sb.h b/include/linux/iso_fs_sb.h deleted file mode 100644 index 043b97b55b8d..000000000000 --- a/include/linux/iso_fs_sb.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _ISOFS_FS_SB -#define _ISOFS_FS_SB - -/* - * iso9660 super-block data in memory - */ -struct isofs_sb_info { - unsigned long s_ninodes; - unsigned long s_nzones; - unsigned long s_firstdatazone; - unsigned long s_log_zone_size; - unsigned long s_max_size; - - unsigned char s_high_sierra; /* A simple flag */ - unsigned char s_mapping; - int s_rock_offset; /* offset of SUSP fields within SU area */ - unsigned char s_rock; - unsigned char s_joliet_level; - unsigned char s_utf8; - unsigned char s_cruft; /* Broken disks with high - byte of length containing - junk */ - unsigned char s_unhide; - unsigned char s_nosuid; - unsigned char s_nodev; - unsigned char s_nocompress; - - mode_t s_mode; - gid_t s_gid; - uid_t s_uid; - struct nls_table *s_nls_iocharset; /* Native language support table */ -}; - -#endif -- cgit v1.2.3 From 2d29306b231a1a0e7a70166c10e4c0f917b21334 Mon Sep 17 00:00:00 2001 From: Martin Hicks Date: Tue, 26 Apr 2005 09:04:31 -0700 Subject: [IA64] re-enable preempt before page allocation for pgtable quicklist This is a fix to the pgtable_quicklist code. There is a GFP_KERNEL allocation in pgtable_quicklist_alloc(), which spews the usual warnings if the kernel is under heavy VM pressure and the reclaim code is invoked. re-enable preempt before we allocate the new page. This patch is against 2.6.12-rc2-mm2 Signed-off-by: Martin Hicks Signed-off-by: Tony Luck --- include/asm-ia64/pgalloc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h index 2b7127330ae1..a5f214554afd 100644 --- a/include/asm-ia64/pgalloc.h +++ b/include/asm-ia64/pgalloc.h @@ -49,12 +49,12 @@ static inline void *pgtable_quicklist_alloc(void) pgtable_quicklist = (unsigned long *)(*ret); ret[0] = 0; --pgtable_quicklist_size; + preempt_enable(); } else { + preempt_enable(); ret = (unsigned long *)__get_free_page(GFP_KERNEL | __GFP_ZERO); } - preempt_enable(); - return ret; } -- cgit v1.2.3 From ea3f4eaca09de1bcc80e922e56a6dabba5882f56 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 27 Apr 2005 18:19:55 +0100 Subject: [PATCH] ARM: Add further explaination for clk_get() clk_get() comments can be confusing. Add extra explaination of the dev and id parameters to ensure correct usage. Signed-off-by: Russell King --- include/asm-arm/hardware/clock.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-arm/hardware/clock.h b/include/asm-arm/hardware/clock.h index 4983449ff2c7..19da861e523d 100644 --- a/include/asm-arm/hardware/clock.h +++ b/include/asm-arm/hardware/clock.h @@ -26,10 +26,13 @@ struct clk; /** * clk_get - lookup and obtain a reference to a clock producer. * @dev: device for clock "consumer" - * @id: device ID + * @id: clock comsumer ID * * Returns a struct clk corresponding to the clock producer, or - * valid IS_ERR() condition containing errno. + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. (IOW, @id may be identical strings, but + * clk_get may return different clock producers depending on @dev.) */ struct clk *clk_get(struct device *dev, const char *id); -- cgit v1.2.3 From c4d12b98ead8bb2437f656c17e7ef065fa160e13 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 28 Apr 2005 10:38:19 +0100 Subject: [PATCH] ARM: Fix AMBA CLCD fb driver for 1bpp/STN mono panels Fix the AMBA CLCD framebuffer driver for 1bpp modes and STN monochrome LCD panels. Signed-off-by: Russell King --- drivers/video/amba-clcd.c | 6 +++--- include/asm-arm/hardware/amba_clcd.h | 27 +++++++++++++++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index acdba0c67fb8..075d3961a119 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -125,11 +125,11 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) case 2: case 4: case 8: - var->red.length = 8; + var->red.length = var->bits_per_pixel; var->red.offset = 0; - var->green.length = 8; + var->green.length = var->bits_per_pixel; var->green.offset = 0; - var->blue.length = 8; + var->blue.length = var->bits_per_pixel; var->blue.offset = 0; break; case 16: diff --git a/include/asm-arm/hardware/amba_clcd.h b/include/asm-arm/hardware/amba_clcd.h index 2149be7c7023..476b6398ae1e 100644 --- a/include/asm-arm/hardware/amba_clcd.h +++ b/include/asm-arm/hardware/amba_clcd.h @@ -153,7 +153,7 @@ struct clcd_fb { static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) { - u32 val; + u32 val, cpl; /* * Program the CLCD controller registers and start the CLCD @@ -164,7 +164,10 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) val |= (fb->fb.var.left_margin - 1) << 24; regs->tim0 = val; - val = fb->fb.var.yres - 1; + val = fb->fb.var.yres; + if (fb->panel->cntl & CNTL_LCDDUAL) + val /= 2; + val -= 1; val |= (fb->fb.var.vsync_len - 1) << 10; val |= fb->fb.var.lower_margin << 16; val |= fb->fb.var.upper_margin << 24; @@ -174,13 +177,17 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT ? 0 : TIM2_IHS; val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS; - if (fb->panel->cntl & CNTL_LCDTFT) - val |= (fb->fb.var.xres_virtual - 1) << 16; - else if (fb->panel->cntl & CNTL_LCDBW) - printk("what value for CPL for stnmono panels?"); - else - val |= ((fb->fb.var.xres_virtual * 8 / 3) - 1) << 16; - regs->tim2 = val; + cpl = fb->fb.var.xres_virtual; + if (fb->panel->cntl & CNTL_LCDTFT) /* TFT */ + /* / 1 */; + else if (!fb->fb.var.grayscale) /* STN color */ + cpl = cpl * 8 / 3; + else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */ + cpl /= 8; + else /* STN monochrome, 4bit */ + cpl /= 4; + + regs->tim2 = val | ((cpl - 1) << 16); regs->tim3 = fb->panel->tim3; @@ -216,7 +223,7 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) { var->xres_virtual = var->xres = (var->xres + 7) & ~7; - var->yres_virtual = var->yres; + var->yres_virtual = var->yres = (var->yres + 1) & ~1; #define CHECK(e,l,h) (var->e < l || var->e > h) if (CHECK(right_margin, (5+1), 256) || /* back porch */ -- cgit v1.2.3 From 82235e9170f19fa327361ee82a76618e60f2db47 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 28 Apr 2005 10:43:52 +0100 Subject: [PATCH] ARM: Fix AMBA CLCD fb driver for 32bpp We were supporting 24bpp. However, the pixel organisation in memory was 0RGB, so it was 24bpp in 32bit words. This means we're actually supporting 32bpp and not 24bpp. Also, add a check to ensure that we don't exceed the available framebuffer when changing display resolutions. Signed-off-by: Russell King --- drivers/video/amba-clcd.c | 8 +++++++- include/asm-arm/hardware/amba_clcd.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 075d3961a119..3e386fd4c5c6 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -146,7 +146,7 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) var->blue.offset = 10; } break; - case 24: + case 32: if (fb->panel->cntl & CNTL_LCDTFT) { var->red.length = 8; var->green.length = 8; @@ -178,6 +178,12 @@ static int clcdfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (fb->board->check) ret = fb->board->check(fb, var); + + if (ret == 0 && + var->xres_virtual * var->bits_per_pixel / 8 * + var->yres_virtual > fb->fb.fix.smem_len) + ret = -EINVAL; + if (ret == 0) ret = clcdfb_set_bitfields(fb, var); diff --git a/include/asm-arm/hardware/amba_clcd.h b/include/asm-arm/hardware/amba_clcd.h index 476b6398ae1e..d6ad33e52ea9 100644 --- a/include/asm-arm/hardware/amba_clcd.h +++ b/include/asm-arm/hardware/amba_clcd.h @@ -211,7 +211,7 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) case 16: val |= CNTL_LCDBPP16; break; - case 24: + case 32: val |= CNTL_LCDBPP24; break; } -- cgit v1.2.3 From 0f7ad450394560a6b6c72115e04bf7afd6230e70 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 28 Apr 2005 10:46:15 +0100 Subject: [PATCH] ARM: AMBA CLCD: X resolutions must be multiples of 16 We ignore the bottom 4 bits of the X resolution, so we should round X resolutions up to the nearest multiple of 16. Signed-off-by: Russell King --- include/asm-arm/hardware/amba_clcd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/hardware/amba_clcd.h b/include/asm-arm/hardware/amba_clcd.h index d6ad33e52ea9..ce4cf5c1c05d 100644 --- a/include/asm-arm/hardware/amba_clcd.h +++ b/include/asm-arm/hardware/amba_clcd.h @@ -222,7 +222,7 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs) static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) { - var->xres_virtual = var->xres = (var->xres + 7) & ~7; + var->xres_virtual = var->xres = (var->xres + 15) & ~15; var->yres_virtual = var->yres = (var->yres + 1) & ~1; #define CHECK(e,l,h) (var->e < l || var->e > h) -- cgit v1.2.3 From 047a2428a14216a83980ed26b6a59b3ca40a1fb0 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Thu, 28 Apr 2005 11:58:43 -0700 Subject: [SCTP] Implement Sec 2.41 of SCTP Implementers guide. - Fixed sctp_vtag_verify_either() to comply with impguide 2.41 B) and C). - Make sure vtag is reflected when T-bit is set in SHUTDOWN-COMPLETE sent due to an OOTB SHUTDOWN-ACK and in ABORT sent due to an OOTB packet. - Do not set T-Bit in ABORT chunk in response to INIT. - Fixed some comments to reflect the new meaning of the T-Bit. Signed-off-by: Jerome Forissier Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller --- include/net/sctp/sm.h | 42 +++++++++++++++----------- net/sctp/sm_make_chunk.c | 19 ++++++++---- net/sctp/sm_statefuns.c | 77 ++++++++++++++++++++++++++++++------------------ 3 files changed, 86 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 5576db56324d..f4fcee104707 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -407,32 +407,38 @@ sctp_vtag_verify(const struct sctp_chunk *chunk, return 0; } -/* Check VTAG of the packet matches the sender's own tag OR its peer's - * tag and the T bit is set in the Chunk Flags. +/* Check VTAG of the packet matches the sender's own tag and the T bit is + * not set, OR its peer's tag and the T bit is set in the Chunk Flags. */ static inline int sctp_vtag_verify_either(const struct sctp_chunk *chunk, const struct sctp_association *asoc) { - /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2 + /* RFC 2960 Section 8.5.1, sctpimpguide Section 2.41 * - * B) The receiver of a ABORT shall accept the packet if the - * Verification Tag field of the packet matches its own tag OR it - * is set to its peer's tag and the T bit is set in the Chunk - * Flags. Otherwise, the receiver MUST silently discard the packet - * and take no further action. - * - * (C) The receiver of a SHUTDOWN COMPLETE shall accept the - * packet if the Verification Tag field of the packet - * matches its own tag OR it is set to its peer's tag and - * the T bit is set in the Chunk Flags. Otherwise, the - * receiver MUST silently discard the packet and take no - * further action.... + * B) The receiver of a ABORT MUST accept the packet + * if the Verification Tag field of the packet matches its own tag + * and the T bit is not set + * OR + * it is set to its peer's tag and the T bit is set in the Chunk + * Flags. + * Otherwise, the receiver MUST silently discard the packet + * and take no further action. * + * C) The receiver of a SHUTDOWN COMPLETE shall accept the packet + * if the Verification Tag field of the packet matches its own tag + * and the T bit is not set + * OR + * it is set to its peer's tag and the T bit is set in the Chunk + * Flags. + * Otherwise, the receiver MUST silently discard the packet + * and take no further action. An endpoint MUST ignore the + * SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state. */ - if ((ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag) || - (sctp_test_T_bit(chunk) && (ntohl(chunk->sctp_hdr->vtag) - == asoc->c.peer_vtag))) { + if ((!sctp_test_T_bit(chunk) && + (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)) || + (sctp_test_T_bit(chunk) && + (ntohl(chunk->sctp_hdr->vtag) == asoc->c.peer_vtag))) { return 1; } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 1db12cc18cf7..33ac8bf47b0e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -710,7 +710,9 @@ struct sctp_chunk *sctp_make_shutdown_complete( struct sctp_chunk *retval; __u8 flags = 0; - /* Maybe set the T-bit if we have no association. */ + /* Set the T-bit if we have no association (vtag will be + * reflected) + */ flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T; retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0); @@ -732,7 +734,7 @@ struct sctp_chunk *sctp_make_shutdown_complete( } /* Create an ABORT. Note that we set the T bit if we have no - * association. + * association, except when responding to an INIT (sctpimpguide 2.41). */ struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc, const struct sctp_chunk *chunk, @@ -741,8 +743,16 @@ struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc, struct sctp_chunk *retval; __u8 flags = 0; - /* Maybe set the T-bit if we have no association. */ - flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T; + /* Set the T-bit if we have no association and 'chunk' is not + * an INIT (vtag will be reflected). + */ + if (!asoc) { + if (chunk && chunk->chunk_hdr && + chunk->chunk_hdr->type == SCTP_CID_INIT) + flags = 0; + else + flags = SCTP_CHUNK_FLAG_T; + } retval = sctp_make_chunk(asoc, SCTP_CID_ABORT, flags, hint); @@ -2744,7 +2754,6 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, hint = (nstreams + 1) * sizeof(__u32); - /* Maybe set the T-bit if we have no association. */ retval = sctp_make_chunk(asoc, SCTP_CID_FWD_TSN, 0, hint); if (!retval) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 278c56a2d076..8e01b8f09ac2 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -126,15 +126,18 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk, * should stop the T2-shutdown timer and remove all knowledge of the * association (and thus the association enters the CLOSED state). * - * Verification Tag: 8.5.1(C) + * Verification Tag: 8.5.1(C), sctpimpguide 2.41. * C) Rules for packet carrying SHUTDOWN COMPLETE: * ... - * - The receiver of a SHUTDOWN COMPLETE shall accept the packet if the - * Verification Tag field of the packet matches its own tag OR it is - * set to its peer's tag and the T bit is set in the Chunk Flags. - * Otherwise, the receiver MUST silently discard the packet and take - * no further action. An endpoint MUST ignore the SHUTDOWN COMPLETE if - * it is not in the SHUTDOWN-ACK-SENT state. + * - The receiver of a SHUTDOWN COMPLETE shall accept the packet + * if the Verification Tag field of the packet matches its own tag and + * the T bit is not set + * OR + * it is set to its peer's tag and the T bit is set in the Chunk + * Flags. + * Otherwise, the receiver MUST silently discard the packet + * and take no further action. An endpoint MUST ignore the + * SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state. * * Inputs * (endpoint, asoc, chunk) @@ -2858,16 +2861,16 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, /* * Generate an ABORT in response to a packet. * - * Section: 8.4 Handle "Out of the blue" Packets + * Section: 8.4 Handle "Out of the blue" Packets, sctpimpguide 2.41 * - * 8) The receiver should respond to the sender of the OOTB packet - * with an ABORT. When sending the ABORT, the receiver of the - * OOTB packet MUST fill in the Verification Tag field of the - * outbound packet with the value found in the Verification Tag - * field of the OOTB packet and set the T-bit in the Chunk Flags - * to indicate that no TCB was found. After sending this ABORT, - * the receiver of the OOTB packet shall discard the OOTB packet - * and take no further action. + * 8) The receiver should respond to the sender of the OOTB packet with + * an ABORT. When sending the ABORT, the receiver of the OOTB packet + * MUST fill in the Verification Tag field of the outbound packet + * with the value found in the Verification Tag field of the OOTB + * packet and set the T-bit in the Chunk Flags to indicate that the + * Verification Tag is reflected. After sending this ABORT, the + * receiver of the OOTB packet shall discard the OOTB packet and take + * no further action. * * Verification Tag: * @@ -2895,6 +2898,10 @@ sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, return SCTP_DISPOSITION_NOMEM; } + /* Reflect vtag if T-Bit is set */ + if (sctp_test_T_bit(abort)) + packet->vtag = ntohl(chunk->sctp_hdr->vtag); + /* Set the skb to the belonging sock for accounting. */ abort->skb->sk = ep->base.sk; @@ -3026,22 +3033,24 @@ nomem: } /* - * RFC 2960, 8.4 - Handle "Out of the blue" Packets + * RFC 2960, 8.4 - Handle "Out of the blue" Packets, sctpimpguide 2.41. + * * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should * respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE. * When sending the SHUTDOWN COMPLETE, the receiver of the OOTB * packet must fill in the Verification Tag field of the outbound * packet with the Verification Tag received in the SHUTDOWN ACK and - * set the T-bit in the Chunk Flags to indicate that no TCB was - * found. Otherwise, + * set the T-bit in the Chunk Flags to indicate that the Verification + * Tag is reflected. * * 8) The receiver should respond to the sender of the OOTB packet with * an ABORT. When sending the ABORT, the receiver of the OOTB packet * MUST fill in the Verification Tag field of the outbound packet * with the value found in the Verification Tag field of the OOTB - * packet and set the T-bit in the Chunk Flags to indicate that no - * TCB was found. After sending this ABORT, the receiver of the OOTB - * packet shall discard the OOTB packet and take no further action. + * packet and set the T-bit in the Chunk Flags to indicate that the + * Verification Tag is reflected. After sending this ABORT, the + * receiver of the OOTB packet shall discard the OOTB packet and take + * no further action. */ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, const struct sctp_association *asoc, @@ -3090,13 +3099,15 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, /* * Handle an "Out of the blue" SHUTDOWN ACK. * - * Section: 8.4 5) + * Section: 8.4 5, sctpimpguide 2.41. + * * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should - * respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE. - * When sending the SHUTDOWN COMPLETE, the receiver of the OOTB packet - * must fill in the Verification Tag field of the outbound packet with - * the Verification Tag received in the SHUTDOWN ACK and set the - * T-bit in the Chunk Flags to indicate that no TCB was found. + * respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE. + * When sending the SHUTDOWN COMPLETE, the receiver of the OOTB + * packet must fill in the Verification Tag field of the outbound + * packet with the Verification Tag received in the SHUTDOWN ACK and + * set the T-bit in the Chunk Flags to indicate that the Verification + * Tag is reflected. * * Inputs * (endpoint, asoc, type, arg, commands) @@ -3128,6 +3139,10 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, return SCTP_DISPOSITION_NOMEM; } + /* Reflect vtag if T-Bit is set */ + if (sctp_test_T_bit(shut)) + packet->vtag = ntohl(chunk->sctp_hdr->vtag); + /* Set the skb to the belonging sock for accounting. */ shut->skb->sk = ep->base.sk; @@ -3591,7 +3606,6 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep, * * 2) If the OOTB packet contains an ABORT chunk, the receiver MUST * silently discard the OOTB packet and take no further action. - * Otherwise, * * Verification Tag: No verification necessary * @@ -4961,6 +4975,11 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep, sctp_ootb_pkt_free(packet); return NULL; } + + /* Reflect vtag if T-Bit is set */ + if (sctp_test_T_bit(abort)) + packet->vtag = ntohl(chunk->sctp_hdr->vtag); + /* Add specified error causes, i.e., payload, to the * end of the chunk. */ -- cgit v1.2.3 From 4eb701dfc618491c9b97377df6e61de36dfc39ce Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 28 Apr 2005 12:02:04 -0700 Subject: [SCTP] Fix SCTP sendbuffer accouting. - Include chunk and skb sizes in sendbuffer accounting. - 2 policies are supported. 0: per socket accouting, 1: per association accounting DaveM: I've made the default per-socket. Signed-off-by: Neil Horman Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller --- include/linux/sysctl.h | 1 + include/net/sctp/structs.h | 11 ++++++++++- net/sctp/endpointola.c | 1 + net/sctp/protocol.c | 3 +++ net/sctp/socket.c | 36 +++++++++++++++++++++++++++++++----- net/sctp/sysctl.c | 8 ++++++++ 6 files changed, 54 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 358d52b0c445..772998147e3e 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -643,6 +643,7 @@ enum { NET_SCTP_MAX_BURST = 12, NET_SCTP_ADDIP_ENABLE = 13, NET_SCTP_PRSCTP_ENABLE = 14, + NET_SCTP_SNDBUF_POLICY = 15, }; /* /proc/sys/net/bridge */ diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 7e64cf6bda1e..6c24d9cd3d66 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -154,6 +154,13 @@ extern struct sctp_globals { int max_retrans_path; int max_retrans_init; + /* + * Policy for preforming sctp/socket accounting + * 0 - do socket level accounting, all assocs share sk_sndbuf + * 1 - do sctp accounting, each asoc may use sk_sndbuf bytes + */ + int sndbuf_policy; + /* HB.interval - 30 seconds */ int hb_interval; @@ -207,6 +214,7 @@ extern struct sctp_globals { #define sctp_valid_cookie_life (sctp_globals.valid_cookie_life) #define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable) #define sctp_max_retrans_association (sctp_globals.max_retrans_association) +#define sctp_sndbuf_policy (sctp_globals.sndbuf_policy) #define sctp_max_retrans_path (sctp_globals.max_retrans_path) #define sctp_max_retrans_init (sctp_globals.max_retrans_init) #define sctp_hb_interval (sctp_globals.hb_interval) @@ -1212,7 +1220,8 @@ struct sctp_endpoint { /* Default timeouts. */ int timeouts[SCTP_NUM_TIMEOUT_TYPES]; - /* Various thresholds. */ + /* sendbuf acct. policy. */ + __u32 sndbuf_policy; /* Name for debugging output... */ char *debug_name; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 544b75077dbd..334f61773e6d 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -125,6 +125,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, sp->autoclose * HZ; /* Use SCTP specific send buffer space queues. */ + ep->sndbuf_policy = sctp_sndbuf_policy; sk->sk_write_space = sctp_write_space; sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 23c85a236c41..2e1f9c3556f5 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1043,6 +1043,9 @@ SCTP_STATIC __init int sctp_init(void) sctp_max_retrans_path = 5; sctp_max_retrans_init = 8; + /* Sendbuffer growth - do per-socket accounting */ + sctp_sndbuf_policy = 0; + /* HB.interval - 30 seconds */ sctp_hb_interval = 30 * HZ; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 32f2249411fa..0b338eca6dc0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -115,9 +115,17 @@ static inline int sctp_wspace(struct sctp_association *asoc) struct sock *sk = asoc->base.sk; int amt = 0; - amt = sk->sk_sndbuf - asoc->sndbuf_used; + if (asoc->ep->sndbuf_policy) { + /* make sure that no association uses more than sk_sndbuf */ + amt = sk->sk_sndbuf - asoc->sndbuf_used; + } else { + /* do socket level accounting */ + amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); + } + if (amt < 0) amt = 0; + return amt; } @@ -138,12 +146,21 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk) /* The sndbuf space is tracked per association. */ sctp_association_hold(asoc); + skb_set_owner_w(chunk->skb, sk); + chunk->skb->destructor = sctp_wfree; /* Save the chunk pointer in skb for sctp_wfree to use later. */ *((struct sctp_chunk **)(chunk->skb->cb)) = chunk; - asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk); - sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk); + asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) + + sizeof(struct sk_buff) + + sizeof(struct sctp_chunk); + + sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk) + + sizeof(struct sk_buff) + + sizeof(struct sctp_chunk); + + atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); } /* Verify that this is a valid address. */ @@ -4422,8 +4439,17 @@ static void sctp_wfree(struct sk_buff *skb) chunk = *((struct sctp_chunk **)(skb->cb)); asoc = chunk->asoc; sk = asoc->base.sk; - asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk); - sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk); + asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) + + sizeof(struct sk_buff) + + sizeof(struct sctp_chunk); + + sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk) + + sizeof(struct sk_buff) + + sizeof(struct sctp_chunk); + + atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); + + sock_wfree(skb); __sctp_write_space(asoc); sctp_association_put(asoc); diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 89fa20c73a5c..7fc31849312b 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -109,6 +109,14 @@ static ctl_table sctp_table[] = { .mode = 0644, .proc_handler = &proc_dointvec }, + { + .ctl_name = NET_SCTP_SNDBUF_POLICY, + .procname = "sndbuf_policy", + .data = &sctp_sndbuf_policy, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec + }, { .ctl_name = NET_SCTP_PATH_MAX_RETRANS, .procname = "path_max_retrans", -- cgit v1.2.3 From 7b3c63ac7cb5e2e6680727045aa35c2e5f1bace7 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 28 Apr 2005 12:14:37 -0700 Subject: [PKT_SCHED]: Fix range in psched_tod_diff() to 0..bound Signed-off-by: Nicolas Dichtel Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/net/pkt_sched.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 87496e3aa330..7352e455053c 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -140,7 +140,7 @@ psched_tod_diff(int delta_sec, int bound) if (bound <= 1000000 || delta_sec > (0x7FFFFFFF/1000000)-1) return bound; delta = delta_sec * 1000000; - if (delta > bound) + if (delta > bound || delta < 0) delta = bound; return delta; } @@ -156,7 +156,8 @@ psched_tod_diff(int delta_sec, int bound) __delta += 1000000; \ case 1: \ __delta += 1000000; \ - case 0: ; \ + case 0: \ + __delta = abs(__delta); \ } \ __delta; \ }) -- cgit v1.2.3 From 42d4dc3f4e1ec1396371aac89d0dccfdd977191b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 29 Apr 2005 07:40:12 -0700 Subject: [PATCH] Add suspend method to cpufreq core In order to properly fix some issues with cpufreq vs. sleep on PowerBooks, I had to add a suspend callback to the pmac_cpufreq driver. I must force a switch to full speed before sleep and I switch back to previous speed on resume. I also added a driver flag to disable the warnings in suspend/resume since it is expected in this case to have different speed (and I want it to fixup the jiffies properly). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq.c | 94 ++++++++++++++++++++++++++++++++++++++++++++--- include/linux/cpufreq.h | 5 ++- 2 files changed, 93 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b30001f31610..4fc0cb79f18f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -223,7 +223,7 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) } if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) || - (val == CPUFREQ_RESUMECHANGE)) { + (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) { loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new); } @@ -865,12 +865,91 @@ unsigned int cpufreq_get(unsigned int cpu) EXPORT_SYMBOL(cpufreq_get); +/** + * cpufreq_suspend - let the low level driver prepare for suspend + */ + +static int cpufreq_suspend(struct sys_device * sysdev, u32 state) +{ + int cpu = sysdev->id; + unsigned int ret = 0; + unsigned int cur_freq = 0; + struct cpufreq_policy *cpu_policy; + + dprintk("resuming cpu %u\n", cpu); + + if (!cpu_online(cpu)) + return 0; + + /* we may be lax here as interrupts are off. Nonetheless + * we need to grab the correct cpu policy, as to check + * whether we really run on this CPU. + */ + + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) + return -EINVAL; + + /* only handle each CPU group once */ + if (unlikely(cpu_policy->cpu != cpu)) { + cpufreq_cpu_put(cpu_policy); + return 0; + } + + if (cpufreq_driver->suspend) { + ret = cpufreq_driver->suspend(cpu_policy, state); + if (ret) { + printk(KERN_ERR "cpufreq: suspend failed in ->suspend " + "step on CPU %u\n", cpu_policy->cpu); + cpufreq_cpu_put(cpu_policy); + return ret; + } + } + + + if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS) + goto out; + + if (cpufreq_driver->get) + cur_freq = cpufreq_driver->get(cpu_policy->cpu); + + if (!cur_freq || !cpu_policy->cur) { + printk(KERN_ERR "cpufreq: suspend failed to assert current " + "frequency is what timing core thinks it is.\n"); + goto out; + } + + if (unlikely(cur_freq != cpu_policy->cur)) { + struct cpufreq_freqs freqs; + + if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) + printk(KERN_DEBUG "Warning: CPU frequency is %u, " + "cpufreq assumed %u kHz.\n", + cur_freq, cpu_policy->cur); + + freqs.cpu = cpu; + freqs.old = cpu_policy->cur; + freqs.new = cur_freq; + + notifier_call_chain(&cpufreq_transition_notifier_list, + CPUFREQ_SUSPENDCHANGE, &freqs); + adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); + + cpu_policy->cur = cur_freq; + } + + out: + cpufreq_cpu_put(cpu_policy); + return 0; +} + /** * cpufreq_resume - restore proper CPU frequency handling after resume * * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) * 2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync - * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are restored. + * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are + * restored. */ static int cpufreq_resume(struct sys_device * sysdev) { @@ -915,7 +994,9 @@ static int cpufreq_resume(struct sys_device * sysdev) cur_freq = cpufreq_driver->get(cpu_policy->cpu); if (!cur_freq || !cpu_policy->cur) { - printk(KERN_ERR "cpufreq: resume failed to assert current frequency is what timing core thinks it is.\n"); + printk(KERN_ERR "cpufreq: resume failed to assert " + "current frequency is what timing core " + "thinks it is.\n"); goto out; } @@ -923,13 +1004,15 @@ static int cpufreq_resume(struct sys_device * sysdev) struct cpufreq_freqs freqs; printk(KERN_WARNING "Warning: CPU frequency is %u, " - "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); + "cpufreq assumed %u kHz.\n", + cur_freq, cpu_policy->cur); freqs.cpu = cpu; freqs.old = cpu_policy->cur; freqs.new = cur_freq; - notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs); + notifier_call_chain(&cpufreq_transition_notifier_list, + CPUFREQ_RESUMECHANGE, &freqs); adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); cpu_policy->cur = cur_freq; @@ -945,6 +1028,7 @@ out: static struct sysdev_driver cpufreq_sysdev_driver = { .add = cpufreq_add_dev, .remove = cpufreq_remove_dev, + .suspend = cpufreq_suspend, .resume = cpufreq_resume, }; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 910eca35583d..f21af067d015 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -103,6 +103,7 @@ struct cpufreq_policy { #define CPUFREQ_PRECHANGE (0) #define CPUFREQ_POSTCHANGE (1) #define CPUFREQ_RESUMECHANGE (8) +#define CPUFREQ_SUSPENDCHANGE (9) struct cpufreq_freqs { unsigned int cpu; /* cpu nr */ @@ -200,6 +201,7 @@ struct cpufreq_driver { /* optional */ int (*exit) (struct cpufreq_policy *policy); + int (*suspend) (struct cpufreq_policy *policy, u32 state); int (*resume) (struct cpufreq_policy *policy); struct freq_attr **attr; }; @@ -211,7 +213,8 @@ struct cpufreq_driver { #define CPUFREQ_CONST_LOOPS 0x02 /* loops_per_jiffy or other kernel * "constants" aren't affected by * frequency transitions */ - +#define CPUFREQ_PM_NO_WARN 0x04 /* don't warn on suspend/resume speed + * mismatches */ int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); -- cgit v1.2.3 From 83c7d09173fdb6b06b109e65895392db3e49ac9c Mon Sep 17 00:00:00 2001 From: Date: Fri, 29 Apr 2005 15:54:44 +0100 Subject: AUDIT: Avoid log pollution by untrusted strings. We log strings from userspace, such as arguments to open(). These could be formatted to contain \n followed by fake audit log entries. Provide a function for logging such strings, which gives a hex dump when the string contains anything but basic printable ASCII characters. Use it for logging filenames. Signed-off-by: David Woodhouse --- include/linux/audit.h | 8 +++++++- kernel/audit.c | 23 +++++++++++++++++++++++ kernel/auditsc.c | 7 ++++--- 3 files changed, 34 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/audit.h b/include/linux/audit.h index 3628f7cfb178..9b77992c4888 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -174,11 +174,15 @@ extern void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) __attribute__((format(printf,2,3))); extern void audit_log_end(struct audit_buffer *ab); +extern void audit_log_hex(struct audit_buffer *ab, + const unsigned char *buf, + size_t len); +extern void audit_log_untrustedstring(struct audit_buffer *ab, + const char *string); extern void audit_log_d_path(struct audit_buffer *ab, const char *prefix, struct dentry *dentry, struct vfsmount *vfsmnt); - /* Private API (for auditsc.c only) */ extern void audit_send_reply(int pid, int seq, int type, int done, int multi, @@ -190,6 +194,8 @@ extern void audit_log_lost(const char *message); #define audit_log_vformat(b,f,a) do { ; } while (0) #define audit_log_format(b,f,...) do { ; } while (0) #define audit_log_end(b) do { ; } while (0) +#define audit_log_hex(a,b,l) do { ; } while (0) +#define audit_log_untrustedstring(a,s) do { ; } while (0) #define audit_log_d_path(b,p,d,v) do { ; } while (0) #endif #endif diff --git a/kernel/audit.c b/kernel/audit.c index 0f84dd7af2c8..dca7b99615d2 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -720,6 +720,29 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) va_end(args); } +void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len) +{ + int i; + + for (i=0; i 0x7f) { + audit_log_hex(ab, string, strlen(string)); + return; + } + p++; + } + audit_log_format(ab, "\"%s\"", string); +} + + /* This is a helper-function to print the d_path without using a static * buffer or allocating another buffer in addition to the one in * audit_buffer. */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 6f1931381bc9..00e87ffff13b 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -696,9 +696,10 @@ static void audit_log_exit(struct audit_context *context) if (!ab) continue; /* audit_panic has been called */ audit_log_format(ab, "item=%d", i); - if (context->names[i].name) - audit_log_format(ab, " name=%s", - context->names[i].name); + if (context->names[i].name) { + audit_log_format(ab, " name="); + audit_log_untrustedstring(ab, context->names[i].name); + } if (context->names[i].ino != (unsigned long)-1) audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" " uid=%d gid=%d rdev=%02x:%02x", -- cgit v1.2.3 From 2fd6f58ba6efc82ea2c9c2630f7ff5ed9eeaf34a Mon Sep 17 00:00:00 2001 From: Date: Fri, 29 Apr 2005 16:08:28 +0100 Subject: [AUDIT] Don't allow ptrace to fool auditing, log arch of audited syscalls. We were calling ptrace_notify() after auditing the syscall and arguments, but the debugger could have _changed_ them before the syscall was actually invoked. Reorder the calls to fix that. While we're touching ever call to audit_syscall_entry(), we also make it take an extra argument: the architecture of the syscall which was made, because some architectures allow more than one type of syscall. Also add an explicit success/failure flag to audit_syscall_exit(), for the benefit of architectures which return that in a condition register rather than only returning a single register. Change type of syscall return value to 'long' not 'int'. Signed-off-by: David Woodhouse --- arch/i386/kernel/ptrace.c | 19 +++++++++--------- arch/ia64/kernel/ptrace.c | 21 ++++++++++++-------- arch/mips/kernel/ptrace.c | 38 +++++++++++++++++++++++++---------- arch/ppc64/kernel/ptrace.c | 15 +++++++++----- arch/s390/kernel/ptrace.c | 21 ++++++++++---------- arch/x86_64/kernel/ptrace.c | 13 +++++++----- include/linux/audit.h | 48 +++++++++++++++++++++++++++++++++++++++++---- kernel/auditsc.c | 22 +++++++++++++++------ 8 files changed, 139 insertions(+), 58 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index b2f17640ceff..5606ec7a5c2b 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -682,24 +682,18 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit) /* do the secure computing check first */ secure_computing(regs->orig_eax); - if (unlikely(current->audit_context)) { - if (!entryexit) - audit_syscall_entry(current, regs->orig_eax, - regs->ebx, regs->ecx, - regs->edx, regs->esi); - else - audit_syscall_exit(current, regs->eax); - } + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax); if (!(current->ptrace & PT_PTRACED)) - return; + goto out; /* Fake a debug trap */ if (test_thread_flag(TIF_SINGLESTEP)) send_sigtrap(current, regs, 0); if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + goto out; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ @@ -714,4 +708,9 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit) send_sig(current->exit_code, current, 1); current->exit_code = 0; } + out: + if (unlikely(current->audit_context) && !entryexit) + audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax, + regs->ebx, regs->ecx, regs->edx, regs->esi); + } diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 55789fcd7210..8dde0b16d4c8 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1595,20 +1595,25 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, struct pt_regs regs) { - long syscall; + if (test_thread_flag(TIF_SYSCALL_TRACE) + && (current->ptrace & PT_PTRACED)) + syscall_trace(); if (unlikely(current->audit_context)) { - if (IS_IA32_PROCESS(®s)) + long syscall; + int arch; + + if (IS_IA32_PROCESS(®s)) { syscall = regs.r1; - else + arch = AUDIT_ARCH_I386; + } else { syscall = regs.r15; + arch = AUDIT_ARCH_IA64; + } - audit_syscall_entry(current, syscall, arg0, arg1, arg2, arg3); + audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3); } - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - syscall_trace(); } /* "asmlinkage" so the input arguments are preserved... */ @@ -1619,7 +1624,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, struct pt_regs regs) { if (unlikely(current->audit_context)) - audit_syscall_exit(current, regs.r8); + audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8); if (test_thread_flag(TIF_SYSCALL_TRACE) && (current->ptrace & PT_PTRACED)) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 92f2c39afe27..eaf7be9d0b0a 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -300,25 +300,38 @@ out: return ret; } +static inline int audit_arch() +{ +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#ifdef CONFIG_MIPS64 + if (!(current->thread.mflags & MF_32BIT_REGS)) + return AUDIT_ARCH_MIPSEL64; +#endif /* MIPS64 */ + return AUDIT_ARCH_MIPSEL; + +#else /* big endian... */ +#ifdef CONFIG_MIPS64 + if (!(current->thread.mflags & MF_32BIT_REGS)) + return AUDIT_ARCH_MIPS64; +#endif /* MIPS64 */ + return AUDIT_ARCH_MIPS; + +#endif /* endian */ +} + /* * Notification of system call entry/exit * - triggered by current->work.syscall_trace */ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) { - if (unlikely(current->audit_context)) { - if (!entryexit) - audit_syscall_entry(current, regs->regs[2], - regs->regs[4], regs->regs[5], - regs->regs[6], regs->regs[7]); - else - audit_syscall_exit(current, regs->regs[2]); - } + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]), regs->regs[2]); if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + goto out; if (!(current->ptrace & PT_PTRACED)) - return; + goto out; /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ @@ -334,4 +347,9 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) send_sig(current->exit_code, current, 1); current->exit_code = 0; } + out: + if (unlikely(current->audit_context) && !entryexit) + audit_syscall_entry(current, audit_arch(), regs->regs[2], + regs->regs[4], regs->regs[5], + regs->regs[6], regs->regs[7]); } diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index 354a287c67eb..3c76333ec3a9 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c @@ -304,14 +304,17 @@ static void do_syscall_trace(void) void do_syscall_trace_enter(struct pt_regs *regs) { + if (test_thread_flag(TIF_SYSCALL_TRACE) + && (current->ptrace & PT_PTRACED)) + do_syscall_trace(); + if (unlikely(current->audit_context)) - audit_syscall_entry(current, regs->gpr[0], + audit_syscall_entry(current, + test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64, + regs->gpr[0], regs->gpr[3], regs->gpr[4], regs->gpr[5], regs->gpr[6]); - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - do_syscall_trace(); } void do_syscall_trace_leave(struct pt_regs *regs) @@ -319,7 +322,9 @@ void do_syscall_trace_leave(struct pt_regs *regs) secure_computing(regs->gpr[0]); if (unlikely(current->audit_context)) - audit_syscall_exit(current, regs->result); + audit_syscall_exit(current, + (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, + regs->result); if ((test_thread_flag(TIF_SYSCALL_TRACE) || test_thread_flag(TIF_SINGLESTEP)) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 647233c02fc8..2d546c67f7c3 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -711,18 +711,13 @@ out: asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) { - if (unlikely(current->audit_context)) { - if (!entryexit) - audit_syscall_entry(current, regs->gprs[2], - regs->orig_gpr2, regs->gprs[3], - regs->gprs[4], regs->gprs[5]); - else - audit_syscall_exit(current, regs->gprs[2]); - } + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]); + if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + goto out; if (!(current->ptrace & PT_PTRACED)) - return; + goto out; ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); @@ -735,4 +730,10 @@ syscall_trace(struct pt_regs *regs, int entryexit) send_sig(current->exit_code, current, 1); current->exit_code = 0; } + out: + if (unlikely(current->audit_context) && !entryexit) + audit_syscall_entry(current, + test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X, + regs->gprs[2], regs->orig_gpr2, regs->gprs[3], + regs->gprs[4], regs->gprs[5]); } diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index c7011675007d..ecbccbbf5c2a 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -629,25 +629,28 @@ static void syscall_trace(struct pt_regs *regs) } } +#define audit_arch() (test_thread_flag(TIF_IA32) ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64) + asmlinkage void syscall_trace_enter(struct pt_regs *regs) { /* do the secure computing check first */ secure_computing(regs->orig_rax); + if (test_thread_flag(TIF_SYSCALL_TRACE) + && (current->ptrace & PT_PTRACED)) + syscall_trace(regs); + if (unlikely(current->audit_context)) - audit_syscall_entry(current, regs->orig_rax, + audit_syscall_entry(current, audit_arch(), regs->orig_rax, regs->rdi, regs->rsi, regs->rdx, regs->r10); - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - syscall_trace(regs); } asmlinkage void syscall_trace_leave(struct pt_regs *regs) { if (unlikely(current->audit_context)) - audit_syscall_exit(current, regs->rax); + audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax); if ((test_thread_flag(TIF_SYSCALL_TRACE) || test_thread_flag(TIF_SINGLESTEP)) diff --git a/include/linux/audit.h b/include/linux/audit.h index 9b77992c4888..fad0c1dc21a9 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -24,6 +24,9 @@ #ifndef _LINUX_AUDIT_H_ #define _LINUX_AUDIT_H_ +#include +#include + /* Request and reply types */ #define AUDIT_GET 1000 /* Get status */ #define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */ @@ -67,6 +70,7 @@ #define AUDIT_FSGID 8 #define AUDIT_LOGINUID 9 #define AUDIT_PERS 10 +#define AUDIT_ARCH 11 /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -96,6 +100,38 @@ #define AUDIT_FAIL_PRINTK 1 #define AUDIT_FAIL_PANIC 2 +/* distinguish syscall tables */ +#define __AUDIT_ARCH_64BIT 0x80000000 +#define __AUDIT_ARCH_LE 0x40000000 +#define AUDIT_ARCH_ALPHA (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_ARMEB (EM_ARM) +#define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_FRV (EM_FRV) +#define AUDIT_ARCH_H8300 (EM_H8_300) +#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_IA64 (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_M32R (EM_M32R) +#define AUDIT_ARCH_M68K (EM_68K) +#define AUDIT_ARCH_MIPS (EM_MIPS) +#define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_MIPS64 (EM_MIPS|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_PARISC (EM_PARISC) +#define AUDIT_ARCH_PARISC64 (EM_PARISC|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_PPC (EM_PPC) +#define AUDIT_ARCH_PPC64 (EM_PPC64|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_S390 (EM_S390) +#define AUDIT_ARCH_S390X (EM_S390|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_SH (EM_SH) +#define AUDIT_ARCH_SHEL (EM_SH|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_SH64 (EM_SH|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_SHEL64 (EM_SH|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_SPARC (EM_SPARC) +#define AUDIT_ARCH_SPARC64 (EM_SPARC64|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) + #ifndef __KERNEL__ struct audit_message { struct nlmsghdr nlh; @@ -129,15 +165,19 @@ struct audit_buffer; struct audit_context; struct inode; +#define AUDITSC_INVALID 0 +#define AUDITSC_SUCCESS 1 +#define AUDITSC_FAILURE 2 +#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) #ifdef CONFIG_AUDITSYSCALL /* These are defined in auditsc.c */ /* Public API */ extern int audit_alloc(struct task_struct *task); extern void audit_free(struct task_struct *task); -extern void audit_syscall_entry(struct task_struct *task, +extern void audit_syscall_entry(struct task_struct *task, int arch, int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3); -extern void audit_syscall_exit(struct task_struct *task, int return_code); +extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code); extern void audit_getname(const char *name); extern void audit_putname(const char *name); extern void audit_inode(const char *name, const struct inode *inode); @@ -153,8 +193,8 @@ extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mo #else #define audit_alloc(t) ({ 0; }) #define audit_free(t) do { ; } while (0) -#define audit_syscall_entry(t,a,b,c,d,e) do { ; } while (0) -#define audit_syscall_exit(t,r) do { ; } while (0) +#define audit_syscall_entry(t,ta,a,b,c,d,e) do { ; } while (0) +#define audit_syscall_exit(t,f,r) do { ; } while (0) #define audit_getname(n) do { ; } while (0) #define audit_putname(n) do { ; } while (0) #define audit_inode(n,i) do { ; } while (0) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 00e87ffff13b..77e92592de57 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -123,7 +123,7 @@ struct audit_context { int major; /* syscall number */ unsigned long argv[4]; /* syscall arguments */ int return_valid; /* return code is valid */ - int return_code;/* syscall return code */ + long return_code;/* syscall return code */ int auditable; /* 1 if record should be written */ int name_count; struct audit_names names[AUDIT_NAMES]; @@ -135,6 +135,7 @@ struct audit_context { uid_t uid, euid, suid, fsuid; gid_t gid, egid, sgid, fsgid; unsigned long personality; + int arch; #if AUDIT_DEBUG int put_count; @@ -348,6 +349,10 @@ static int audit_filter_rules(struct task_struct *tsk, case AUDIT_PERS: result = (tsk->personality == value); break; + case AUDIT_ARCH: + if (ctx) + result = (ctx->arch == value); + break; case AUDIT_EXIT: if (ctx && ctx->return_valid) @@ -355,7 +360,7 @@ static int audit_filter_rules(struct task_struct *tsk, break; case AUDIT_SUCCESS: if (ctx && ctx->return_valid) - result = (ctx->return_code >= 0); + result = (ctx->return_valid == AUDITSC_SUCCESS); break; case AUDIT_DEVMAJOR: if (ctx) { @@ -648,8 +653,11 @@ static void audit_log_exit(struct audit_context *context) audit_log_format(ab, "syscall=%d", context->major); if (context->personality != PER_LINUX) audit_log_format(ab, " per=%lx", context->personality); + audit_log_format(ab, " arch=%x", context->arch); if (context->return_valid) - audit_log_format(ab, " exit=%d", context->return_code); + audit_log_format(ab, " success=%s exit=%ld", + (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", + context->return_code); audit_log_format(ab, " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" " pid=%d loginuid=%d uid=%d gid=%d" @@ -773,7 +781,7 @@ static inline unsigned int audit_serial(void) * then the record will be written at syscall exit time (otherwise, it * will only be written if another part of the kernel requests that it * be written). */ -void audit_syscall_entry(struct task_struct *tsk, int major, +void audit_syscall_entry(struct task_struct *tsk, int arch, int major, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4) { @@ -827,6 +835,7 @@ void audit_syscall_entry(struct task_struct *tsk, int major, if (!audit_enabled) return; + context->arch = arch; context->major = major; context->argv[0] = a1; context->argv[1] = a2; @@ -850,13 +859,13 @@ void audit_syscall_entry(struct task_struct *tsk, int major, * filtering, or because some other part of the kernel write an audit * message), then write out the syscall information. In call cases, * free the names stored from getname(). */ -void audit_syscall_exit(struct task_struct *tsk, int return_code) +void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code) { struct audit_context *context; get_task_struct(tsk); task_lock(tsk); - context = audit_get_context(tsk, 1, return_code); + context = audit_get_context(tsk, valid, return_code); task_unlock(tsk); /* Not having a context here is ok, since the parent may have @@ -869,6 +878,7 @@ void audit_syscall_exit(struct task_struct *tsk, int return_code) context->in_syscall = 0; context->auditable = 0; + if (context->previous) { struct audit_context *new_context = context->previous; context->previous = NULL; -- cgit v1.2.3 From d812ddbb89e323d054a7d073466225966c8350c8 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Fri, 29 Apr 2005 16:09:52 +0100 Subject: [AUDIT] Fix signedness of 'serial' in various routines. Attached is a patch that corrects a signed/unsigned warning. I also noticed that we needlessly init serial to 0. That only needs to occur if the kernel was compiled without the audit system. -Steve Grubb Signed-off-by: David Woodhouse --- include/linux/audit.h | 2 +- kernel/audit.c | 6 ++++-- kernel/auditsc.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/audit.h b/include/linux/audit.h index fad0c1dc21a9..0467f2441b68 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -186,7 +186,7 @@ extern void audit_inode(const char *name, const struct inode *inode); extern int audit_receive_filter(int type, int pid, int uid, int seq, void *data); extern void audit_get_stamp(struct audit_context *ctx, - struct timespec *t, int *serial); + struct timespec *t, unsigned int *serial); extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid); extern uid_t audit_get_loginuid(struct audit_context *ctx); extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); diff --git a/kernel/audit.c b/kernel/audit.c index e7bff8000d23..aa35422c0c42 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -620,7 +620,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx) struct audit_buffer *ab = NULL; unsigned long flags; struct timespec t; - int serial = 0; + unsigned int serial; if (!audit_initialized) return NULL; @@ -669,8 +669,10 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx) audit_get_stamp(ab->ctx, &t, &serial); else #endif + { t = CURRENT_TIME; - + serial = 0; + } audit_log_format(ab, "audit(%lu.%03lu:%u): ", t.tv_sec, t.tv_nsec/1000000, serial); return ab; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 77e92592de57..49ecd707b953 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -992,7 +992,7 @@ void audit_inode(const char *name, const struct inode *inode) } void audit_get_stamp(struct audit_context *ctx, - struct timespec *t, int *serial) + struct timespec *t, unsigned int *serial) { if (ctx) { t->tv_sec = ctx->ctime.tv_sec; -- cgit v1.2.3 From 85c8721ff3bc96b702427a440616079e8daf8a2f Mon Sep 17 00:00:00 2001 From: Date: Fri, 29 Apr 2005 16:23:29 +0100 Subject: audit: update pointer to userspace tools, remove emacs mode tags --- include/linux/audit.h | 2 +- kernel/audit.c | 4 ++-- kernel/auditsc.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/audit.h b/include/linux/audit.h index 0467f2441b68..5fabe8481011 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -1,4 +1,4 @@ -/* audit.h -- Auditing support -*- linux-c -*- +/* audit.h -- Auditing support * * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. * All Rights Reserved. diff --git a/kernel/audit.c b/kernel/audit.c index 42ce282728b6..58c7d7e47299 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1,4 +1,4 @@ -/* audit.c -- Auditing support -*- linux-c -*- +/* audit.c -- Auditing support * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. * System-call specific features have moved to auditsc.c * @@ -38,7 +38,7 @@ * 6) Support low-overhead kernel-based filtering to minimize the * information that must be passed to user-space. * - * Example user-space utilities: http://people.redhat.com/faith/audit/ + * Example user-space utilities: http://people.redhat.com/sgrubb/audit/ */ #include diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 49ecd707b953..9ff2c1b1033e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1,4 +1,4 @@ -/* auditsc.c -- System-call auditing support -*- linux-c -*- +/* auditsc.c -- System-call auditing support * Handles all system-call specific auditing features. * * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. -- cgit v1.2.3 From c94c257c88c517f251da273a15c654224c7b6e21 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Fri, 29 Apr 2005 16:27:17 +0100 Subject: Add audit uid to netlink credentials Most audit control messages are sent over netlink.In order to properly log the identity of the sender of audit control messages, we would like to add the loginuid to the netlink_creds structure, as per the attached patch. Signed-off-by: Serge Hallyn Signed-off-by: David Woodhouse --- include/linux/audit.h | 2 +- include/linux/netlink.h | 1 + kernel/audit.c | 46 +++++++++++++++++++++++++--------------------- kernel/auditsc.c | 5 ++++- net/netlink/af_netlink.c | 1 + 5 files changed, 32 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/include/linux/audit.h b/include/linux/audit.h index 5fabe8481011..19f214230fec 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -184,7 +184,7 @@ extern void audit_inode(const char *name, const struct inode *inode); /* Private API (for audit.c only) */ extern int audit_receive_filter(int type, int pid, int uid, int seq, - void *data); + void *data, uid_t loginuid); extern void audit_get_stamp(struct audit_context *ctx, struct timespec *t, unsigned int *serial); extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid); diff --git a/include/linux/netlink.h b/include/linux/netlink.h index f731abdc1a29..b2738ac8bc99 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -110,6 +110,7 @@ struct netlink_skb_parms __u32 dst_pid; __u32 dst_groups; kernel_cap_t eff_cap; + __u32 loginuid; /* Login (audit) uid */ }; #define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb)) diff --git a/kernel/audit.c b/kernel/audit.c index 58c7d7e47299..587d3b2eba7f 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -239,36 +239,36 @@ void audit_log_lost(const char *message) } -static int audit_set_rate_limit(int limit) +static int audit_set_rate_limit(int limit, uid_t loginuid) { int old = audit_rate_limit; audit_rate_limit = limit; - audit_log(current->audit_context, "audit_rate_limit=%d old=%d", - audit_rate_limit, old); + audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u", + audit_rate_limit, old, loginuid); return old; } -static int audit_set_backlog_limit(int limit) +static int audit_set_backlog_limit(int limit, uid_t loginuid) { int old = audit_backlog_limit; audit_backlog_limit = limit; - audit_log(current->audit_context, "audit_backlog_limit=%d old=%d", - audit_backlog_limit, old); + audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u", + audit_backlog_limit, old, loginuid); return old; } -static int audit_set_enabled(int state) +static int audit_set_enabled(int state, uid_t loginuid) { int old = audit_enabled; if (state != 0 && state != 1) return -EINVAL; audit_enabled = state; - audit_log(current->audit_context, "audit_enabled=%d old=%d", - audit_enabled, old); + audit_log(NULL, "audit_enabled=%d old=%d by auid %u", + audit_enabled, old, loginuid); return old; } -static int audit_set_failure(int state) +static int audit_set_failure(int state, uid_t loginuid) { int old = audit_failure; if (state != AUDIT_FAIL_SILENT @@ -276,8 +276,8 @@ static int audit_set_failure(int state) && state != AUDIT_FAIL_PANIC) return -EINVAL; audit_failure = state; - audit_log(current->audit_context, "audit_failure=%d old=%d", - audit_failure, old); + audit_log(NULL, "audit_failure=%d old=%d by auid %u", + audit_failure, old, loginuid); return old; } @@ -344,6 +344,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) int err; struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; + uid_t loginuid; /* loginuid of sender */ err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); if (err) @@ -351,6 +352,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) pid = NETLINK_CREDS(skb)->pid; uid = NETLINK_CREDS(skb)->uid; + loginuid = NETLINK_CB(skb).loginuid; seq = nlh->nlmsg_seq; data = NLMSG_DATA(nlh); @@ -371,34 +373,36 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return -EINVAL; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { - err = audit_set_enabled(status_get->enabled); + err = audit_set_enabled(status_get->enabled, loginuid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_FAILURE) { - err = audit_set_failure(status_get->failure); + err = audit_set_failure(status_get->failure, loginuid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_PID) { int old = audit_pid; audit_pid = status_get->pid; - audit_log(current->audit_context, - "audit_pid=%d old=%d", audit_pid, old); + audit_log(NULL, "audit_pid=%d old=%d by auid %u", + audit_pid, old, loginuid); } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) - audit_set_rate_limit(status_get->rate_limit); + audit_set_rate_limit(status_get->rate_limit, loginuid); if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) - audit_set_backlog_limit(status_get->backlog_limit); + audit_set_backlog_limit(status_get->backlog_limit, + loginuid); break; case AUDIT_USER: ab = audit_log_start(NULL); if (!ab) break; /* audit_panic has been called */ audit_log_format(ab, - "user pid=%d uid=%d length=%d msg='%.1024s'", + "user pid=%d uid=%d length=%d loginuid=%u" + " msg='%.1024s'", pid, uid, (int)(nlh->nlmsg_len - ((char *)data - (char *)nlh)), - (char *)data); + loginuid, (char *)data); ab->type = AUDIT_USER; ab->pid = pid; audit_log_end(ab); @@ -411,7 +415,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case AUDIT_LIST: #ifdef CONFIG_AUDITSYSCALL err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, - uid, seq, data); + uid, seq, data, loginuid); #else err = -EOPNOTSUPP; #endif diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 9ff2c1b1033e..66148f81d783 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -251,7 +251,8 @@ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s) return 0; } -int audit_receive_filter(int type, int pid, int uid, int seq, void *data) +int audit_receive_filter(int type, int pid, int uid, int seq, void *data, + uid_t loginuid) { u32 flags; struct audit_entry *entry; @@ -286,6 +287,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data) err = audit_add_rule(entry, &audit_entlist); if (!err && (flags & AUDIT_AT_EXIT)) err = audit_add_rule(entry, &audit_extlist); + audit_log(NULL, "auid %u added an audit rule\n", loginuid); break; case AUDIT_DEL: flags =((struct audit_rule *)data)->flags; @@ -295,6 +297,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data) err = audit_del_rule(data, &audit_entlist); if (!err && (flags & AUDIT_AT_EXIT)) err = audit_del_rule(data, &audit_extlist); + audit_log(NULL, "auid %u removed an audit rule\n", loginuid); break; default: return -EINVAL; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 29a5fd231eac..cb64cff3e339 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -905,6 +905,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, NETLINK_CB(skb).groups = nlk->groups; NETLINK_CB(skb).dst_pid = dst_pid; NETLINK_CB(skb).dst_groups = dst_groups; + NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context); memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); /* What can I do? Netlink is asynchronous, so that -- cgit v1.2.3 From 456be6cd90dbbb9b0ea01d56932d56d110d51cf7 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Fri, 29 Apr 2005 17:30:07 +0100 Subject: [AUDIT] LOGIN message credentials Attached is a new patch that solves the issue of getting valid credentials into the LOGIN message. The current code was assuming that the audit context had already been copied. This is not always the case for LOGIN messages. To solve the problem, the patch passes the task struct to the function that emits the message where it can get valid credentials. Signed-off-by: Steve Grubb Signed-off-by: David Woodhouse --- fs/proc/base.c | 2 +- include/linux/audit.h | 2 +- kernel/auditsc.c | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/fs/proc/base.c b/fs/proc/base.c index 39fd336cfdb9..57554bfbed79 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -820,7 +820,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, goto out_free_page; } - length = audit_set_loginuid(task->audit_context, loginuid); + length = audit_set_loginuid(task, loginuid); if (likely(length == 0)) length = count; diff --git a/include/linux/audit.h b/include/linux/audit.h index 19f214230fec..19f04b049798 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -187,7 +187,7 @@ extern int audit_receive_filter(int type, int pid, int uid, int seq, void *data, uid_t loginuid); extern void audit_get_stamp(struct audit_context *ctx, struct timespec *t, unsigned int *serial); -extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid); +extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); extern uid_t audit_get_loginuid(struct audit_context *ctx); extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); #else diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 66148f81d783..37b3ac94bc47 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1010,20 +1010,21 @@ void audit_get_stamp(struct audit_context *ctx, extern int audit_set_type(struct audit_buffer *ab, int type); -int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid) +int audit_set_loginuid(struct task_struct *task, uid_t loginuid) { - if (ctx) { + if (task->audit_context) { struct audit_buffer *ab; ab = audit_log_start(NULL); if (ab) { audit_log_format(ab, "login pid=%d uid=%u " "old loginuid=%u new loginuid=%u", - ctx->pid, ctx->uid, ctx->loginuid, loginuid); + task->pid, task->uid, + task->audit_context->loginuid, loginuid); audit_set_type(ab, AUDIT_LOGIN); audit_log_end(ab); } - ctx->loginuid = loginuid; + task->audit_context->loginuid = loginuid; } return 0; } -- cgit v1.2.3 From 8443b165f13d21214e5d5495eee7c3bf7f2456bf Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 29 Apr 2005 21:58:15 +0100 Subject: [PATCH] ARM: 2657/1: export ixp2000_pci_config_addr Patch from Lennert Buytenhek Export ixp2000_pci_config_addr, to be used by the IXDP2800 platform setup code to coordinate booting the master and slave NPU. Signed-off-by: Lennert Buytenhek Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp2000/pci.c | 2 +- include/asm-arm/arch-ixp2000/platform.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c index 831f8ffb6b61..36c9a94298cc 100644 --- a/arch/arm/mach-ixp2000/pci.c +++ b/arch/arm/mach-ixp2000/pci.c @@ -37,7 +37,7 @@ static int pci_master_aborts = 0; static int clear_master_aborts(void); -static u32 * +u32 * ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where) { u32 *paddress; diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h index 509e44d528d8..901bba6d02b4 100644 --- a/include/asm-arm/arch-ixp2000/platform.h +++ b/include/asm-arm/arch-ixp2000/platform.h @@ -121,6 +121,7 @@ unsigned long ixp2000_gettimeoffset(void); struct pci_sys_data; +u32 *ixp2000_pci_config_addr(unsigned int bus, unsigned int devfn, int where); void ixp2000_pci_preinit(void); int ixp2000_pci_setup(int, struct pci_sys_data*); struct pci_bus* ixp2000_pci_scan_bus(int, struct pci_sys_data*); -- cgit v1.2.3 From 2d2669b62984b8d76b05a6a045390a3250317d21 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 29 Apr 2005 22:08:33 +0100 Subject: [PATCH] ARM: 2651/3: kernel helpers for NPTL support Patch from Nicolas Pitre This patch entirely reworks the kernel assistance for NPTL on ARM. In particular this provides an efficient way to retrieve the TLS value and perform atomic operations without any instruction emulation nor special system call. This even allows for pre ARMv6 binaries to be forward compatible with SMP systems without any penalty. The problematic and performance critical operations are performed through segment of kernel provided user code reachable from user space at a fixed address in kernel memory. Those fixed entry points are within the vector page so we basically get it for free as no extra memory page is required and nothing else may be mapped at that location anyway. This is different from (but doesn't preclude) a full blown VDSO implementation, however a VDSO would prevent some assembly tricks with constants that allows for efficient branching to those code segments. And since those code segments only use a few cycles before returning to user code, the overhead of a VDSO far call would add a significant overhead to such minimalistic operations. The ARM_NR_set_tls syscall also changed number. This is done for two reasons: 1) this patch changes the way the TLS value was previously meant to be retrieved, therefore we ensure whatever library using the old way gets fixed (they only exist in private tree at the moment since the NPTL work is still progressing). 2) the previous number was allocated in a range causing an undefined instruction trap on kernels not supporting that syscall and it was determined that allocating it in a range returning -ENOSYS would be much nicer for libraries trying to determine if the feature is present or not. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 213 ++++++++++++++++++++++++++++++++++++++++++- arch/arm/kernel/traps.c | 58 ++++++++++-- arch/arm/mm/Kconfig | 14 +++ include/asm-arm/unistd.h | 3 +- 4 files changed, 277 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 2a5c3fe09a95..080df907f242 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -269,6 +269,12 @@ __pabt_svc: add r5, sp, #S_PC ldmia r7, {r2 - r4} @ Get USR pc, cpsr +#if __LINUX_ARM_ARCH__ < 6 + @ make sure our user space atomic helper is aborted + cmp r2, #VIRT_OFFSET + bichs r3, r3, #PSR_Z_BIT +#endif + @ @ We are now ready to fill in the remaining blanks on the stack: @ @@ -499,8 +505,12 @@ ENTRY(__switch_to) mra r4, r5, acc0 stmia ip, {r4, r5} #endif +#ifdef CONFIG_HAS_TLS_REG + mcr p15, 0, r3, c13, c0, 3 @ set TLS register +#else mov r4, #0xffff0fff - str r3, [r4, #-3] @ Set TLS ptr + str r3, [r4, #-15] @ TLS val at 0xffff0ff0 +#endif mcr p15, 0, r6, c3, c0, 0 @ Set domain register #ifdef CONFIG_VFP @ Always disable VFP so we can lazily save/restore the old @@ -519,6 +529,207 @@ ENTRY(__switch_to) ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously __INIT + +/* + * User helpers. + * + * These are segment of kernel provided user code reachable from user space + * at a fixed address in kernel memory. This is used to provide user space + * with some operations which require kernel help because of unimplemented + * native feature and/or instructions in many ARM CPUs. The idea is for + * this code to be executed directly in user mode for best efficiency but + * which is too intimate with the kernel counter part to be left to user + * libraries. In fact this code might even differ from one CPU to another + * depending on the available instruction set and restrictions like on + * SMP systems. In other words, the kernel reserves the right to change + * this code as needed without warning. Only the entry points and their + * results are guaranteed to be stable. + * + * Each segment is 32-byte aligned and will be moved to the top of the high + * vector page. New segments (if ever needed) must be added in front of + * existing ones. This mechanism should be used only for things that are + * really small and justified, and not be abused freely. + * + * User space is expected to implement those things inline when optimizing + * for a processor that has the necessary native support, but only if such + * resulting binaries are already to be incompatible with earlier ARM + * processors due to the use of unsupported instructions other than what + * is provided here. In other words don't make binaries unable to run on + * earlier processors just for the sake of not using these kernel helpers + * if your compiled code is not going to use the new instructions for other + * purpose. + */ + + .align 5 + .globl __kuser_helper_start +__kuser_helper_start: + +/* + * Reference prototype: + * + * int __kernel_cmpxchg(int oldval, int newval, int *ptr) + * + * Input: + * + * r0 = oldval + * r1 = newval + * r2 = ptr + * lr = return address + * + * Output: + * + * r0 = returned value (zero or non-zero) + * C flag = set if r0 == 0, clear if r0 != 0 + * + * Clobbered: + * + * r3, ip, flags + * + * Definition and user space usage example: + * + * typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); + * #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) + * + * Atomically store newval in *ptr if *ptr is equal to oldval for user space. + * Return zero if *ptr was changed or non-zero if no exchange happened. + * The C flag is also set if *ptr was changed to allow for assembly + * optimization in the calling code. + * + * For example, a user space atomic_add implementation could look like this: + * + * #define atomic_add(ptr, val) \ + * ({ register unsigned int *__ptr asm("r2") = (ptr); \ + * register unsigned int __result asm("r1"); \ + * asm volatile ( \ + * "1: @ atomic_add\n\t" \ + * "ldr r0, [r2]\n\t" \ + * "mov r3, #0xffff0fff\n\t" \ + * "add lr, pc, #4\n\t" \ + * "add r1, r0, %2\n\t" \ + * "add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \ + * "bcc 1b" \ + * : "=&r" (__result) \ + * : "r" (__ptr), "rIL" (val) \ + * : "r0","r3","ip","lr","cc","memory" ); \ + * __result; }) + */ + +__kuser_cmpxchg: @ 0xffff0fc0 + +#if __LINUX_ARM_ARCH__ < 6 + +#ifdef CONFIG_SMP /* sanity check */ +#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?" +#endif + + /* + * Theory of operation: + * + * We set the Z flag before loading oldval. If ever an exception + * occurs we can not be sure the loaded value will still be the same + * when the exception returns, therefore the user exception handler + * will clear the Z flag whenever the interrupted user code was + * actually from the kernel address space (see the usr_entry macro). + * + * The post-increment on the str is used to prevent a race with an + * exception happening just after the str instruction which would + * clear the Z flag although the exchange was done. + */ + teq ip, ip @ set Z flag + ldr ip, [r2] @ load current val + add r3, r2, #1 @ prepare store ptr + teqeq ip, r0 @ compare with oldval if still allowed + streq r1, [r3, #-1]! @ store newval if still allowed + subs r0, r2, r3 @ if r2 == r3 the str occured + mov pc, lr + +#else + + ldrex r3, [r2] + subs r3, r3, r0 + strexeq r3, r1, [r2] + rsbs r0, r3, #0 + mov pc, lr + +#endif + + .align 5 + +/* + * Reference prototype: + * + * int __kernel_get_tls(void) + * + * Input: + * + * lr = return address + * + * Output: + * + * r0 = TLS value + * + * Clobbered: + * + * the Z flag might be lost + * + * Definition and user space usage example: + * + * typedef int (__kernel_get_tls_t)(void); + * #define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0) + * + * Get the TLS value as previously set via the __ARM_NR_set_tls syscall. + * + * This could be used as follows: + * + * #define __kernel_get_tls() \ + * ({ register unsigned int __val asm("r0"); \ + * asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \ + * : "=r" (__val) : : "lr","cc" ); \ + * __val; }) + */ + +__kuser_get_tls: @ 0xffff0fe0 + +#ifndef CONFIG_HAS_TLS_REG + +#ifdef CONFIG_SMP /* sanity check */ +#error "CONFIG_SMP without CONFIG_HAS_TLS_REG is wrong" +#endif + + ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0 + mov pc, lr + +#else + + mrc p15, 0, r0, c13, c0, 3 @ read TLS register + mov pc, lr + +#endif + + .rep 5 + .word 0 @ pad up to __kuser_helper_version + .endr + +/* + * Reference declaration: + * + * extern unsigned int __kernel_helper_version; + * + * Definition and user space usage example: + * + * #define __kernel_helper_version (*(unsigned int *)0xffff0ffc) + * + * User space may read this to determine the curent number of helpers + * available. + */ + +__kuser_helper_version: @ 0xffff0ffc + .word ((__kuser_helper_end - __kuser_helper_start) >> 5) + + .globl __kuser_helper_end +__kuser_helper_end: + + /* * Vector stubs. * diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 0078aeb85737..3a001fe5540b 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -450,13 +450,17 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) case NR(set_tls): thread->tp_value = regs->ARM_r0; +#ifdef CONFIG_HAS_TLS_REG + asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) ); +#else /* - * Our user accessible TLS ptr is located at 0xffff0ffc. - * On SMP read access to this address must raise a fault - * and be emulated from the data abort handler. - * m + * User space must never try to access this directly. + * Expect your app to break eventually if you do so. + * The user helper at 0xffff0fe0 must be used instead. + * (see entry-armv.S for details) */ - *((unsigned long *)0xffff0ffc) = thread->tp_value; + *((unsigned int *)0xffff0ff0) = regs->ARM_r0; +#endif return 0; default: @@ -493,6 +497,41 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) return 0; } +#if defined(CONFIG_CPU_32v6) && !defined(CONFIG_HAS_TLS_REG) + +/* + * We might be running on an ARMv6+ processor which should have the TLS + * register, but for some reason we can't use it and have to emulate it. + */ + +static int get_tp_trap(struct pt_regs *regs, unsigned int instr) +{ + int reg = (instr >> 12) & 15; + if (reg == 15) + return 1; + regs->uregs[reg] = current_thread_info()->tp_value; + regs->ARM_pc += 4; + return 0; +} + +static struct undef_hook arm_mrc_hook = { + .instr_mask = 0x0fff0fff, + .instr_val = 0x0e1d0f70, + .cpsr_mask = PSR_T_BIT, + .cpsr_val = 0, + .fn = get_tp_trap, +}; + +static int __init arm_mrc_hook_init(void) +{ + register_undef_hook(&arm_mrc_hook); + return 0; +} + +late_initcall(arm_mrc_hook_init); + +#endif + void __bad_xchg(volatile void *ptr, int size) { printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", @@ -580,14 +619,17 @@ void __init trap_init(void) { extern char __stubs_start[], __stubs_end[]; extern char __vectors_start[], __vectors_end[]; + extern char __kuser_helper_start[], __kuser_helper_end[]; + int kuser_sz = __kuser_helper_end - __kuser_helper_start; /* - * Copy the vectors and stubs (in entry-armv.S) into the - * vector page, mapped at 0xffff0000, and ensure these are - * visible to the instruction stream. + * Copy the vectors, stubs and kuser helpers (in entry-armv.S) + * into the vector page, mapped at 0xffff0000, and ensure these + * are visible to the instruction stream. */ memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start); memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start); + memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz); flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 5b670c9ac5ef..007766a0644c 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -409,3 +409,17 @@ config CPU_BPREDICT_DISABLE depends on CPU_ARM1020 help Say Y here to disable branch prediction. If unsure, say N. + +config HAS_TLS_REG + bool + depends on CPU_32v6 && !CPU_32v5 && !CPU_32v4 && !CPU_32v3 + help + This selects support for the CP15 thread register. + It is defined to be available on ARMv6 or later. However + if the kernel is configured to support multiple CPUs including + a pre-ARMv6 processors, or if a given ARMv6 processor doesn't + implement the thread register for some reason, then access to + this register from user space must be trapped and emulated. + If user space is relying on the __kuser_get_tls code then + there should not be any impact. + diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index a19ec09eaa01..ace27480886e 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h @@ -359,8 +359,7 @@ #define __ARM_NR_cacheflush (__ARM_NR_BASE+2) #define __ARM_NR_usr26 (__ARM_NR_BASE+3) #define __ARM_NR_usr32 (__ARM_NR_BASE+4) - -#define __ARM_NR_set_tls (__ARM_NR_BASE+0x800) +#define __ARM_NR_set_tls (__ARM_NR_BASE+5) #define __sys2(x) #x #define __sys1(x) __sys2(x) -- cgit v1.2.3 From 05f9869bf20e11bcb9b64b9ebd6a9cf89d6b71ba Mon Sep 17 00:00:00 2001 From: Olav Kongas Date: Fri, 29 Apr 2005 22:08:34 +0100 Subject: [PATCH] ARM: 2649/1: Fix 'sparse -Wbitwise' warnings from MMIO macros Patch from Olav Kongas On ARM, the outX() and writeX() families of macros take the result of cpu_to_leYY(), which is of restricted type __leYY, and feed it to __raw_writeX(), which expect an argument of unrestricted type. This results in 'sparse -Wbitwise' warnings about incorrect types in assignments. Analogous type mismatch warnings are issued for inX() and readX() counterparts. The below patch resolves these warnings by adding forced typecasts. Signed-off-by: Olav Kongas Signed-off-by: Russell King --- include/asm-arm/io.h | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index 69bc7a3e8160..658ffa384fda 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -99,12 +99,16 @@ extern void __readwrite_bug(const char *fn); */ #ifdef __io #define outb(v,p) __raw_writeb(v,__io(p)) -#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p)) -#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p)) +#define outw(v,p) __raw_writew((__force __u16) \ + cpu_to_le16(v),__io(p)) +#define outl(v,p) __raw_writel((__force __u32) \ + cpu_to_le32(v),__io(p)) -#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; }) -#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; }) -#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; }) +#define inb(p) ({ __u8 __v = __raw_readb(__io(p)); __v; }) +#define inw(p) ({ __u16 __v = le16_to_cpu((__force __le16) \ + __raw_readw(__io(p))); __v; }) +#define inl(p) ({ __u32 __v = le32_to_cpu((__force __le32) \ + __raw_readl(__io(p))); __v; }) #define outsb(p,d,l) __raw_writesb(__io(p),d,l) #define outsw(p,d,l) __raw_writesw(__io(p),d,l) @@ -149,9 +153,11 @@ extern void _memset_io(void __iomem *, int, size_t); * IO port primitives for more information. */ #ifdef __mem_pci -#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; }) -#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; }) -#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; }) +#define readb(c) ({ __u8 __v = __raw_readb(__mem_pci(c)); __v; }) +#define readw(c) ({ __u16 __v = le16_to_cpu((__force __le16) \ + __raw_readw(__mem_pci(c))); __v; }) +#define readl(c) ({ __u32 __v = le32_to_cpu((__force __le32) \ + __raw_readl(__mem_pci(c))); __v; }) #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) @@ -161,8 +167,10 @@ extern void _memset_io(void __iomem *, int, size_t); #define readsl(p,d,l) __raw_readsl(__mem_pci(p),d,l) #define writeb(v,c) __raw_writeb(v,__mem_pci(c)) -#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c)) -#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c)) +#define writew(v,c) __raw_writew((__force __u16) \ + cpu_to_le16(v),__mem_pci(c)) +#define writel(v,c) __raw_writel((__force __u32) \ + cpu_to_le32(v),__mem_pci(c)) #define writesb(p,d,l) __raw_writesb(__mem_pci(p),d,l) #define writesw(p,d,l) __raw_writesw(__mem_pci(p),d,l) -- cgit v1.2.3 From d5aa207e46ff7ee838683a7d95ecf46fe42a9a56 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 30 Apr 2005 12:19:28 +0100 Subject: [PATCH] ARM: RTC: allow driver methods to return error Allow RTC drivers to return error codes from their read_time or read_alarm methods. Signed-off-by: Russell King --- arch/arm/common/rtctime.c | 29 +++++++++++++++-------------- arch/arm/mach-integrator/time.c | 17 ++++++++++++----- drivers/char/s3c2410-rtc.c | 8 ++++++-- include/asm-arm/rtc.h | 4 ++-- 4 files changed, 35 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c index c397e71f938d..72b03f201eb9 100644 --- a/arch/arm/common/rtctime.c +++ b/arch/arm/common/rtctime.c @@ -141,10 +141,10 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc next->tm_sec = alrm->tm_sec; } -static inline void rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) +static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) { memset(tm, 0, sizeof(struct rtc_time)); - ops->read_time(tm); + return ops->read_time(tm); } static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) @@ -163,8 +163,7 @@ static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) int ret = -EINVAL; if (ops->read_alarm) { memset(alrm, 0, sizeof(struct rtc_wkalrm)); - ops->read_alarm(alrm); - ret = 0; + ret = ops->read_alarm(alrm); } return ret; } @@ -283,7 +282,9 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, break; case RTC_RD_TIME: - rtc_read_time(ops, &tm); + ret = rtc_read_time(ops, &tm); + if (ret) + break; ret = copy_to_user(uarg, &tm, sizeof(tm)); if (ret) ret = -EFAULT; @@ -424,15 +425,15 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo struct rtc_time tm; char *p = page; - rtc_read_time(ops, &tm); - - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n" - "rtc_epoch\t: %04lu\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - rtc_epoch); + if (rtc_read_time(ops, &tm) == 0) { + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04lu\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + rtc_epoch); + } if (rtc_read_alarm(ops, &alrm) == 0) { p += sprintf(p, "alrm_time\t: "); diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c index 20729de2af28..1a844ca139e0 100644 --- a/arch/arm/mach-integrator/time.c +++ b/arch/arm/mach-integrator/time.c @@ -40,25 +40,32 @@ static int integrator_set_rtc(void) return 1; } -static void rtc_read_alarm(struct rtc_wkalrm *alrm) +static int rtc_read_alarm(struct rtc_wkalrm *alrm) { rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time); + return 0; } -static int rtc_set_alarm(struct rtc_wkalrm *alrm) +static inline int rtc_set_alarm(struct rtc_wkalrm *alrm) { unsigned long time; int ret; - ret = rtc_tm_to_time(&alrm->time, &time); + /* + * At the moment, we can only deal with non-wildcarded alarm times. + */ + ret = rtc_valid_tm(&alrm->time); + if (ret == 0) + ret = rtc_tm_to_time(&alrm->time, &time); if (ret == 0) writel(time, rtc_base + RTC_MR); return ret; } -static void rtc_read_time(struct rtc_time *tm) +static int rtc_read_time(struct rtc_time *tm) { rtc_time_to_tm(readl(rtc_base + RTC_DR), tm); + return 0; } /* @@ -69,7 +76,7 @@ static void rtc_read_time(struct rtc_time *tm) * edge of the 1Hz clock, we must write the time one second * in advance. */ -static int rtc_set_time(struct rtc_time *tm) +static inline int rtc_set_time(struct rtc_time *tm) { unsigned long time; int ret; diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c index 8e61be34a1d3..ed867db550a9 100644 --- a/drivers/char/s3c2410-rtc.c +++ b/drivers/char/s3c2410-rtc.c @@ -116,7 +116,7 @@ static void s3c2410_rtc_setfreq(int freq) /* Time read/write */ -static void s3c2410_rtc_gettime(struct rtc_time *rtc_tm) +static int s3c2410_rtc_gettime(struct rtc_time *rtc_tm) { unsigned int have_retried = 0; @@ -151,6 +151,8 @@ static void s3c2410_rtc_gettime(struct rtc_time *rtc_tm) rtc_tm->tm_year += 100; rtc_tm->tm_mon -= 1; + + return 0; } @@ -171,7 +173,7 @@ static int s3c2410_rtc_settime(struct rtc_time *tm) return 0; } -static void s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm) +static int s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm) { struct rtc_time *alm_tm = &alrm->time; unsigned int alm_en; @@ -231,6 +233,8 @@ static void s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm) } /* todo - set alrm->enabled ? */ + + return 0; } static int s3c2410_rtc_setalarm(struct rtc_wkalrm *alrm) diff --git a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h index aa7e16b2e225..370dfe77589d 100644 --- a/include/asm-arm/rtc.h +++ b/include/asm-arm/rtc.h @@ -18,9 +18,9 @@ struct rtc_ops { void (*release)(void); int (*ioctl)(unsigned int, unsigned long); - void (*read_time)(struct rtc_time *); + int (*read_time)(struct rtc_time *); int (*set_time)(struct rtc_time *); - void (*read_alarm)(struct rtc_wkalrm *); + int (*read_alarm)(struct rtc_wkalrm *); int (*set_alarm)(struct rtc_wkalrm *); int (*proc)(char *buf); }; -- cgit v1.2.3 From 4774e2260cf25c54f2188dd0407676e3af6f1f23 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 30 Apr 2005 23:32:38 +0100 Subject: [PATCH] ARM: IntegratorCP: Fix CLCD MUX selection values The documentation on these values seems to be rather wrong. These values have been determined by mere trial and error. Signed-off-by: Russell King --- arch/arm/mach-integrator/integrator_cp.c | 17 ++++++++++++++++- include/asm-arm/arch-integrator/cm.h | 6 +++--- 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 68e15c36e336..3b948e8c2751 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -420,7 +420,22 @@ static struct clcd_panel vga = { */ static void cp_clcd_enable(struct clcd_fb *fb) { - cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA); + u32 val; + + if (fb->fb.var.bits_per_pixel <= 8) + val = CM_CTRL_LCDMUXSEL_VGA_8421BPP; + else if (fb->fb.var.bits_per_pixel <= 16) + val = CM_CTRL_LCDMUXSEL_VGA_16BPP; + else + val = 0; /* no idea for this, don't trust the docs */ + + cm_control(CM_CTRL_LCDMUXSEL_MASK| + CM_CTRL_LCDEN0| + CM_CTRL_LCDEN1| + CM_CTRL_STATIC1| + CM_CTRL_STATIC2| + CM_CTRL_STATIC| + CM_CTRL_n24BITEN, val); } static unsigned long framesize = SZ_1M; diff --git a/include/asm-arm/arch-integrator/cm.h b/include/asm-arm/arch-integrator/cm.h index d31c1a71f781..1ab353e23595 100644 --- a/include/asm-arm/arch-integrator/cm.h +++ b/include/asm-arm/arch-integrator/cm.h @@ -24,9 +24,9 @@ void cm_control(u32, u32); #define CM_CTRL_LCDBIASDN (1 << 10) #define CM_CTRL_LCDMUXSEL_MASK (7 << 11) #define CM_CTRL_LCDMUXSEL_GENLCD (1 << 11) -#define CM_CTRL_LCDMUXSEL_SHARPLCD1 (3 << 11) -#define CM_CTRL_LCDMUXSEL_SHARPLCD2 (4 << 11) -#define CM_CTRL_LCDMUXSEL_VGA (7 << 11) +#define CM_CTRL_LCDMUXSEL_VGA_16BPP (2 << 11) +#define CM_CTRL_LCDMUXSEL_SHARPLCD (3 << 11) +#define CM_CTRL_LCDMUXSEL_VGA_8421BPP (4 << 11) #define CM_CTRL_LCDEN0 (1 << 14) #define CM_CTRL_LCDEN1 (1 << 15) #define CM_CTRL_STATIC1 (1 << 16) -- cgit v1.2.3 From 119f657c72fc07d6fd28c61de59cfba1566970a9 Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Sun, 1 May 2005 08:58:35 -0700 Subject: [PATCH] RLIMIT_AS checking fix Address bug #4508: there's potential for wraparound in the various places where we perform RLIMIT_AS checking. (I'm a bit worried about acct_stack_growth(). Are we sure that vma->vm_mm is always equal to current->mm? If not, then we're comparing some other process's total_vm with the calling process's rlimits). Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 + mm/mmap.c | 24 +++++++++++++++++++----- mm/mremap.c | 6 +++--- 3 files changed, 23 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index c74a74ca401d..8b007ad2d450 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -726,6 +726,7 @@ extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *, extern struct vm_area_struct *copy_vma(struct vm_area_struct **, unsigned long addr, unsigned long len, pgoff_t pgoff); extern void exit_mmap(struct mm_struct *); +extern int may_expand_vm(struct mm_struct *mm, unsigned long npages); extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/mm/mmap.c b/mm/mmap.c index 6ea204cc751e..1ec0f6e9c0d8 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1009,8 +1009,7 @@ munmap_back: } /* Check against address space limit. */ - if ((mm->total_vm << PAGE_SHIFT) + len - > current->signal->rlim[RLIMIT_AS].rlim_cur) + if (!may_expand_vm(mm, len >> PAGE_SHIFT)) return -ENOMEM; if (accountable && (!(flags & MAP_NORESERVE) || @@ -1421,7 +1420,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un struct rlimit *rlim = current->signal->rlim; /* address space limit tests */ - if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT) + if (!may_expand_vm(mm, grow)) return -ENOMEM; /* Stack limit test */ @@ -1848,8 +1847,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) } /* Check against address space limits *after* clearing old maps... */ - if ((mm->total_vm << PAGE_SHIFT) + len - > current->signal->rlim[RLIMIT_AS].rlim_cur) + if (!may_expand_vm(mm, len >> PAGE_SHIFT)) return -ENOMEM; if (mm->map_count > sysctl_max_map_count) @@ -2019,3 +2017,19 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, } return new_vma; } + +/* + * Return true if the calling process may expand its vm space by the passed + * number of pages + */ +int may_expand_vm(struct mm_struct *mm, unsigned long npages) +{ + unsigned long cur = mm->total_vm; /* pages */ + unsigned long lim; + + lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; + + if (cur + npages > lim) + return 0; + return 1; +} diff --git a/mm/mremap.c b/mm/mremap.c index 0d1c1b9c7a0a..0dd7ace94e51 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -347,10 +347,10 @@ unsigned long do_mremap(unsigned long addr, if (locked > lock_limit && !capable(CAP_IPC_LOCK)) goto out; } - ret = -ENOMEM; - if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len) - > current->signal->rlim[RLIMIT_AS].rlim_cur) + if (!may_expand_vm(current->mm, (new_len - old_len) >> PAGE_SHIFT)) { + ret = -ENOMEM; goto out; + } if (vma->vm_flags & VM_ACCOUNT) { charged = (new_len - old_len) >> PAGE_SHIFT; -- cgit v1.2.3 From b84a35be0285229b0a8a5e2e04d79360c5b75562 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Sun, 1 May 2005 08:58:36 -0700 Subject: [PATCH] mempool: NOMEMALLOC and NORETRY Mempools have 2 problems. The first is that mempool_alloc can possibly get stuck in __alloc_pages when they should opt to fail, and take an element from their reserved pool. The second is that it will happily eat emergency PF_MEMALLOC reserves instead of going to their reserved pools. Fix the first by passing __GFP_NORETRY in the allocation calls in mempool_alloc. Fix the second by introducing a __GFP_MEMPOOL flag which directs the page allocator not to allocate from the reserve pool. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/gfp.h | 6 ++++-- mm/mempool.c | 9 +++++++-- mm/page_alloc.c | 20 ++++++++++++-------- 3 files changed, 23 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 848a1baac079..af7407e8cfc5 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -38,14 +38,16 @@ struct vm_area_struct; #define __GFP_NO_GROW 0x2000u /* Slab internal usage */ #define __GFP_COMP 0x4000u /* Add compound page metadata */ #define __GFP_ZERO 0x8000u /* Return zeroed page on success */ +#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */ -#define __GFP_BITS_SHIFT 16 /* Room for 16 __GFP_FOO bits */ +#define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1) /* if you forget to add the bitmask here kernel will crash, period */ #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \ __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \ - __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP) + __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ + __GFP_NOMEMALLOC) #define GFP_ATOMIC (__GFP_HIGH) #define GFP_NOIO (__GFP_WAIT) diff --git a/mm/mempool.c b/mm/mempool.c index b014ffeaa413..d691b5cb8022 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -198,11 +198,16 @@ void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask) void *element; unsigned long flags; DEFINE_WAIT(wait); - int gfp_nowait = gfp_mask & ~(__GFP_WAIT | __GFP_IO); + int gfp_nowait; + + gfp_mask |= __GFP_NOMEMALLOC; /* don't allocate emergency reserves */ + gfp_mask |= __GFP_NORETRY; /* don't loop in __alloc_pages */ + gfp_mask |= __GFP_NOWARN; /* failures are OK */ + gfp_nowait = gfp_mask & ~(__GFP_WAIT | __GFP_IO); might_sleep_if(gfp_mask & __GFP_WAIT); repeat_alloc: - element = pool->alloc(gfp_nowait|__GFP_NOWARN, pool->pool_data); + element = pool->alloc(gfp_nowait, pool->pool_data); if (likely(element != NULL)) return element; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 08e8627361a0..04a35b3d3262 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -799,14 +799,18 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order, } /* This allocation should allow future memory freeing. */ - if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) && !in_interrupt()) { - /* go through the zonelist yet again, ignoring mins */ - for (i = 0; (z = zones[i]) != NULL; i++) { - if (!cpuset_zone_allowed(z)) - continue; - page = buffered_rmqueue(z, order, gfp_mask); - if (page) - goto got_pg; + + if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) + && !in_interrupt()) { + if (!(gfp_mask & __GFP_NOMEMALLOC)) { + /* go through the zonelist yet again, ignoring mins */ + for (i = 0; (z = zones[i]) != NULL; i++) { + if (!cpuset_zone_allowed(z)) + continue; + page = buffered_rmqueue(z, order, gfp_mask); + if (page) + goto got_pg; + } } goto nopage; } -- cgit v1.2.3 From edfbe2b0038723e5699ab22695ccd62b5542a5c1 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Sun, 1 May 2005 08:58:37 -0700 Subject: [PATCH] count bounce buffer pages in vmstat This is a patch for counting the number of pages for bounce buffers. It's shown in /proc/vmstat. Currently, the number of bounce pages are not counted anywhere. So, if there are many bounce pages, it seems that there are leaked pages. And it's difficult for a user to imagine the usage of bounce pages. So, it's meaningful to show # of bouce pages. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 1 + mm/highmem.c | 2 ++ mm/page_alloc.c | 1 + 3 files changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 6b74fcf5bb63..39ab8c6b5652 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -131,6 +131,7 @@ struct page_state { unsigned long allocstall; /* direct reclaim calls */ unsigned long pgrotated; /* pages rotated to tail of the LRU */ + unsigned long nr_bounce; /* pages for bounce buffers */ }; extern void get_page_state(struct page_state *ret); diff --git a/mm/highmem.c b/mm/highmem.c index d01276506b00..400911599468 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -325,6 +325,7 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) continue; mempool_free(bvec->bv_page, pool); + dec_page_state(nr_bounce); } bio_endio(bio_orig, bio_orig->bi_size, err); @@ -405,6 +406,7 @@ static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, to->bv_page = mempool_alloc(pool, q->bounce_gfp); to->bv_len = from->bv_len; to->bv_offset = from->bv_offset; + inc_page_state(nr_bounce); if (rw == WRITE) { char *vto, *vfrom; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 04a35b3d3262..80ce7f2104df 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1897,6 +1897,7 @@ static char *vmstat_text[] = { "allocstall", "pgrotated", + "nr_bounce", }; static void *vmstat_start(struct seq_file *m, loff_t *pos) -- cgit v1.2.3 From 97e2bde47f886a317909c8a8f9bd2fcd8ce2f0b0 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Sun, 1 May 2005 08:58:38 -0700 Subject: [PATCH] add kmalloc_node, inline cleanup The patch makes the following function calls available to allocate memory on a specific node without changing the basic operation of the slab allocator: kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int flags, int node); kmalloc_node(size_t size, unsigned int flags, int node); in a similar way to the existing node-blind functions: kmem_cache_alloc(kmem_cache_t *cachep, unsigned int flags); kmalloc(size, flags); kmem_cache_alloc_node was changed to pass flags and the node information through the existing layers of the slab allocator (which lead to some minor rearrangements). The functions at the lowest layer (kmem_getpages, cache_grow) are already node aware. Also __alloc_percpu can call kmalloc_node now. Performance measurements (using the pageset localization patch) yields: w/o patches: Tasks jobs/min jti jobs/min/task real cpu 1 484.27 100 484.2736 12.02 1.97 Wed Mar 30 20:50:43 2005 100 25170.83 91 251.7083 23.12 150.10 Wed Mar 30 20:51:06 2005 200 34601.66 84 173.0083 33.64 294.14 Wed Mar 30 20:51:40 2005 300 37154.47 86 123.8482 46.99 436.56 Wed Mar 30 20:52:28 2005 400 39839.82 80 99.5995 58.43 580.46 Wed Mar 30 20:53:27 2005 500 40036.32 79 80.0726 72.68 728.60 Wed Mar 30 20:54:40 2005 600 44074.21 79 73.4570 79.23 872.10 Wed Mar 30 20:55:59 2005 700 44016.60 78 62.8809 92.56 1015.84 Wed Mar 30 20:57:32 2005 800 40411.05 80 50.5138 115.22 1161.13 Wed Mar 30 20:59:28 2005 900 42298.56 79 46.9984 123.83 1303.42 Wed Mar 30 21:01:33 2005 1000 40955.05 80 40.9551 142.11 1441.92 Wed Mar 30 21:03:55 2005 with pageset localization and slab API patches: Tasks jobs/min jti jobs/min/task real cpu 1 484.19 100 484.1930 12.02 1.98 Wed Mar 30 21:10:18 2005 100 27428.25 92 274.2825 21.22 149.79 Wed Mar 30 21:10:40 2005 200 37228.94 86 186.1447 31.27 293.49 Wed Mar 30 21:11:12 2005 300 41725.42 85 139.0847 41.84 434.10 Wed Mar 30 21:11:54 2005 400 43032.22 82 107.5805 54.10 582.06 Wed Mar 30 21:12:48 2005 500 42211.23 83 84.4225 68.94 722.61 Wed Mar 30 21:13:58 2005 600 40084.49 82 66.8075 87.12 873.11 Wed Mar 30 21:15:25 2005 700 44169.30 79 63.0990 92.24 1008.77 Wed Mar 30 21:16:58 2005 800 43097.94 79 53.8724 108.03 1155.88 Wed Mar 30 21:18:47 2005 900 41846.75 79 46.4964 125.17 1303.38 Wed Mar 30 21:20:52 2005 1000 40247.85 79 40.2478 144.60 1442.21 Wed Mar 30 21:23:17 2005 Signed-off-by: Christoph Lameter Signed-off-by: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/slab.h | 23 +++++++++++++++-------- mm/slab.c | 45 +++++++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/include/linux/slab.h b/include/linux/slab.h index 3e3c3ab8ff94..7d66385ae750 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -62,16 +62,9 @@ extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned lo extern int kmem_cache_destroy(kmem_cache_t *); extern int kmem_cache_shrink(kmem_cache_t *); extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast); -#ifdef CONFIG_NUMA -extern void *kmem_cache_alloc_node(kmem_cache_t *, int); -#else -static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int node) -{ - return kmem_cache_alloc(cachep, GFP_KERNEL); -} -#endif extern void kmem_cache_free(kmem_cache_t *, void *); extern unsigned int kmem_cache_size(kmem_cache_t *); +extern kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags); /* Size description struct for general caches. */ struct cache_sizes { @@ -109,6 +102,20 @@ extern void *kcalloc(size_t, size_t, unsigned int __nocast); extern void kfree(const void *); extern unsigned int ksize(const void *); +#ifdef CONFIG_NUMA +extern void *kmem_cache_alloc_node(kmem_cache_t *, int flags, int node); +extern void *kmalloc_node(size_t size, int flags, int node); +#else +static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node) +{ + return kmem_cache_alloc(cachep, flags); +} +static inline void *kmalloc_node(size_t size, int flags, int node) +{ + return kmalloc(size, flags); +} +#endif + extern int FASTCALL(kmem_cache_reap(int)); extern int FASTCALL(kmem_ptr_validate(kmem_cache_t *cachep, void *ptr)); diff --git a/mm/slab.c b/mm/slab.c index ec660d85ddd7..771cc09f9f1a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -583,7 +583,7 @@ static inline struct array_cache *ac_data(kmem_cache_t *cachep) return cachep->array[smp_processor_id()]; } -static inline kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags) +static inline kmem_cache_t *__find_general_cachep(size_t size, int gfpflags) { struct cache_sizes *csizep = malloc_sizes; @@ -607,6 +607,12 @@ static inline kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags) return csizep->cs_cachep; } +kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags) +{ + return __find_general_cachep(size, gfpflags); +} +EXPORT_SYMBOL(kmem_find_general_cachep); + /* Cal the num objs, wastage, and bytes left over for a given slab size. */ static void cache_estimate(unsigned long gfporder, size_t size, size_t align, int flags, size_t *left_over, unsigned int *num) @@ -672,14 +678,11 @@ static struct array_cache *alloc_arraycache(int cpu, int entries, int memsize = sizeof(void*)*entries+sizeof(struct array_cache); struct array_cache *nc = NULL; - if (cpu != -1) { - kmem_cache_t *cachep; - cachep = kmem_find_general_cachep(memsize, GFP_KERNEL); - if (cachep) - nc = kmem_cache_alloc_node(cachep, cpu_to_node(cpu)); - } - if (!nc) + if (cpu == -1) nc = kmalloc(memsize, GFP_KERNEL); + else + nc = kmalloc_node(memsize, GFP_KERNEL, cpu_to_node(cpu)); + if (nc) { nc->avail = 0; nc->limit = entries; @@ -2361,7 +2364,7 @@ out: * and can sleep. And it will allocate memory on the given node, which * can improve the performance for cpu bound structures. */ -void *kmem_cache_alloc_node(kmem_cache_t *cachep, int nodeid) +void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid) { int loop; void *objp; @@ -2393,7 +2396,7 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, int nodeid) spin_unlock_irq(&cachep->spinlock); local_irq_disable(); - if (!cache_grow(cachep, GFP_KERNEL, nodeid)) { + if (!cache_grow(cachep, flags, nodeid)) { local_irq_enable(); return NULL; } @@ -2435,6 +2438,16 @@ got_slabp: } EXPORT_SYMBOL(kmem_cache_alloc_node); +void *kmalloc_node(size_t size, int flags, int node) +{ + kmem_cache_t *cachep; + + cachep = kmem_find_general_cachep(size, flags); + if (unlikely(cachep == NULL)) + return NULL; + return kmem_cache_alloc_node(cachep, flags, node); +} +EXPORT_SYMBOL(kmalloc_node); #endif /** @@ -2462,7 +2475,12 @@ void *__kmalloc(size_t size, unsigned int __nocast flags) { kmem_cache_t *cachep; - cachep = kmem_find_general_cachep(size, flags); + /* If you want to save a few bytes .text space: replace + * __ with kmem_. + * Then kmalloc uses the uninlined functions instead of the inline + * functions. + */ + cachep = __find_general_cachep(size, flags); if (unlikely(cachep == NULL)) return NULL; return __cache_alloc(cachep, flags); @@ -2489,9 +2507,8 @@ void *__alloc_percpu(size_t size, size_t align) for (i = 0; i < NR_CPUS; i++) { if (!cpu_possible(i)) continue; - pdata->ptrs[i] = kmem_cache_alloc_node( - kmem_find_general_cachep(size, GFP_KERNEL), - cpu_to_node(i)); + pdata->ptrs[i] = kmalloc_node(size, GFP_KERNEL, + cpu_to_node(i)); if (!pdata->ptrs[i]) goto unwind_oom; -- cgit v1.2.3 From 443a848cd30eb5bb5c1038e6371d83404775dcfc Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 1 May 2005 08:58:40 -0700 Subject: [PATCH] ppc32: refactor FPU exception handling Moved common FPU exception handling code out of head.S so it can be used by several of the sub-architectures that might of a full PowerPC FPU. Also, uses new CONFIG_PPC_FPU define to fix alignment exception handling for floating point load/store instructions to only occur if we have a hardware FPU. Signed-off-by: Jason McMullan Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/Kconfig | 4 + arch/ppc/Makefile | 1 + arch/ppc/kernel/Makefile | 1 + arch/ppc/kernel/align.c | 8 ++ arch/ppc/kernel/entry.S | 59 ++++++++++++++ arch/ppc/kernel/fpu.S | 133 ++++++++++++++++++++++++++++++++ arch/ppc/kernel/head.S | 163 --------------------------------------- arch/ppc/kernel/head_44x.S | 6 ++ arch/ppc/kernel/head_booke.h | 7 ++ arch/ppc/kernel/head_fsl_booke.S | 8 +- arch/ppc/kernel/misc.S | 12 +-- arch/ppc/kernel/traps.c | 2 +- include/asm-ppc/reg_booke.h | 1 + 13 files changed, 229 insertions(+), 176 deletions(-) create mode 100644 arch/ppc/kernel/fpu.S (limited to 'include') diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 74aa1e92a395..c3d941345e3d 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -53,6 +53,7 @@ choice config 6xx bool "6xx/7xx/74xx/52xx/82xx/83xx" + select PPC_FPU help There are four types of PowerPC chips supported. The more common types (601, 603, 604, 740, 750, 7400), the Motorola embedded @@ -86,6 +87,9 @@ config E500 endchoice +config PPC_FPU + bool + config BOOKE bool depends on E500 diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 73cbdda5b597..0432a25b4735 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -53,6 +53,7 @@ head-$(CONFIG_FSL_BOOKE) := arch/ppc/kernel/head_fsl_booke.o head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o +head-$(CONFIG_PPC_FPU) += arch/ppc/kernel/fpu.o core-y += arch/ppc/kernel/ arch/ppc/platforms/ \ arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/ diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 86bc878cb3ee..b284451802c9 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -9,6 +9,7 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o extra-$(CONFIG_8xx) := head_8xx.o extra-$(CONFIG_6xx) += idle_6xx.o extra-$(CONFIG_POWER4) += idle_power4.o +extra-$(CONFIG_PPC_FPU) += fpu.o extra-y += vmlinux.lds obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c index 79c929475037..40d356c66c41 100644 --- a/arch/ppc/kernel/align.c +++ b/arch/ppc/kernel/align.c @@ -368,16 +368,24 @@ fix_alignment(struct pt_regs *regs) /* Single-precision FP load and store require conversions... */ case LD+F+S: +#ifdef CONFIG_PPC_FPU preempt_disable(); enable_kernel_fp(); cvt_fd(&data.f, &data.d, ¤t->thread.fpscr); preempt_enable(); +#else + return 0; +#endif break; case ST+F+S: +#ifdef CONFIG_PPC_FPU preempt_disable(); enable_kernel_fp(); cvt_df(&data.d, &data.f, ¤t->thread.fpscr); preempt_enable(); +#else + return 0; +#endif break; } diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 035217d6c0f1..5f075dbc4ee7 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -563,6 +563,65 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) addi r1,r1,INT_FRAME_SIZE blr + .globl fast_exception_return +fast_exception_return: +#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) + andi. r10,r9,MSR_RI /* check for recoverable interrupt */ + beq 1f /* if not, we've got problems */ +#endif + +2: REST_4GPRS(3, r11) + lwz r10,_CCR(r11) + REST_GPR(1, r11) + mtcr r10 + lwz r10,_LINK(r11) + mtlr r10 + REST_GPR(10, r11) + mtspr SPRN_SRR1,r9 + mtspr SPRN_SRR0,r12 + REST_GPR(9, r11) + REST_GPR(12, r11) + lwz r11,GPR11(r11) + SYNC + RFI + +#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) +/* check if the exception happened in a restartable section */ +1: lis r3,exc_exit_restart_end@ha + addi r3,r3,exc_exit_restart_end@l + cmplw r12,r3 + bge 3f + lis r4,exc_exit_restart@ha + addi r4,r4,exc_exit_restart@l + cmplw r12,r4 + blt 3f + lis r3,fee_restarts@ha + tophys(r3,r3) + lwz r5,fee_restarts@l(r3) + addi r5,r5,1 + stw r5,fee_restarts@l(r3) + mr r12,r4 /* restart at exc_exit_restart */ + b 2b + + .comm fee_restarts,4 + +/* aargh, a nonrecoverable interrupt, panic */ +/* aargh, we don't know which trap this is */ +/* but the 601 doesn't implement the RI bit, so assume it's OK */ +3: +BEGIN_FTR_SECTION + b 2b +END_FTR_SECTION_IFSET(CPU_FTR_601) + li r10,-1 + stw r10,TRAP(r11) + addi r3,r1,STACK_FRAME_OVERHEAD + lis r10,MSR_KERNEL@h + ori r10,r10,MSR_KERNEL@l + bl transfer_to_handler_full + .long nonrecoverable_exception + .long ret_from_except +#endif + .globl sigreturn_exit sigreturn_exit: subi r1,r3,STACK_FRAME_OVERHEAD diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S new file mode 100644 index 000000000000..6189b26f640f --- /dev/null +++ b/arch/ppc/kernel/fpu.S @@ -0,0 +1,133 @@ +/* + * FPU support code, moved here from head.S so that it can be used + * by chips which use other head-whatever.S files. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This task wants to use the FPU now. + * On UP, disable FP for the task which had the FPU previously, + * and save its floating-point registers in its thread_struct. + * Load up this task's FP registers from its thread_struct, + * enable the FPU for the current task and return to the task. + */ + .globl load_up_fpu +load_up_fpu: + mfmsr r5 + ori r5,r5,MSR_FP +#ifdef CONFIG_PPC64BRIDGE + clrldi r5,r5,1 /* turn off 64-bit mode */ +#endif /* CONFIG_PPC64BRIDGE */ + SYNC + MTMSRD(r5) /* enable use of fpu now */ + isync +/* + * For SMP, we don't do lazy FPU switching because it just gets too + * horrendously complex, especially when a task switches from one CPU + * to another. Instead we call giveup_fpu in switch_to. + */ +#ifndef CONFIG_SMP + tophys(r6,0) /* get __pa constant */ + addis r3,r6,last_task_used_math@ha + lwz r4,last_task_used_math@l(r3) + cmpwi 0,r4,0 + beq 1f + add r4,r4,r6 + addi r4,r4,THREAD /* want last_task_used_math->thread */ + SAVE_32FPRS(0, r4) + mffs fr0 + stfd fr0,THREAD_FPSCR-4(r4) + lwz r5,PT_REGS(r4) + add r5,r5,r6 + lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) + li r10,MSR_FP|MSR_FE0|MSR_FE1 + andc r4,r4,r10 /* disable FP for previous task */ + stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#endif /* CONFIG_SMP */ + /* enable use of FP after return */ + mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ + lwz r4,THREAD_FPEXC_MODE(r5) + ori r9,r9,MSR_FP /* enable FP for current */ + or r9,r9,r4 + lfd fr0,THREAD_FPSCR-4(r5) + mtfsf 0xff,fr0 + REST_32FPRS(0, r5) +#ifndef CONFIG_SMP + subi r4,r5,THREAD + sub r4,r4,r6 + stw r4,last_task_used_math@l(r3) +#endif /* CONFIG_SMP */ + /* restore registers and return */ + /* we haven't used ctr or xer or lr */ + b fast_exception_return + +/* + * FP unavailable trap from kernel - print a message, but let + * the task use FP in the kernel until it returns to user mode. + */ + .globl KernelFP +KernelFP: + lwz r3,_MSR(r1) + ori r3,r3,MSR_FP + stw r3,_MSR(r1) /* enable use of FP after return */ + lis r3,86f@h + ori r3,r3,86f@l + mr r4,r2 /* current */ + lwz r5,_NIP(r1) + bl printk + b ret_from_except +86: .string "floating point used in kernel (task=%p, pc=%x)\n" + .align 4,0 + +/* + * giveup_fpu(tsk) + * Disable FP for the task given as the argument, + * and save the floating-point registers in its thread_struct. + * Enables the FPU for use in the kernel on return. + */ + .globl giveup_fpu +giveup_fpu: + mfmsr r5 + ori r5,r5,MSR_FP + SYNC_601 + ISYNC_601 + MTMSRD(r5) /* enable use of fpu now */ + SYNC_601 + isync + cmpwi 0,r3,0 + beqlr- /* if no previous owner, done */ + addi r3,r3,THREAD /* want THREAD of task */ + lwz r5,PT_REGS(r3) + cmpwi 0,r5,0 + SAVE_32FPRS(0, r3) + mffs fr0 + stfd fr0,THREAD_FPSCR-4(r3) + beq 1f + lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) + li r3,MSR_FP|MSR_FE0|MSR_FE1 + andc r4,r4,r3 /* disable FP for previous task */ + stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#ifndef CONFIG_SMP + li r5,0 + lis r4,last_task_used_math@ha + stw r5,last_task_used_math@l(r4) +#endif /* CONFIG_SMP */ + blr diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 1a89a71e0acc..a931d773715f 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -775,133 +775,6 @@ InstructionSegment: EXC_XFER_STD(0x480, UnknownException) #endif /* CONFIG_PPC64BRIDGE */ -/* - * This task wants to use the FPU now. - * On UP, disable FP for the task which had the FPU previously, - * and save its floating-point registers in its thread_struct. - * Load up this task's FP registers from its thread_struct, - * enable the FPU for the current task and return to the task. - */ -load_up_fpu: - mfmsr r5 - ori r5,r5,MSR_FP -#ifdef CONFIG_PPC64BRIDGE - clrldi r5,r5,1 /* turn off 64-bit mode */ -#endif /* CONFIG_PPC64BRIDGE */ - SYNC - MTMSRD(r5) /* enable use of fpu now */ - isync -/* - * For SMP, we don't do lazy FPU switching because it just gets too - * horrendously complex, especially when a task switches from one CPU - * to another. Instead we call giveup_fpu in switch_to. - */ -#ifndef CONFIG_SMP - tophys(r6,0) /* get __pa constant */ - addis r3,r6,last_task_used_math@ha - lwz r4,last_task_used_math@l(r3) - cmpwi 0,r4,0 - beq 1f - add r4,r4,r6 - addi r4,r4,THREAD /* want last_task_used_math->thread */ - SAVE_32FPRS(0, r4) - mffs fr0 - stfd fr0,THREAD_FPSCR-4(r4) - lwz r5,PT_REGS(r4) - add r5,r5,r6 - lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) - li r10,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r10 /* disable FP for previous task */ - stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) -1: -#endif /* CONFIG_SMP */ - /* enable use of FP after return */ - mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ - lwz r4,THREAD_FPEXC_MODE(r5) - ori r9,r9,MSR_FP /* enable FP for current */ - or r9,r9,r4 - lfd fr0,THREAD_FPSCR-4(r5) - mtfsf 0xff,fr0 - REST_32FPRS(0, r5) -#ifndef CONFIG_SMP - subi r4,r5,THREAD - sub r4,r4,r6 - stw r4,last_task_used_math@l(r3) -#endif /* CONFIG_SMP */ - /* restore registers and return */ - /* we haven't used ctr or xer or lr */ - /* fall through to fast_exception_return */ - - .globl fast_exception_return -fast_exception_return: - andi. r10,r9,MSR_RI /* check for recoverable interrupt */ - beq 1f /* if not, we've got problems */ -2: REST_4GPRS(3, r11) - lwz r10,_CCR(r11) - REST_GPR(1, r11) - mtcr r10 - lwz r10,_LINK(r11) - mtlr r10 - REST_GPR(10, r11) - mtspr SPRN_SRR1,r9 - mtspr SPRN_SRR0,r12 - REST_GPR(9, r11) - REST_GPR(12, r11) - lwz r11,GPR11(r11) - SYNC - RFI - -/* check if the exception happened in a restartable section */ -1: lis r3,exc_exit_restart_end@ha - addi r3,r3,exc_exit_restart_end@l - cmplw r12,r3 - bge 3f - lis r4,exc_exit_restart@ha - addi r4,r4,exc_exit_restart@l - cmplw r12,r4 - blt 3f - lis r3,fee_restarts@ha - tophys(r3,r3) - lwz r5,fee_restarts@l(r3) - addi r5,r5,1 - stw r5,fee_restarts@l(r3) - mr r12,r4 /* restart at exc_exit_restart */ - b 2b - - .comm fee_restarts,4 - -/* aargh, a nonrecoverable interrupt, panic */ -/* aargh, we don't know which trap this is */ -/* but the 601 doesn't implement the RI bit, so assume it's OK */ -3: -BEGIN_FTR_SECTION - b 2b -END_FTR_SECTION_IFSET(CPU_FTR_601) - li r10,-1 - stw r10,TRAP(r11) - addi r3,r1,STACK_FRAME_OVERHEAD - li r10,MSR_KERNEL - bl transfer_to_handler_full - .long nonrecoverable_exception - .long ret_from_except - -/* - * FP unavailable trap from kernel - print a message, but let - * the task use FP in the kernel until it returns to user mode. - */ -KernelFP: - lwz r3,_MSR(r1) - ori r3,r3,MSR_FP - stw r3,_MSR(r1) /* enable use of FP after return */ - lis r3,86f@h - ori r3,r3,86f@l - mr r4,r2 /* current */ - lwz r5,_NIP(r1) - bl printk - b ret_from_except -86: .string "floating point used in kernel (task=%p, pc=%x)\n" - .align 4,0 - #ifdef CONFIG_ALTIVEC /* Note that the AltiVec support is closely modeled after the FP * support. Changes to one are likely to be applicable to the @@ -1015,42 +888,6 @@ giveup_altivec: blr #endif /* CONFIG_ALTIVEC */ -/* - * giveup_fpu(tsk) - * Disable FP for the task given as the argument, - * and save the floating-point registers in its thread_struct. - * Enables the FPU for use in the kernel on return. - */ - .globl giveup_fpu -giveup_fpu: - mfmsr r5 - ori r5,r5,MSR_FP - SYNC_601 - ISYNC_601 - MTMSRD(r5) /* enable use of fpu now */ - SYNC_601 - isync - cmpwi 0,r3,0 - beqlr- /* if no previous owner, done */ - addi r3,r3,THREAD /* want THREAD of task */ - lwz r5,PT_REGS(r3) - cmpwi 0,r5,0 - SAVE_32FPRS(0, r3) - mffs fr0 - stfd fr0,THREAD_FPSCR-4(r3) - beq 1f - lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) - li r3,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r3 /* disable FP for previous task */ - stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) -1: -#ifndef CONFIG_SMP - li r5,0 - lis r4,last_task_used_math@ha - stw r5,last_task_used_math@l(r4) -#endif /* CONFIG_SMP */ - blr - /* * This code is jumped to from the startup code to copy * the kernel image to physical address 0. diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 9ed8165a3d6c..9b6a8e513657 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -426,7 +426,11 @@ interrupt_base: PROGRAM_EXCEPTION /* Floating Point Unavailable Interrupt */ +#ifdef CONFIG_PPC_FPU + FP_UNAVAILABLE_EXCEPTION +#else EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) +#endif /* System Call Interrupt */ START_EXCEPTION(SystemCall) @@ -686,8 +690,10 @@ _GLOBAL(giveup_altivec) * * The 44x core does not have an FPU. */ +#ifndef CONFIG_PPC_FPU _GLOBAL(giveup_fpu) blr +#endif /* * extern void abort(void) diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h index 884dac916bce..f213d12eec08 100644 --- a/arch/ppc/kernel/head_booke.h +++ b/arch/ppc/kernel/head_booke.h @@ -337,4 +337,11 @@ label: addi r3,r1,STACK_FRAME_OVERHEAD; \ EXC_XFER_LITE(0x0900, timer_interrupt) +#define FP_UNAVAILABLE_EXCEPTION \ + START_EXCEPTION(FloatingPointUnavailable) \ + NORMAL_EXCEPTION_PROLOG; \ + bne load_up_fpu; /* if from user, just load it up */ \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_EE_LITE(0x800, KernelFP) + #endif /* __HEAD_BOOKE_H__ */ diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index d64bf61d2b1f..f22ddce36135 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S @@ -504,7 +504,11 @@ interrupt_base: PROGRAM_EXCEPTION /* Floating Point Unavailable Interrupt */ +#ifdef CONFIG_PPC_FPU + FP_UNAVAILABLE_EXCEPTION +#else EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) +#endif /* System Call Interrupt */ START_EXCEPTION(SystemCall) @@ -916,10 +920,12 @@ _GLOBAL(giveup_spe) /* * extern void giveup_fpu(struct task_struct *prev) * - * The e500 core does not have an FPU. + * Not all FSL Book-E cores have an FPU */ +#ifndef CONFIG_PPC_FPU _GLOBAL(giveup_fpu) blr +#endif /* * extern void abort(void) diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 73f7c23b0dd4..e4f1615ec13f 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -1096,17 +1096,7 @@ _GLOBAL(_get_SP) * and exceptions as if the cpu had performed the load or store. */ -#if defined(CONFIG_4xx) || defined(CONFIG_E500) -_GLOBAL(cvt_fd) - lfs 0,0(r3) - stfd 0,0(r4) - blr - -_GLOBAL(cvt_df) - lfd 0,0(r3) - stfs 0,0(r4) - blr -#else +#ifdef CONFIG_PPC_FPU _GLOBAL(cvt_fd) lfd 0,-4(r5) /* load up fpscr value */ mtfsf 0xff,0 diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 361865c4bc84..f8e7e324a173 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -176,7 +176,7 @@ static inline int check_io_access(struct pt_regs *regs) #else #define get_mc_reason(regs) (mfspr(SPRN_MCSR)) #endif -#define REASON_FP 0 +#define REASON_FP ESR_FP #define REASON_ILLEGAL ESR_PIL #define REASON_PRIVILEGED ESR_PPR #define REASON_TRAP ESR_PTR diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h index e70c25f3c339..45c5e6f2b7ab 100644 --- a/include/asm-ppc/reg_booke.h +++ b/include/asm-ppc/reg_booke.h @@ -305,6 +305,7 @@ do { \ #define ESR_PIL 0x08000000 /* Program Exception - Illegal */ #define ESR_PPR 0x04000000 /* Program Exception - Priveleged */ #define ESR_PTR 0x02000000 /* Program Exception - Trap */ +#define ESR_FP 0x01000000 /* Floating Point Operation */ #define ESR_DST 0x00800000 /* Storage Exception - Data miss */ #define ESR_DIZ 0x00400000 /* Storage Exception - Zone fault */ #define ESR_ST 0x00800000 /* Store Operation */ -- cgit v1.2.3 From 146a4b3bdfb5641bfbf975e29680b482b8b343ba Mon Sep 17 00:00:00 2001 From: Andreas Jaggi Date: Sun, 1 May 2005 08:58:41 -0700 Subject: [PATCH] macintosh/adbhid.c: adb buttons support for aluminium PowerBook G4 This patch adds support for the special adb buttons of the aluminium PowerBook G4. Signed-off-by: Andreas Jaggi Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/macintosh/adbhid.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/input.h | 5 +++++ 2 files changed, 45 insertions(+) (limited to 'include') diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 8f93d01d8928..db654e8bd67e 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -555,6 +555,42 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto #endif /* CONFIG_PMAC_BACKLIGHT */ input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down); break; + + case 0xc: /* videomode switch */ + input_report_key(&adbhid[id]->input, KEY_SWITCHVIDEOMODE, down); + break; + + case 0xd: /* keyboard illumination toggle */ + input_report_key(&adbhid[id]->input, KEY_KBDILLUMTOGGLE, down); + break; + + case 0xe: /* keyboard illumination decrease */ + input_report_key(&adbhid[id]->input, KEY_KBDILLUMDOWN, down); + break; + + case 0xf: + switch (data[1]) { + case 0x8f: + case 0x0f: + /* keyboard illumination increase */ + input_report_key(&adbhid[id]->input, KEY_KBDILLUMUP, down); + break; + + case 0x7f: + case 0xff: + /* keypad overlay toogle */ + break; + + default: + printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n", + data[0], data[1], data[2], data[3]); + break; + } + break; + default: + printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n", + data[0], data[1], data[2], data[3]); + break; } } break; @@ -775,6 +811,10 @@ adbhid_input_register(int id, int default_id, int original_handler_id, set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit); set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit); set_bit(KEY_EJECTCD, adbhid[id]->input.keybit); + set_bit(KEY_SWITCHVIDEOMODE, adbhid[id]->input.keybit); + set_bit(KEY_KBDILLUMTOGGLE, adbhid[id]->input.keybit); + set_bit(KEY_KBDILLUMDOWN, adbhid[id]->input.keybit); + set_bit(KEY_KBDILLUMUP, adbhid[id]->input.keybit); break; } if (adbhid[id]->name[0]) diff --git a/include/linux/input.h b/include/linux/input.h index b70df8fe60e6..72731d7d189e 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -328,6 +328,11 @@ struct input_absinfo { #define KEY_BRIGHTNESSUP 225 #define KEY_MEDIA 226 +#define KEY_SWITCHVIDEOMODE 227 +#define KEY_KBDILLUMTOGGLE 228 +#define KEY_KBDILLUMDOWN 229 +#define KEY_KBDILLUMUP 230 + #define KEY_UNKNOWN 240 #define BTN_MISC 0x100 -- cgit v1.2.3 From 58366af5861eee1479426380e3c91ecb334c301d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 1 May 2005 08:58:44 -0700 Subject: [PATCH] ppc64: update to use the new 4L headers This patch converts ppc64 to use the generic pgtable-nopud.h instead of the "fixup" header. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/mm/hugetlbpage.c | 45 +++++----- arch/ppc64/mm/init.c | 198 ++++++++++++++++++++++---------------------- include/asm-ppc64/pgalloc.h | 2 +- include/asm-ppc64/pgtable.h | 41 +++++---- 4 files changed, 147 insertions(+), 139 deletions(-) (limited to 'include') diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c index 390296efe3e0..d3bf86a5c1ad 100644 --- a/arch/ppc64/mm/hugetlbpage.c +++ b/arch/ppc64/mm/hugetlbpage.c @@ -42,7 +42,7 @@ static inline int hugepgd_index(unsigned long addr) return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT; } -static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr) +static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr) { int index; @@ -52,21 +52,21 @@ static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr) index = hugepgd_index(addr); BUG_ON(index >= PTRS_PER_HUGEPGD); - return mm->context.huge_pgdir + index; + return (pud_t *)(mm->context.huge_pgdir + index); } -static inline pte_t *hugepte_offset(pgd_t *dir, unsigned long addr) +static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr) { int index; - if (pgd_none(*dir)) + if (pud_none(*dir)) return NULL; index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE; - return (pte_t *)pgd_page(*dir) + index; + return (pte_t *)pud_page(*dir) + index; } -static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr) +static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr) { BUG_ON(! in_hugepage_area(mm->context, addr)); @@ -90,10 +90,9 @@ static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr) return hugepgd_offset(mm, addr); } -static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir, - unsigned long addr) +static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr) { - if (! pgd_present(*dir)) { + if (! pud_present(*dir)) { pte_t *new; spin_unlock(&mm->page_table_lock); @@ -104,7 +103,7 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir, * Because we dropped the lock, we should re-check the * entry, as somebody else could have populated it.. */ - if (pgd_present(*dir)) { + if (pud_present(*dir)) { if (new) kmem_cache_free(zero_cache, new); } else { @@ -115,7 +114,7 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir, ptepage = virt_to_page(new); ptepage->mapping = (void *) mm; ptepage->index = addr & HUGEPGDIR_MASK; - pgd_populate(mm, dir, new); + pud_populate(mm, dir, new); } } @@ -124,28 +123,28 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir, static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) { - pgd_t *pgd; + pud_t *pud; BUG_ON(! in_hugepage_area(mm->context, addr)); - pgd = hugepgd_offset(mm, addr); - if (! pgd) + pud = hugepgd_offset(mm, addr); + if (! pud) return NULL; - return hugepte_offset(pgd, addr); + return hugepte_offset(pud, addr); } static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) { - pgd_t *pgd; + pud_t *pud; BUG_ON(! in_hugepage_area(mm->context, addr)); - pgd = hugepgd_alloc(mm, addr); - if (! pgd) + pud = hugepgd_alloc(mm, addr); + if (! pud) return NULL; - return hugepte_alloc(mm, pgd, addr); + return hugepte_alloc(mm, pud, addr); } static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, @@ -709,10 +708,10 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm) /* cleanup any hugepte pages leftover */ for (i = 0; i < PTRS_PER_HUGEPGD; i++) { - pgd_t *pgd = pgdir + i; + pud_t *pud = (pud_t *)(pgdir + i); - if (! pgd_none(*pgd)) { - pte_t *pte = (pte_t *)pgd_page(*pgd); + if (! pud_none(*pud)) { + pte_t *pte = (pte_t *)pud_page(*pud); struct page *ptepage = virt_to_page(pte); ptepage->mapping = NULL; @@ -720,7 +719,7 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm) BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE)); kmem_cache_free(zero_cache, pte); } - pgd_clear(pgd); + pud_clear(pud); } BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE)); diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c index a7149b9fc35c..cf33d7ec2e29 100644 --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c @@ -136,14 +136,78 @@ void iounmap(volatile void __iomem *addr) #else +static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr, + unsigned long end) +{ + pte_t *pte; + + pte = pte_offset_kernel(pmd, addr); + do { + pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte); + WARN_ON(!pte_none(ptent) && !pte_present(ptent)); + } while (pte++, addr += PAGE_SIZE, addr != end); +} + +static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr, + unsigned long end) +{ + pmd_t *pmd; + unsigned long next; + + pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); + if (pmd_none_or_clear_bad(pmd)) + continue; + unmap_im_area_pte(pmd, addr, next); + } while (pmd++, addr = next, addr != end); +} + +static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr, + unsigned long end) +{ + pud_t *pud; + unsigned long next; + + pud = pud_offset(pgd, addr); + do { + next = pud_addr_end(addr, end); + if (pud_none_or_clear_bad(pud)) + continue; + unmap_im_area_pmd(pud, addr, next); + } while (pud++, addr = next, addr != end); +} + +static void unmap_im_area(unsigned long addr, unsigned long end) +{ + struct mm_struct *mm = &ioremap_mm; + unsigned long next; + pgd_t *pgd; + + spin_lock(&mm->page_table_lock); + + pgd = pgd_offset_i(addr); + flush_cache_vunmap(addr, end); + do { + next = pgd_addr_end(addr, end); + if (pgd_none_or_clear_bad(pgd)) + continue; + unmap_im_area_pud(pgd, addr, next); + } while (pgd++, addr = next, addr != end); + flush_tlb_kernel_range(start, end); + + spin_unlock(&mm->page_table_lock); +} + /* * map_io_page currently only called by __ioremap * map_io_page adds an entry to the ioremap page table * and adds an entry to the HPT, possibly bolting it */ -static void map_io_page(unsigned long ea, unsigned long pa, int flags) +static int map_io_page(unsigned long ea, unsigned long pa, int flags) { pgd_t *pgdp; + pud_t *pudp; pmd_t *pmdp; pte_t *ptep; unsigned long vsid; @@ -151,9 +215,15 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags) if (mem_init_done) { spin_lock(&ioremap_mm.page_table_lock); pgdp = pgd_offset_i(ea); - pmdp = pmd_alloc(&ioremap_mm, pgdp, ea); + pudp = pud_alloc(&ioremap_mm, pgdp, ea); + if (!pudp) + return -ENOMEM; + pmdp = pmd_alloc(&ioremap_mm, pudp, ea); + if (!pmdp) + return -ENOMEM; ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea); - + if (!ptep) + return -ENOMEM; pa = abs_to_phys(pa); set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); @@ -181,6 +251,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags) panic("map_io_page: could not insert mapping"); } } + return 0; } @@ -194,9 +265,14 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, flags |= pgprot_val(PAGE_KERNEL); for (i = 0; i < size; i += PAGE_SIZE) - map_io_page(ea+i, pa+i, flags); + if (map_io_page(ea+i, pa+i, flags)) + goto failure; return (void __iomem *) (ea + (addr & ~PAGE_MASK)); + failure: + if (mem_init_done) + unmap_im_area(ea, ea + size); + return NULL; } @@ -206,10 +282,11 @@ ioremap(unsigned long addr, unsigned long size) return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED); } -void __iomem * -__ioremap(unsigned long addr, unsigned long size, unsigned long flags) +void __iomem * __ioremap(unsigned long addr, unsigned long size, + unsigned long flags) { unsigned long pa, ea; + void __iomem *ret; /* * Choose an address to map it to. @@ -232,12 +309,16 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags) if (area == NULL) return NULL; ea = (unsigned long)(area->addr); + ret = __ioremap_com(addr, pa, ea, size, flags); + if (!ret) + im_free(area->addr); } else { ea = ioremap_bot; - ioremap_bot += size; + ret = __ioremap_com(addr, pa, ea, size, flags); + if (ret) + ioremap_bot += size; } - - return __ioremap_com(addr, pa, ea, size, flags); + return ret; } #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) @@ -246,6 +327,7 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, unsigned long size, unsigned long flags) { struct vm_struct *area; + void __iomem *ret; /* For now, require page-aligned values for pa, ea, and size */ if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || @@ -276,7 +358,12 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, } } - if (__ioremap_com(pa, pa, ea, size, flags) != (void *) ea) { + ret = __ioremap_com(pa, pa, ea, size, flags); + if (ret == NULL) { + printk(KERN_ERR "ioremap_explicit() allocation failure !\n"); + return 1; + } + if (ret != (void *) ea) { printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); return 1; } @@ -284,69 +371,6 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, return 0; } -static void unmap_im_area_pte(pmd_t *pmd, unsigned long address, - unsigned long size) -{ - unsigned long base, end; - pte_t *pte; - - if (pmd_none(*pmd)) - return; - if (pmd_bad(*pmd)) { - pmd_ERROR(*pmd); - pmd_clear(pmd); - return; - } - - pte = pte_offset_kernel(pmd, address); - base = address & PMD_MASK; - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - - do { - pte_t page; - page = ptep_get_and_clear(&ioremap_mm, base + address, pte); - address += PAGE_SIZE; - pte++; - if (pte_none(page)) - continue; - if (pte_present(page)) - continue; - printk(KERN_CRIT "Whee.. Swapped out page in kernel page" - " table\n"); - } while (address < end); -} - -static void unmap_im_area_pmd(pgd_t *dir, unsigned long address, - unsigned long size) -{ - unsigned long base, end; - pmd_t *pmd; - - if (pgd_none(*dir)) - return; - if (pgd_bad(*dir)) { - pgd_ERROR(*dir); - pgd_clear(dir); - return; - } - - pmd = pmd_offset(dir, address); - base = address & PGDIR_MASK; - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - - do { - unmap_im_area_pte(pmd, base + address, end - address); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); -} - /* * Unmap an IO region and remove it from imalloc'd list. * Access to IO memory should be serialized by driver. @@ -356,39 +380,19 @@ static void unmap_im_area_pmd(pgd_t *dir, unsigned long address, */ void iounmap(volatile void __iomem *token) { - unsigned long address, start, end, size; - struct mm_struct *mm; - pgd_t *dir; + unsigned long address, size; void *addr; - if (!mem_init_done) { + if (!mem_init_done) return; - } addr = (void *) ((unsigned long __force) token & PAGE_MASK); - if ((size = im_free(addr)) == 0) { + if ((size = im_free(addr)) == 0) return; - } address = (unsigned long)addr; - start = address; - end = address + size; - - mm = &ioremap_mm; - spin_lock(&mm->page_table_lock); - - dir = pgd_offset_i(address); - flush_cache_vunmap(address, end); - do { - unmap_im_area_pmd(dir, address, end - address); - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_kernel_range(start, end); - - spin_unlock(&mm->page_table_lock); - return; + unmap_im_area(address, address + size); } static int iounmap_subset_regions(unsigned long addr, unsigned long size) diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h index 16232d740173..4fc4b739b380 100644 --- a/include/asm-ppc64/pgalloc.h +++ b/include/asm-ppc64/pgalloc.h @@ -27,7 +27,7 @@ pgd_free(pgd_t *pgd) kmem_cache_free(zero_cache, pgd); } -#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD) +#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long addr) diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index a26120517c54..b984e2747e0c 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -1,8 +1,6 @@ #ifndef _PPC64_PGTABLE_H #define _PPC64_PGTABLE_H -#include - /* * This file contains the functions and defines necessary to modify and use * the ppc64 hashed page table. @@ -17,6 +15,8 @@ #include #endif /* __ASSEMBLY__ */ +#include + /* PMD_SHIFT determines what a second-level page table entry can map */ #define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3) #define PMD_SIZE (1UL << PMD_SHIFT) @@ -228,12 +228,13 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); #define pmd_page_kernel(pmd) \ (__bpn_to_ba(pmd_val(pmd) >> PMD_TO_PTEPAGE_SHIFT)) #define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) -#define pgd_set(pgdp, pmdp) (pgd_val(*(pgdp)) = (__ba_to_bpn(pmdp))) -#define pgd_none(pgd) (!pgd_val(pgd)) -#define pgd_bad(pgd) ((pgd_val(pgd)) == 0) -#define pgd_present(pgd) (pgd_val(pgd) != 0UL) -#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0UL) -#define pgd_page(pgd) (__bpn_to_ba(pgd_val(pgd))) + +#define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (__ba_to_bpn(pmdp))) +#define pud_none(pud) (!pud_val(pud)) +#define pud_bad(pud) ((pud_val(pud)) == 0UL) +#define pud_present(pud) (pud_val(pud) != 0UL) +#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) +#define pud_page(pud) (__bpn_to_ba(pud_val(pud))) /* * Find an entry in a page-table-directory. We combine the address region @@ -245,12 +246,13 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) /* Find an entry in the second-level page table.. */ -#define pmd_offset(dir,addr) \ - ((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) +#define pmd_offset(pudp,addr) \ + ((pmd_t *) pud_page(*(pudp)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) /* Find an entry in the third-level page table.. */ #define pte_offset_kernel(dir,addr) \ - ((pte_t *) pmd_page_kernel(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) + ((pte_t *) pmd_page_kernel(*(dir)) \ + + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) @@ -582,19 +584,22 @@ extern long native_hpte_insert(unsigned long hpte_group, unsigned long va, static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) { pgd_t *pg; + pud_t *pu; pmd_t *pm; pte_t *pt = NULL; pte_t pte; pg = pgdir + pgd_index(ea); if (!pgd_none(*pg)) { - - pm = pmd_offset(pg, ea); - if (pmd_present(*pm)) { - pt = pte_offset_kernel(pm, ea); - pte = *pt; - if (!pte_present(pte)) - pt = NULL; + pu = pud_offset(pg, ea); + if (!pud_none(*pu)) { + pm = pmd_offset(pu, ea); + if (pmd_present(*pm)) { + pt = pte_offset_kernel(pm, ea); + pte = *pt; + if (!pte_present(pte)) + pt = NULL; + } } } -- cgit v1.2.3 From a2f95a5ae99eb8209ad8d9faeaada00600bd8027 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 1 May 2005 08:58:45 -0700 Subject: [PATCH] ppc64: noexec fixes There were a few issues with the ppc64 noexec support: The 64bit ABI has a non executable stack by default. At the moment 64bit apps require a PT_GNU_STACK section in order to have a non executable stack. Disable the read implies exec workaround on the 64bit ABI. The 64bit toolchain has never had problems with incorrect mmap permissions (the 32bit has, thats why we need to retain the workaround). With these fixes as well as a gcc fix from Alan Modra (that was recently committed) 64bit apps work as expected. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ppc64/elf.h | 8 ++++++-- include/asm-ppc64/page.h | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h index 8457d90244fb..6c42d61bedd1 100644 --- a/include/asm-ppc64/elf.h +++ b/include/asm-ppc64/elf.h @@ -229,9 +229,13 @@ do { \ /* * An executable for which elf_read_implies_exec() returns TRUE will - * have the READ_IMPLIES_EXEC personality flag set automatically. + * have the READ_IMPLIES_EXEC personality flag set automatically. This + * is only required to work around bugs in old 32bit toolchains. Since + * the 64bit ABI has never had these issues dont enable the workaround + * even if we have an executable stack. */ -#define elf_read_implies_exec(ex, exec_stk) (exec_stk != EXSTACK_DISABLE_X) +#define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \ + (exec_stk != EXSTACK_DISABLE_X) : 0) #endif diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h index 20e0f19324e8..86219574c1a5 100644 --- a/include/asm-ppc64/page.h +++ b/include/asm-ppc64/page.h @@ -252,10 +252,19 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */ /* * This is the default if a program doesn't have a PT_GNU_STACK - * program header entry. + * program header entry. The PPC64 ELF ABI has a non executable stack + * stack by default, so in the absense of a PT_GNU_STACK program header + * we turn execute permission off. */ -#define VM_STACK_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#define VM_STACK_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#define VM_STACK_DEFAULT_FLAGS \ + (test_thread_flag(TIF_32BIT) ? \ + VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) #endif /* __KERNEL__ */ #endif /* _PPC64_PAGE_H */ -- cgit v1.2.3 From 4b88e927e8c38f4053680a3098325142017a37f0 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 1 May 2005 08:58:46 -0700 Subject: [PATCH] ppc64: remove unnecessary include We no longer use any ppcdebug stuff in a.out.h, so remove the define. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ppc64/a.out.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h index 802338efcb19..3871e252a6f1 100644 --- a/include/asm-ppc64/a.out.h +++ b/include/asm-ppc64/a.out.h @@ -1,8 +1,6 @@ #ifndef __PPC64_A_OUT_H__ #define __PPC64_A_OUT_H__ -#include - /* * c 2001 PPC 64 Team, IBM Corp * -- cgit v1.2.3 From d637413f3f05b41f678f8004225b33b62274183f Mon Sep 17 00:00:00 2001 From: Jake Moilanen Date: Sun, 1 May 2005 08:58:47 -0700 Subject: [PATCH] ppc64: reverse prediction on spinlock busy loop code On our raw spinlocks, we currently have an attempt at the lock, and if we do not get it we enter a spin loop. This spinloop will likely continue for awhile, and we pridict likely. Shouldn't we predict that we will get out of the loop so our next instructions are already prefetched. Even when we miss because the lock is still held, it won't matter since we are waiting anyways. I did a couple quick benchmarks, but the results are inconclusive. 16-way 690 running specjbb with original code # ./specjbb 3000 16 1 1 19 30 120 ... Valid run, Score is 59282 16-way 690 running specjbb with unlikely code # ./specjbb 3000 16 1 1 19 30 120 ... Valid run, Score is 59541 I saw a smaller increase on a JS20 (~1.6%) JS20 specjbb w/ original code # ./specjbb 400 2 1 1 19 30 120 ... Valid run, Score is 20460 JS20 specjbb w/ unlikely code # ./specjbb 400 2 1 1 19 30 120 ... Valid run, Score is 20803 Anton said: Mispredicting the spinlock busy loop also means we slow down the rate at which we do the loads which can be good for heavily contended locks. Note: There are some gcc issues with our default build and branch prediction, but a CONFIG_POWER4_ONLY build should emit them correctly. I'm working with Alan Modra on it now. Signed-off-by: Jake Moilanen Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ppc64/spinlock.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h index a9b2a1162cf7..acd11564dd75 100644 --- a/include/asm-ppc64/spinlock.h +++ b/include/asm-ppc64/spinlock.h @@ -110,7 +110,7 @@ static void __inline__ _raw_spin_lock(spinlock_t *lock) HMT_low(); if (SHARED_PROCESSOR) __spin_yield(lock); - } while (likely(lock->lock != 0)); + } while (unlikely(lock->lock != 0)); HMT_medium(); } } @@ -128,7 +128,7 @@ static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flag HMT_low(); if (SHARED_PROCESSOR) __spin_yield(lock); - } while (likely(lock->lock != 0)); + } while (unlikely(lock->lock != 0)); HMT_medium(); local_irq_restore(flags_dis); } @@ -194,7 +194,7 @@ static void __inline__ _raw_read_lock(rwlock_t *rw) HMT_low(); if (SHARED_PROCESSOR) __rw_yield(rw); - } while (likely(rw->lock < 0)); + } while (unlikely(rw->lock < 0)); HMT_medium(); } } @@ -251,7 +251,7 @@ static void __inline__ _raw_write_lock(rwlock_t *rw) HMT_low(); if (SHARED_PROCESSOR) __rw_yield(rw); - } while (likely(rw->lock != 0)); + } while (unlikely(rw->lock != 0)); HMT_medium(); } } -- cgit v1.2.3 From d5b63d78f1e75f6c6f04862dfb2f2a4aeffafd4c Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sun, 1 May 2005 08:58:48 -0700 Subject: [PATCH] fix i386 memcpy This patch shortens non-constant memcpy() by two bytes and fixes spurious out-of-line constant memcpy(). # size vmlinux.org vmlinux text data bss dec hex filename 3954591 1553426 236544 5744561 57a7b1 vmlinux.org 3952615 1553426 236544 5742585 579ff9 vmlinux Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/string.h | 89 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h index 1679983d053f..6a78ac58c194 100644 --- a/include/asm-i386/string.h +++ b/include/asm-i386/string.h @@ -198,47 +198,80 @@ static inline void * __memcpy(void * to, const void * from, size_t n) int d0, d1, d2; __asm__ __volatile__( "rep ; movsl\n\t" - "testb $2,%b4\n\t" - "je 1f\n\t" - "movsw\n" - "1:\ttestb $1,%b4\n\t" - "je 2f\n\t" - "movsb\n" - "2:" + "movl %4,%%ecx\n\t" + "andl $3,%%ecx\n\t" +#if 1 /* want to pay 2 byte penalty for a chance to skip microcoded rep? */ + "jz 1f\n\t" +#endif + "rep ; movsb\n\t" + "1:" : "=&c" (d0), "=&D" (d1), "=&S" (d2) - :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "0" (n/4), "g" (n), "1" ((long) to), "2" ((long) from) : "memory"); return (to); } /* - * This looks horribly ugly, but the compiler can optimize it totally, + * This looks ugly, but the compiler can optimize it totally, * as the count is constant. */ static inline void * __constant_memcpy(void * to, const void * from, size_t n) { - if (n <= 128) - return __builtin_memcpy(to, from, n); - -#define COMMON(x) \ -__asm__ __volatile__( \ - "rep ; movsl" \ - x \ - : "=&c" (d0), "=&D" (d1), "=&S" (d2) \ - : "0" (n/4),"1" ((long) to),"2" ((long) from) \ - : "memory"); -{ - int d0, d1, d2; + long esi, edi; + if (!n) return to; +#if 1 /* want to do small copies with non-string ops? */ + switch (n) { + case 1: *(char*)to = *(char*)from; return to; + case 2: *(short*)to = *(short*)from; return to; + case 4: *(int*)to = *(int*)from; return to; +#if 1 /* including those doable with two moves? */ + case 3: *(short*)to = *(short*)from; + *((char*)to+2) = *((char*)from+2); return to; + case 5: *(int*)to = *(int*)from; + *((char*)to+4) = *((char*)from+4); return to; + case 6: *(int*)to = *(int*)from; + *((short*)to+2) = *((short*)from+2); return to; + case 8: *(int*)to = *(int*)from; + *((int*)to+1) = *((int*)from+1); return to; +#endif + } +#endif + esi = (long) from; + edi = (long) to; + if (n >= 5*4) { + /* large block: use rep prefix */ + int ecx; + __asm__ __volatile__( + "rep ; movsl" + : "=&c" (ecx), "=&D" (edi), "=&S" (esi) + : "0" (n/4), "1" (edi),"2" (esi) + : "memory" + ); + } else { + /* small block: don't clobber ecx + smaller code */ + if (n >= 4*4) __asm__ __volatile__("movsl" + :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory"); + if (n >= 3*4) __asm__ __volatile__("movsl" + :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory"); + if (n >= 2*4) __asm__ __volatile__("movsl" + :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory"); + if (n >= 1*4) __asm__ __volatile__("movsl" + :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory"); + } switch (n % 4) { - case 0: COMMON(""); return to; - case 1: COMMON("\n\tmovsb"); return to; - case 2: COMMON("\n\tmovsw"); return to; - default: COMMON("\n\tmovsw\n\tmovsb"); return to; + /* tail */ + case 0: return to; + case 1: __asm__ __volatile__("movsb" + :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory"); + return to; + case 2: __asm__ __volatile__("movsw" + :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory"); + return to; + default: __asm__ __volatile__("movsw\n\tmovsb" + :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory"); + return to; } } - -#undef COMMON -} #define __HAVE_ARCH_MEMCPY -- cgit v1.2.3 From fd51f666fa591294bd7462447512666e61c56ea0 Mon Sep 17 00:00:00 2001 From: "H. J. Lu" Date: Sun, 1 May 2005 08:58:48 -0700 Subject: [PATCH] i386/x86_64 segment register access update The new i386/x86_64 assemblers no longer accept instructions for moving between a segment register and a 32bit memory location, i.e., movl (%eax),%ds movl %ds,(%eax) To generate instructions for moving between a segment register and a 16bit memory location without the 16bit operand size prefix, 0x66, mov (%eax),%ds mov %ds,(%eax) should be used. It will work with both new and old assemblers. The assembler starting from 2.16.90.0.1 will also support movw (%eax),%ds movw %ds,(%eax) without the 0x66 prefix. I am enclosing patches for 2.4 and 2.6 kernels here. The resulting kernel binaries should be unchanged as before, with old and new assemblers, if gcc never generates memory access for unsigned gsindex; asm volatile("movl %%gs,%0" : "=g" (gsindex)); If gcc does generate memory access for the code above, the upper bits in gsindex are undefined and the new assembler doesn't allow it. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/process.c | 4 ++-- arch/i386/kernel/vm86.c | 4 ++-- arch/x86_64/kernel/process.c | 12 ++++++------ include/asm-i386/system.h | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index b2203e21acb3..85bd56d44314 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -611,8 +611,8 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas * Save away %fs and %gs. No need to save %es and %ds, as * those are always kernel segments while inside the kernel. */ - asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); - asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); + asm volatile("mov %%fs,%0":"=m" (prev->fs)); + asm volatile("mov %%gs,%0":"=m" (prev->gs)); /* * Restore %fs and %gs if needed. diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index 2f3d52dacff7..d16cd3738a48 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -294,8 +294,8 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk */ info->regs32->eax = 0; tsk->thread.saved_esp0 = tsk->thread.esp0; - asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs)); - asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs)); + asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs)); + asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs)); tss = &per_cpu(init_tss, get_cpu()); tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 9922d2ba24a3..761b6d35e338 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -402,10 +402,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, p->thread.fs = me->thread.fs; p->thread.gs = me->thread.gs; - asm("movl %%gs,%0" : "=m" (p->thread.gsindex)); - asm("movl %%fs,%0" : "=m" (p->thread.fsindex)); - asm("movl %%es,%0" : "=m" (p->thread.es)); - asm("movl %%ds,%0" : "=m" (p->thread.ds)); + asm("mov %%gs,%0" : "=m" (p->thread.gsindex)); + asm("mov %%fs,%0" : "=m" (p->thread.fsindex)); + asm("mov %%es,%0" : "=m" (p->thread.es)); + asm("mov %%ds,%0" : "=m" (p->thread.ds)); if (unlikely(me->thread.io_bitmap_ptr != NULL)) { p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); @@ -468,11 +468,11 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct * * Switch DS and ES. * This won't pick up thread selector changes, but I guess that is ok. */ - asm volatile("movl %%es,%0" : "=m" (prev->es)); + asm volatile("mov %%es,%0" : "=m" (prev->es)); if (unlikely(next->es | prev->es)) loadsegment(es, next->es); - asm volatile ("movl %%ds,%0" : "=m" (prev->ds)); + asm volatile ("mov %%ds,%0" : "=m" (prev->ds)); if (unlikely(next->ds | prev->ds)) loadsegment(ds, next->ds); diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 6f74d4c44a0e..3db717a244f0 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h @@ -81,7 +81,7 @@ static inline unsigned long _get_base(char * addr) #define loadsegment(seg,value) \ asm volatile("\n" \ "1:\t" \ - "movl %0,%%" #seg "\n" \ + "mov %0,%%" #seg "\n" \ "2:\n" \ ".section .fixup,\"ax\"\n" \ "3:\t" \ @@ -93,13 +93,13 @@ static inline unsigned long _get_base(char * addr) ".align 4\n\t" \ ".long 1b,3b\n" \ ".previous" \ - : :"m" (*(unsigned int *)&(value))) + : :"m" (value)) /* * Save a segment register away */ #define savesegment(seg, value) \ - asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value))) + asm volatile("mov %%" #seg ",%0":"=m" (value)) /* * Clear and set 'TS' bit respectively -- cgit v1.2.3 From 67701ae9767534534d3710664037dfde2cc04935 Mon Sep 17 00:00:00 2001 From: Jack F Vogel Date: Sun, 1 May 2005 08:58:48 -0700 Subject: [PATCH] check nmi watchdog is broken A bug against an xSeries system showed up recently noting that the check_nmi_watchdog() test was failing. I have been investigating it and discovered in both i386 and x86_64 the recent change to the routine to use the cpu_callin_map has uncovered a problem. Prior to that change, on an SMP box, the test was trivally passing because all cpu's were found to not yet be online, but now with the callin_map they are discovered, it goes on to test the counter and they have not yet begun to increment, so it announces a CPU is stuck and bails out. On all the systems I have access to test, the announcement of failure is also bougs... by the time you can login and check /proc/interrupts, the NMI count is happily incrementing on all CPUs. Its just that the test is being done too early. I have tried moving the call to the test around a bit, and it was always too early. I finally hit on this proposed solution, it delays the routine via a late_initcall(), seems like the right solution to me. Signed-off-by: Adrian Bunk Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apic.c | 2 -- arch/i386/kernel/io_apic.c | 2 -- arch/i386/kernel/nmi.c | 11 +++++++---- arch/i386/kernel/smpboot.c | 3 --- arch/x86_64/kernel/io_apic.c | 2 -- arch/x86_64/kernel/nmi.c | 9 +++++++-- include/asm-i386/apic.h | 1 - include/asm-x86_64/apic.h | 1 - 8 files changed, 14 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index e3879f7625c2..d509836b70c3 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -1265,8 +1265,6 @@ int __init APIC_init_uniprocessor (void) setup_local_APIC(); - if (nmi_watchdog == NMI_LOCAL_APIC) - check_nmi_watchdog(); #ifdef CONFIG_X86_IO_APIC if (smp_found_config) if (!skip_ioapic_setup && nr_ioapics) diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 5e0d55be5435..7a324e8b86f9 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -2175,7 +2175,6 @@ static inline void check_timer(void) disable_8259A_irq(0); setup_nmi(); enable_8259A_irq(0); - check_nmi_watchdog(); } return; } @@ -2198,7 +2197,6 @@ static inline void check_timer(void) add_pin_to_irq(0, 0, pin2); if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); - check_nmi_watchdog(); } return; } diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 2f89d000f954..2c0ee9c2d020 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -102,20 +102,21 @@ int nmi_active; (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) -int __init check_nmi_watchdog (void) +static int __init check_nmi_watchdog(void) { unsigned int prev_nmi_count[NR_CPUS]; int cpu; - printk(KERN_INFO "testing NMI watchdog ... "); + if (nmi_watchdog == NMI_NONE) + return 0; + + printk(KERN_INFO "Testing NMI watchdog ... "); for (cpu = 0; cpu < NR_CPUS; cpu++) prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count; local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks - /* FIXME: Only boot CPU is online at this stage. Check CPUs - as they come up. */ for (cpu = 0; cpu < NR_CPUS; cpu++) { #ifdef CONFIG_SMP /* Check cpu_callin_map here because that is set @@ -139,6 +140,8 @@ int __init check_nmi_watchdog (void) return 0; } +/* This needs to happen later in boot so counters are working */ +late_initcall(check_nmi_watchdog); static int __init setup_nmi_watchdog(char *str) { diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index fd36d2f65f88..cbea7ac582e5 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1089,9 +1089,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) } } - if (nmi_watchdog == NMI_LOCAL_APIC) - check_nmi_watchdog(); - smpboot_setup_io_apic(); setup_boot_APIC_clock(); diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 29a257295484..60be58617eb9 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -1607,7 +1607,6 @@ static inline void check_timer(void) disable_8259A_irq(0); setup_nmi(); enable_8259A_irq(0); - check_nmi_watchdog(); } return; } @@ -1627,7 +1626,6 @@ static inline void check_timer(void) nmi_watchdog_default(); if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); - check_nmi_watchdog(); } return; } diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index e00d4adec36b..61de0b34a01e 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -112,17 +112,20 @@ static __init int cpu_has_lapic(void) } } -int __init check_nmi_watchdog (void) +static int __init check_nmi_watchdog (void) { int counts[NR_CPUS]; int cpu; + if (nmi_watchdog == NMI_NONE) + return 0; + if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic()) { nmi_watchdog = NMI_NONE; return -1; } - printk(KERN_INFO "testing NMI watchdog ... "); + printk(KERN_INFO "Testing NMI watchdog ... "); for (cpu = 0; cpu < NR_CPUS; cpu++) counts[cpu] = cpu_pda[cpu].__nmi_count; @@ -148,6 +151,8 @@ int __init check_nmi_watchdog (void) return 0; } +/* Have this called later during boot so counters are updating */ +late_initcall(check_nmi_watchdog); int __init setup_nmi_watchdog(char *str) { diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index e1de67483f38..a5810cf7b578 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -109,7 +109,6 @@ extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); -extern int check_nmi_watchdog (void); extern void enable_NMI_through_LVT0 (void * dummy); extern unsigned int nmi_watchdog; diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h index c025cc3ef789..e4b1017b8b2b 100644 --- a/include/asm-x86_64/apic.h +++ b/include/asm-x86_64/apic.h @@ -99,7 +99,6 @@ extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); extern void clustered_apic_check(void); -extern int check_nmi_watchdog(void); extern void nmi_watchdog_default(void); extern int setup_nmi_watchdog(char *); -- cgit v1.2.3 From a2f7c354159b87dfbd9900f597d48d18755a9d16 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Sun, 1 May 2005 08:58:49 -0700 Subject: [PATCH] x86 reboot: Add reboot fixup for gx1/cs5530a This patch by Jaya Kumar introduces a generic infrastructure to deal with x86 chipsets with nonstandard reset sequences, and adds support for the Geode gx1/cs5530a chipset. Signed-off-by: Jaya Kumar Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig | 18 +++++++++++++ arch/i386/kernel/Makefile | 1 + arch/i386/kernel/reboot.c | 2 ++ arch/i386/kernel/reboot_fixups.c | 56 ++++++++++++++++++++++++++++++++++++++++ include/linux/reboot_fixups.h | 10 +++++++ 5 files changed, 87 insertions(+) create mode 100644 arch/i386/kernel/reboot_fixups.c create mode 100644 include/linux/reboot_fixups.h (limited to 'include') diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 17a0cbce6f30..99b4f294a52d 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -653,6 +653,24 @@ config I8K Say Y if you intend to run this kernel on a Dell Inspiron 8000. Say N otherwise. +config X86_REBOOTFIXUPS + bool "Enable X86 board specific fixups for reboot" + depends on X86 + default n + ---help--- + This enables chipset and/or board specific fixups to be done + in order to get reboot to work correctly. This is only needed on + some combinations of hardware and BIOS. The symptom, for which + this config is intended, is when reboot ends with a stalled/hung + system. + + Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1. + combination. + + Say Y if you want to enable the fixup. Currently, it's safe to + enable this option even if you don't need it. + Say N otherwise. + config MICROCODE tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" ---help--- diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index aacdae6f372d..0fbcfe00dd8d 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o +obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o obj-$(CONFIG_KPROBES) += kprobes.o diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 3d7e994563df..6dc27eb70ee7 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -13,6 +13,7 @@ #include #include #include "mach_reboot.h" +#include /* * Power off function, if any @@ -348,6 +349,7 @@ void machine_restart(char * __unused) /* rebooting needs to touch the page at absolute addr 0 */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { + mach_reboot_fixups(); /* for board specific fixups */ mach_reboot(); /* That didn't work - force a triple fault.. */ __asm__ __volatile__("lidt %0": :"m" (no_idt)); diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c new file mode 100644 index 000000000000..1b183b378c2c --- /dev/null +++ b/arch/i386/kernel/reboot_fixups.c @@ -0,0 +1,56 @@ +/* + * linux/arch/i386/kernel/reboot_fixups.c + * + * This is a good place to put board specific reboot fixups. + * + * List of supported fixups: + * geode-gx1/cs5530a - Jaya Kumar + * + */ + +#include +#include + +static void cs5530a_warm_reset(struct pci_dev *dev) +{ + /* writing 1 to the reset control register, 0x44 causes the + cs5530a to perform a system warm reset */ + pci_write_config_byte(dev, 0x44, 0x1); + udelay(50); /* shouldn't get here but be safe and spin-a-while */ + return; +} + +struct device_fixup { + unsigned int vendor; + unsigned int device; + void (*reboot_fixup)(struct pci_dev *); +}; + +static struct device_fixup fixups_table[] = { +{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, +}; + +/* + * we see if any fixup is available for our current hardware. if there + * is a fixup, we call it and we expect to never return from it. if we + * do return, we keep looking and then eventually fall back to the + * standard mach_reboot on return. + */ +void mach_reboot_fixups(void) +{ + struct device_fixup *cur; + struct pci_dev *dev; + int i; + + for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) { + cur = &(fixups_table[i]); + dev = pci_get_device(cur->vendor, cur->device, 0); + if (!dev) + continue; + + cur->reboot_fixup(dev); + } + + printk(KERN_WARNING "No reboot fixup found for your hardware\n"); +} + diff --git a/include/linux/reboot_fixups.h b/include/linux/reboot_fixups.h new file mode 100644 index 000000000000..480ea2d489d8 --- /dev/null +++ b/include/linux/reboot_fixups.h @@ -0,0 +1,10 @@ +#ifndef _LINUX_REBOOT_FIXUPS_H +#define _LINUX_REBOOT_FIXUPS_H + +#ifdef CONFIG_X86_REBOOTFIXUPS +extern void mach_reboot_fixups(void); +#else +#define mach_reboot_fixups() ((void)(0)) +#endif + +#endif /* _LINUX_REBOOT_FIXUPS_H */ -- cgit v1.2.3 From 5b7abc6fdcaf103f15e06c518ef0aec02a9c00e7 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 1 May 2005 08:58:49 -0700 Subject: [PATCH] CPUID bug and inconsistency fix The recent support for K8 multicore was misported from x86-64 to i386, due to an unnecessary inconsistency between the CPUID code. Sure, there is are no x86-64 VIA chips yet, but it should happen eventually. This patch fixes the i386 bug as well as makes x86-64 match i386 in the handing of the CPUID array. Signed-off-by: H. Peter Anvin Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/setup.c | 10 ++++++++-- include/asm-i386/cpufeature.h | 4 ++-- include/asm-x86_64/cpufeature.h | 14 ++++++++++---- 3 files changed, 20 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index b18c114c7648..2959ce703df9 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -977,7 +977,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c) if ((xlvl & 0xffff0000) == 0x80000000) { if (xlvl >= 0x80000001) { c->x86_capability[1] = cpuid_edx(0x80000001); - c->x86_capability[5] = cpuid_ecx(0x80000001); + c->x86_capability[6] = cpuid_ecx(0x80000001); } if (xlvl >= 0x80000004) get_model_name(c); /* Default name */ @@ -1100,11 +1100,17 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* VIA/Cyrix/Centaur-defined */ + NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* AMD-defined (#2) */ "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static char *x86_power_flags[] = { "ts", /* temperature sensor */ diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h index e147cabd3bfe..ff1187e80c32 100644 --- a/include/asm-i386/cpufeature.h +++ b/include/asm-i386/cpufeature.h @@ -87,8 +87,8 @@ #define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ /* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ -#define X86_FEATURE_LAHF_LM (5*32+ 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY (5*32+ 1) /* If yes HyperThreading not valid */ +#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h index e68ad97a6319..aea308c65709 100644 --- a/include/asm-x86_64/cpufeature.h +++ b/include/asm-x86_64/cpufeature.h @@ -7,7 +7,7 @@ #ifndef __ASM_X8664_CPUFEATURE_H #define __ASM_X8664_CPUFEATURE_H -#define NCAPINTS 6 +#define NCAPINTS 7 /* N 32-bit words worth of info */ /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */ #define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ @@ -74,9 +74,15 @@ #define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ #define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ -/* More extended AMD flags: CPUID level 0x80000001, ecx, word 5 */ -#define X86_FEATURE_LAHF_LM (5*32+ 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY (5*32+ 1) /* If yes HyperThreading not valid */ +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ +#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */ +#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ +#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ + +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) -- cgit v1.2.3 From 35492df5ae0f36f717448b2aea908d3a8891d1c4 Mon Sep 17 00:00:00 2001 From: john stultz Date: Sun, 1 May 2005 08:58:50 -0700 Subject: [PATCH] i386: fix hpet for systems that don't support legacy replacement Currently the i386 HPET code assumes the entire HPET implementation from the spec is present. This breaks on boxes that do not implement the optional legacy timer replacement functionality portion of the spec. This patch, which is very similar to my x86-64 patch for the same issue, fixes the problem allowing i386 systems that cannot use the HPET for the timer interrupt and RTC to still use the HPET as a time source. I've tested this patch on a system systems without HPET, with HPET but without legacy timer replacement, as well as HPET with legacy timer replacement. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/time.c | 2 +- arch/i386/kernel/time_hpet.c | 48 ++++++++++++++++++++---------------- arch/i386/kernel/timers/timer_hpet.c | 11 ++++++--- arch/i386/kernel/timers/timer_tsc.c | 2 +- include/asm-i386/hpet.h | 1 + 5 files changed, 37 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 4d75b373f90e..a0dcb7c87c30 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -441,7 +441,7 @@ static void __init hpet_time_init(void) set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - if (hpet_enable() >= 0) { + if ((hpet_enable() >= 0) && hpet_use_timer) { printk("Using HPET for base-timer\n"); } diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c index 244a31b04be7..10a0cbb88e75 100644 --- a/arch/i386/kernel/time_hpet.c +++ b/arch/i386/kernel/time_hpet.c @@ -26,6 +26,7 @@ static unsigned long hpet_period; /* fsecs / HPET clock */ unsigned long hpet_tick; /* hpet clks count per tick */ unsigned long hpet_address; /* hpet memory map physical address */ +int hpet_use_timer; static int use_hpet; /* can be used for runtime check of hpet */ static int boot_hpet_disable; /* boottime override for HPET timer */ @@ -73,27 +74,30 @@ static int hpet_timer_stop_set_go(unsigned long tick) hpet_writel(0, HPET_COUNTER); hpet_writel(0, HPET_COUNTER + 4); - /* - * Set up timer 0, as periodic with first interrupt to happen at - * hpet_tick, and period also hpet_tick. - */ - cfg = hpet_readl(HPET_T0_CFG); - cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | - HPET_TN_SETVAL | HPET_TN_32BIT; - hpet_writel(cfg, HPET_T0_CFG); - - /* - * The first write after writing TN_SETVAL to the config register sets - * the counter value, the second write sets the threshold. - */ - hpet_writel(tick, HPET_T0_CMP); - hpet_writel(tick, HPET_T0_CMP); + if (hpet_use_timer) { + /* + * Set up timer 0, as periodic with first interrupt to happen at + * hpet_tick, and period also hpet_tick. + */ + cfg = hpet_readl(HPET_T0_CFG); + cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | + HPET_TN_SETVAL | HPET_TN_32BIT; + hpet_writel(cfg, HPET_T0_CFG); + /* + * The first write after writing TN_SETVAL to the config register sets + * the counter value, the second write sets the threshold. + */ + hpet_writel(tick, HPET_T0_CMP); + hpet_writel(tick, HPET_T0_CMP); + } /* * Go! */ cfg = hpet_readl(HPET_CFG); - cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY; + if (hpet_use_timer) + cfg |= HPET_CFG_LEGACY; + cfg |= HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); return 0; @@ -128,12 +132,11 @@ int __init hpet_enable(void) * However, we can do with one timer otherwise using the * the single HPET timer for system time. */ - if ( #ifdef CONFIG_HPET_EMULATE_RTC - !(id & HPET_ID_NUMBER) || -#endif - !(id & HPET_ID_LEGSUP)) + if (!(id & HPET_ID_NUMBER)) return -1; +#endif + hpet_period = hpet_readl(HPET_PERIOD); if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) @@ -152,6 +155,8 @@ int __init hpet_enable(void) if (hpet_tick_rem > (hpet_period >> 1)) hpet_tick++; /* rounding the result */ + hpet_use_timer = id & HPET_ID_LEGSUP; + if (hpet_timer_stop_set_go(hpet_tick)) return -1; @@ -202,7 +207,8 @@ int __init hpet_enable(void) #endif #ifdef CONFIG_X86_LOCAL_APIC - wait_timer_tick = wait_hpet_tick; + if (hpet_use_timer) + wait_timer_tick = wait_hpet_tick; #endif return 0; } diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c index 713134e71844..f778f471a09a 100644 --- a/arch/i386/kernel/timers/timer_hpet.c +++ b/arch/i386/kernel/timers/timer_hpet.c @@ -79,7 +79,7 @@ static unsigned long get_offset_hpet(void) eax = hpet_readl(HPET_COUNTER); eax -= hpet_last; /* hpet delta */ - + eax = min(hpet_tick, eax); /* * Time offset = (hpet delta) * ( usecs per HPET clock ) * = (hpet delta) * ( usecs per tick / HPET clocks per tick) @@ -105,9 +105,12 @@ static void mark_offset_hpet(void) last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; rdtsc(last_tsc_low, last_tsc_high); - offset = hpet_readl(HPET_T0_CMP) - hpet_tick; - if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { - int lost_ticks = (offset - hpet_last) / hpet_tick; + if (hpet_use_timer) + offset = hpet_readl(HPET_T0_CMP) - hpet_tick; + else + offset = hpet_readl(HPET_COUNTER); + if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 0))) { + int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1; jiffies_64 += lost_ticks; } hpet_last = offset; diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index a685994e5c8e..7926d967be00 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -477,7 +477,7 @@ static int __init init_tsc(char* override) if (cpu_has_tsc) { unsigned long tsc_quotient; #ifdef CONFIG_HPET_TIMER - if (is_hpet_enabled()){ + if (is_hpet_enabled() && hpet_use_timer) { unsigned long result, remain; printk("Using TSC for gettimeofday\n"); tsc_quotient = calibrate_tsc_hpet(NULL); diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h index 6e20b079f1d3..16ef9f996e3f 100644 --- a/include/asm-i386/hpet.h +++ b/include/asm-i386/hpet.h @@ -92,6 +92,7 @@ extern unsigned long hpet_tick; /* hpet clks count per tick */ extern unsigned long hpet_address; /* hpet memory map physical address */ +extern int hpet_use_timer; extern int hpet_rtc_timer_init(void); extern int hpet_enable(void); -- cgit v1.2.3 From 4d24a439a6b2280357d62fb30a73350cf253bdb7 Mon Sep 17 00:00:00 2001 From: Jason Gaston Date: Sun, 1 May 2005 08:58:50 -0700 Subject: [PATCH] irq and pci_ids for Intel ICH7DH & ICH7-M DH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the Intel ICH7DH and ICH7-M DH DID's to the irq.c and pci_ids.h files. Signed-off-by:  Jason Gaston Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/pci/irq.c | 2 ++ include/linux/pci_ids.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index e07589d04f64..d6598da4b67b 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -495,6 +495,8 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route case PCI_DEVICE_ID_INTEL_ICH6_1: case PCI_DEVICE_ID_INTEL_ICH7_0: case PCI_DEVICE_ID_INTEL_ICH7_1: + case PCI_DEVICE_ID_INTEL_ICH7_30: + case PCI_DEVICE_ID_INTEL_ICH7_31: case PCI_DEVICE_ID_INTEL_ESB2_0: r->name = "PIIX/ICH"; r->get = pirq_piix_get; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 6a1897481942..5d5820a4cf10 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2415,6 +2415,8 @@ #define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9 #define PCI_DEVICE_ID_INTEL_ICH7_2 0x27c0 #define PCI_DEVICE_ID_INTEL_ICH7_3 0x27c1 +#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 +#define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd #define PCI_DEVICE_ID_INTEL_ICH7_5 0x27c4 #define PCI_DEVICE_ID_INTEL_ICH7_6 0x27c5 #define PCI_DEVICE_ID_INTEL_ICH7_7 0x27c8 -- cgit v1.2.3 From f9ba70535dc12d9eb57d466a2ecd749e16eca866 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Sun, 1 May 2005 08:58:51 -0700 Subject: [PATCH] Increase number of e820 entries hard limit from 32 to 128 The specifications that talk about E820 map doesn't have an upper limit on the number of e820 entries. But, today's kernel has a hard limit of 32. With increase in memory size, we are seeing the number of E820 entries reaching close to 32. Patch below bumps the number upto 128. The patch changes the location of EDDBUF in zero-page (as it comes after E820). As, EDDBUF is not used by boot loaders, this patch should not have any effect on bootloader-setup code interface. Patch covers both i386 and x86-64. Tested on: * grub booting bzImage * lilo booting bzImage with EDID info enabled * pxeboot of bzImage Side-effect: bss increases by ~ 2K and init.data increases by ~7.5K on all systems, due to increase in size of static arrays. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/i386/zero-page.txt | 6 +++--- arch/i386/boot/setup.S | 6 +++--- arch/x86_64/boot/setup.S | 6 +++--- arch/x86_64/kernel/head64.c | 4 +--- arch/x86_64/kernel/setup64.c | 3 ++- include/asm-i386/e820.h | 2 +- include/asm-i386/setup.h | 2 +- include/asm-x86_64/bootsetup.h | 3 ++- include/asm-x86_64/e820.h | 2 +- include/linux/edd.h | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt index 67c053a099ed..df28c7416781 100644 --- a/Documentation/i386/zero-page.txt +++ b/Documentation/i386/zero-page.txt @@ -79,6 +79,6 @@ Offset Type Description 0x22c unsigned long ramdisk_max 0x230 16 bytes trampoline 0x290 - 0x2cf EDD_MBR_SIG_BUFFER (edd.S) -0x2d0 - 0x600 E820MAP -0x600 - 0x7ff EDDBUF (edd.S) for disk signature read sector -0x600 - 0x7eb EDDBUF (edd.S) for edd data +0x2d0 - 0xd00 E820MAP +0xd00 - 0xeff EDDBUF (edd.S) for disk signature read sector +0xd00 - 0xeeb EDDBUF (edd.S) for edd data diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index a934ab32bf8e..caa1fde6904e 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -164,7 +164,7 @@ ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff trampoline: call start_of_setup .align 16 # The offset at this point is 0x240 - .space (0x7ff-0x240+1) # E820 & EDD space (ending at 0x7ff) + .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) # End of setup header ##################################################### start_of_setup: @@ -333,9 +333,9 @@ jmpe820: # sizeof(e820rec). # good820: - movb (E820NR), %al # up to 32 entries + movb (E820NR), %al # up to 128 entries cmpb $E820MAX, %al - jnl bail820 + jae bail820 incb (E820NR) movw %di, %ax diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S index 3e838be9dbe7..75d4d2ad93b3 100644 --- a/arch/x86_64/boot/setup.S +++ b/arch/x86_64/boot/setup.S @@ -160,7 +160,7 @@ ramdisk_max: .long 0xffffffff trampoline: call start_of_setup .align 16 # The offset at this point is 0x240 - .space (0x7ff-0x240+1) # E820 & EDD space (ending at 0x7ff) + .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) # End of setup header ##################################################### start_of_setup: @@ -412,9 +412,9 @@ jmpe820: # sizeof(e820rec). # good820: - movb (E820NR), %al # up to 32 entries + movb (E820NR), %al # up to 128 entries cmpb $E820MAX, %al - jnl bail820 + jae bail820 incb (E820NR) movw %di, %ax diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index 6cad46c98a23..77df2ccb08f1 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -29,8 +29,6 @@ static void __init clear_bss(void) (unsigned long) __bss_end - (unsigned long) __bss_start); } -extern char x86_boot_params[2048]; - #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ #define OLD_CL_MAGIC_ADDR 0x90020 #define OLD_CL_MAGIC 0xA33F @@ -44,7 +42,7 @@ static void __init copy_bootdata(char *real_mode_data) int new_data; char * command_line; - memcpy(x86_boot_params, real_mode_data, 2048); + memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE); new_data = *(int *) (x86_boot_params + NEW_CL_POINTER); if (!new_data) { if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) { diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index b5305b04bc40..678b7ac33b8b 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,7 @@ #include #include -char x86_boot_params[2048] __initdata = {0,}; +char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,}; cpumask_t cpu_initialized __initdata = CPU_MASK_NONE; diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h index 5c285aee7294..edf65be21a92 100644 --- a/include/asm-i386/e820.h +++ b/include/asm-i386/e820.h @@ -13,7 +13,7 @@ #define __E820_HEADER #define E820MAP 0x2d0 /* our map */ -#define E820MAX 32 /* number of entries in E820MAP */ +#define E820MAX 128 /* number of entries in E820MAP */ #define E820NR 0x1e8 /* # entries in E820MAP */ #define E820_RAM 1 diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h index 8814b54c75d4..7a32184d54bf 100644 --- a/include/asm-i386/setup.h +++ b/include/asm-i386/setup.h @@ -16,7 +16,7 @@ #define MAXMEM_PFN PFN_DOWN(MAXMEM) #define MAX_NONPAE_PFN (1 << 20) -#define PARAM_SIZE 2048 +#define PARAM_SIZE 4096 #define COMMAND_LINE_SIZE 256 #define OLD_CL_MAGIC_ADDR 0x90020 diff --git a/include/asm-x86_64/bootsetup.h b/include/asm-x86_64/bootsetup.h index b570a484dc50..b829f7b534be 100644 --- a/include/asm-x86_64/bootsetup.h +++ b/include/asm-x86_64/bootsetup.h @@ -2,7 +2,8 @@ #ifndef _X86_64_BOOTSETUP_H #define _X86_64_BOOTSETUP_H 1 -extern char x86_boot_params[2048]; +#define BOOT_PARAM_SIZE 4096 +extern char x86_boot_params[BOOT_PARAM_SIZE]; /* * This is set up by the setup-routine at boot-time diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h index 08f83a4b4f4a..8e94edf0b984 100644 --- a/include/asm-x86_64/e820.h +++ b/include/asm-x86_64/e820.h @@ -14,7 +14,7 @@ #include #define E820MAP 0x2d0 /* our map */ -#define E820MAX 32 /* number of entries in E820MAP */ +#define E820MAX 128 /* number of entries in E820MAP */ #define E820NR 0x1e8 /* # entries in E820MAP */ #define E820_RAM 1 diff --git a/include/linux/edd.h b/include/linux/edd.h index c6e6747a401d..162512b886f7 100644 --- a/include/linux/edd.h +++ b/include/linux/edd.h @@ -32,7 +32,7 @@ #define EDDNR 0x1e9 /* addr of number of edd_info structs at EDDBUF in boot_params - treat this as 1 byte */ -#define EDDBUF 0x600 /* addr of edd_info structs in boot_params */ +#define EDDBUF 0xd00 /* addr of edd_info structs in boot_params */ #define EDDMAXNR 6 /* number of edd_info structs starting at EDDBUF */ #define EDDEXTSIZE 8 /* change these if you muck with the structures */ #define EDDPARMSIZE 74 -- cgit v1.2.3 From 92eac95287d75f220a8bbef6646f51a6497c4b4c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sun, 1 May 2005 08:58:53 -0700 Subject: [PATCH] uml: fix oops related to exception table Paolo 'Blaisorblade' Giarrusso Prevent the kernel from oopsing during the extable sorting, as it can do now, because the extable is in the readonly section of the binary. Jeff says: The exception table turned RO in 2.6.11-rc3-mm1 for some reason. Moving it causes it to land in the writable data section of the binary. Paolo says: This patch fixes a oops on startup, which can be easily triggered by compiling with CONFIG_MODE_TT disabled, and STATIC_LINK either disabled or enabled. The resulting kernel will always Oops on startup, after printing this simple output: I've verified, by binary search on the BitKeeper repository (synced up as of 2.6.12-rc2), starting from the range 2.6.11-2.6.12-rc1, that this bug shows up on BitKeeper revisions in the range [@1.1994.11.168,+inf), i.e. starting from this: [PATCH] lib/sort: Replace insertion sort in exception tables Since UML does not use the exception table, it's likely that insertion sort didn't happen to write anything on the table. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/common.lds.S | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S index a3d6aab0e74d..1010153faaf9 100644 --- a/include/asm-um/common.lds.S +++ b/include/asm-um/common.lds.S @@ -8,11 +8,6 @@ _sdata = .; PROVIDE (sdata = .); - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - RODATA .unprotected : { *(.unprotected) } @@ -20,6 +15,10 @@ PROVIDE (_unprotected_end = .); . = ALIGN(4096); + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + __uml_setup_start = .; .uml.setup.init : { *(.uml.setup.init) } __uml_setup_end = .; -- cgit v1.2.3 From c45166be3cc666ce88fe623ad79276c943e74eff Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 1 May 2005 08:58:54 -0700 Subject: [PATCH] uml: support AES i586 crypto driver We want to make possible, for the user, to enable the i586 AES implementation. This requires a restructure. - Add a CONFIG_UML_X86 to notify that we are building a UML for i386. - Rename CONFIG_64_BIT to CONFIG_64BIT as is used for all other archs - Tell crypto/Kconfig that UML_X86 is as good as X86 - Tell it that it must exclude not X86_64 but 64BIT, which will give the same results. - Tell kbuild to descend down into arch/i386/crypto/ to build what's needed. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig | 1 + arch/um/Kconfig_i386 | 6 +++++- arch/um/Kconfig_x86_64 | 6 +++++- arch/um/Makefile-i386 | 2 +- arch/um/defconfig | 10 +++++----- crypto/Kconfig | 4 ++-- include/asm-um/elf.h | 2 +- include/asm-um/page.h | 2 +- include/asm-um/pgtable-3level.h | 2 +- 9 files changed, 22 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 9a23df182123..c5292181a664 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -244,6 +244,7 @@ config KERNEL_HALF_GIGS config HIGHMEM bool "Highmem support" + depends on !64BIT config KERNEL_STACK_ORDER int "Kernel stack size order" diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig_i386 index 203c242201b6..e41f3748d30f 100644 --- a/arch/um/Kconfig_i386 +++ b/arch/um/Kconfig_i386 @@ -1,4 +1,8 @@ -config 64_BIT +config UML_X86 + bool + default y + +config 64BIT bool default n diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64 index 768dc6626a8d..fd8d7e8982b1 100644 --- a/arch/um/Kconfig_x86_64 +++ b/arch/um/Kconfig_x86_64 @@ -1,4 +1,8 @@ -config 64_BIT +config UML_X86 + bool + default y + +config 64BIT bool default y diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 97b223bfa78e..f9e3c0f06541 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -1,4 +1,4 @@ -SUBARCH_CORE := arch/um/sys-i386/ +SUBARCH_CORE := arch/um/sys-i386/ arch/i386/crypto/ TOP_ADDR := $(CONFIG_TOP_ADDR) diff --git a/arch/um/defconfig b/arch/um/defconfig index fc3075c589d8..4067c3aa5b60 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc1-bk1 -# Sun Mar 20 16:53:00 2005 +# Linux kernel version: 2.6.12-rc3-skas3-v9-pre2 +# Sun Apr 24 19:46:10 2005 # CONFIG_GENERIC_HARDIRQS=y CONFIG_UML=y @@ -15,7 +15,8 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # CONFIG_MODE_TT=y CONFIG_MODE_SKAS=y -# CONFIG_64_BIT is not set +CONFIG_UML_X86=y +# CONFIG_64BIT is not set CONFIG_TOP_ADDR=0xc0000000 # CONFIG_3_LEVEL_PGTABLES is not set CONFIG_ARCH_HAS_SC_SIGNALS=y @@ -41,6 +42,7 @@ CONFIG_UML_REAL_TIME_CLOCK=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup @@ -158,7 +160,6 @@ CONFIG_UML_NET_SLIRP=y # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -412,6 +413,5 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_PT_PROXY=y -# CONFIG_GPROF is not set # CONFIG_GCOV is not set # CONFIG_SYSCALL_DEBUG is not set diff --git a/crypto/Kconfig b/crypto/Kconfig index 536754faf4d2..90d6089d60ed 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -146,7 +146,7 @@ config CRYPTO_SERPENT config CRYPTO_AES tristate "AES cipher algorithms" - depends on CRYPTO && !(X86 && !X86_64) + depends on CRYPTO && !((X86 || UML_X86) && !64BIT) help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. @@ -166,7 +166,7 @@ config CRYPTO_AES config CRYPTO_AES_586 tristate "AES cipher algorithms (i586)" - depends on CRYPTO && (X86 && !X86_64) + depends on CRYPTO && ((X86 || UML_X86) && !64BIT) help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. diff --git a/include/asm-um/elf.h b/include/asm-um/elf.h index b3a7258f9971..7908f8fe8231 100644 --- a/include/asm-um/elf.h +++ b/include/asm-um/elf.h @@ -13,7 +13,7 @@ extern long elf_aux_hwcap; #define elf_check_arch(x) (1) -#ifdef CONFIG_64_BIT +#ifdef CONFIG_64BIT #define ELF_CLASS ELFCLASS64 #else #define ELF_CLASS ELFCLASS32 diff --git a/include/asm-um/page.h b/include/asm-um/page.h index 3620a08dc9f3..102eb3df1aaf 100644 --- a/include/asm-um/page.h +++ b/include/asm-um/page.h @@ -27,7 +27,7 @@ struct page; #define clear_user_page(page, vaddr, pg) clear_page(page) #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) -#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64_BIT) +#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64BIT) typedef struct { unsigned long pte_low, pte_high; } pte_t; typedef struct { unsigned long long pmd; } pmd_t; diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h index bdbc3f97e20b..d309f3a9e6f6 100644 --- a/include/asm-um/pgtable-3level.h +++ b/include/asm-um/pgtable-3level.h @@ -145,7 +145,7 @@ static inline pmd_t pfn_pmd(pfn_t page_nr, pgprot_t pgprot) */ #define PTE_FILE_MAX_BITS 32 -#ifdef CONFIG_64_BIT +#ifdef CONFIG_64BIT #define pte_to_pgoff(p) ((p).pte >> 32) -- cgit v1.2.3 From c16993d9009b4311f0e6088af38844eabc8b5e5b Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 1 May 2005 08:58:54 -0700 Subject: [PATCH] uml: inline empty proc Cleanup: make an inline of this empty proc. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/process_kern.c | 4 ---- include/asm-um/processor-generic.h | 6 +++++- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 1d719d5b4bb9..7a943696f950 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -161,10 +161,6 @@ void *get_current(void) return(current); } -void prepare_to_copy(struct task_struct *tsk) -{ -} - int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h index 038ba6fc88b8..4d9404989b5a 100644 --- a/include/asm-um/processor-generic.h +++ b/include/asm-um/processor-generic.h @@ -89,7 +89,11 @@ extern struct task_struct *alloc_task_struct(void); extern void release_thread(struct task_struct *); extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern void dump_thread(struct pt_regs *regs, struct user *u); -extern void prepare_to_copy(struct task_struct *tsk); + +static inline void prepare_to_copy(struct task_struct *tsk) +{ +} + extern unsigned long thread_saved_pc(struct task_struct *t); -- cgit v1.2.3 From e9c527163d31da9f616e989a90429729525c5233 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 1 May 2005 08:58:54 -0700 Subject: [PATCH] uml: move va_copy conditional def GCC 2.95 uses __va_copy instead of va_copy. Handle it inside compiler.h instead of in a casual file, and avoid the risk that this breaks with a newer compiler (which it could do). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/uaccess.c | 4 ++-- include/linux/compiler-gcc2.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 7575ec489b63..f7da9d027672 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -3,6 +3,7 @@ * Licensed under the GPL */ +#include "linux/compiler.h" #include "linux/stddef.h" #include "linux/kernel.h" #include "linux/string.h" @@ -61,8 +62,7 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) void *arg; int *res; - /* Some old gccs recognize __va_copy, but not va_copy */ - __va_copy(args, *(va_list *)arg_ptr); + va_copy(args, *(va_list *)arg_ptr); addr = va_arg(args, unsigned long); len = va_arg(args, int); is_write = va_arg(args, int); diff --git a/include/linux/compiler-gcc2.h b/include/linux/compiler-gcc2.h index 5a359153ffd9..ebed17660c5f 100644 --- a/include/linux/compiler-gcc2.h +++ b/include/linux/compiler-gcc2.h @@ -22,3 +22,8 @@ # define __attribute_pure__ __attribute__((pure)) # define __attribute_const__ __attribute__((__const__)) #endif + +/* GCC 2.95.x/2.96 recognize __va_copy, but not va_copy. Actually later GCC's + * define both va_copy and __va_copy, but the latter may go away, so limit this + * to this header */ +#define va_copy __va_copy -- cgit v1.2.3 From acef2e55d2a1b59bb5610cacc546c1d1b5de2dc9 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 1 May 2005 08:58:56 -0700 Subject: [PATCH] uml: commentary about forking flag Add some commentary about UML internals, for a strange trick. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/processor-generic.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h index 4d9404989b5a..b953b1ad3b02 100644 --- a/include/asm-um/processor-generic.h +++ b/include/asm-um/processor-generic.h @@ -17,6 +17,10 @@ struct task_struct; struct mm_struct; struct thread_struct { + /* This flag is set to 1 before calling do_fork (and analyzed in + * copy_thread) to mark that we are begin called from userspace (fork / + * vfork / clone), and reset to 0 after. It is left to 0 when called + * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */ int forking; int nsyscalls; struct pt_regs regs; -- cgit v1.2.3 From 0b642ede47969d4180b0922d982777fe64379228 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Sun, 1 May 2005 08:58:58 -0700 Subject: [PATCH] s390: default storage key Provide an easy way to define a non-zero storage key at compile time. This is useful for debugging purposes. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/s390_ksyms.c | 1 - arch/s390/kernel/setup.c | 20 ++++++++++++++++---- drivers/s390/cio/cio.c | 4 ++-- drivers/s390/cio/device_ops.c | 6 +++--- drivers/s390/cio/qdio.h | 6 ++++-- include/asm-s390/page.h | 2 ++ include/asm-s390/processor.h | 2 +- include/asm-s390/ptrace.h | 16 +++++++++++++--- 8 files changed, 41 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 11fd6d556d8f..bee654abb6d3 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -34,7 +34,6 @@ EXPORT_SYMBOL(__clear_user_asm); EXPORT_SYMBOL(__strncpy_from_user_asm); EXPORT_SYMBOL(__strnlen_user_asm); EXPORT_SYMBOL(diag10); -EXPORT_SYMBOL(default_storage_key); /* * semaphore ops diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index f0679be4f96f..df83215beac3 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include /* * Machine setup.. @@ -53,7 +55,6 @@ unsigned int console_devno = -1; unsigned int console_irq = -1; unsigned long memory_size = 0; unsigned long machine_flags = 0; -unsigned int default_storage_key = 0; struct { unsigned long addr, size, type; } memory_chunk[MEMORY_CHUNKS] = { { 0 } }; @@ -402,7 +403,7 @@ setup_lowcore(void) lc = (struct _lowcore *) __alloc_bootmem(lc_pages * PAGE_SIZE, lc_pages * PAGE_SIZE, 0); memset(lc, 0, lc_pages * PAGE_SIZE); - lc->restart_psw.mask = PSW_BASE_BITS; + lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) restart_int_handler; lc->external_new_psw.mask = PSW_KERNEL_BITS; @@ -470,7 +471,7 @@ static void __init setup_memory(void) { unsigned long bootmap_size; - unsigned long start_pfn, end_pfn; + unsigned long start_pfn, end_pfn, init_pfn; unsigned long last_rw_end; int i; @@ -481,6 +482,10 @@ setup_memory(void) start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT; end_pfn = max_pfn = memory_end >> PAGE_SHIFT; + /* Initialize storage key for kernel pages */ + for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++) + page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); + /* * Initialize the boot-time allocator (with low memory only): */ @@ -491,7 +496,7 @@ setup_memory(void) */ last_rw_end = start_pfn; - for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) { + for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { unsigned long start_chunk, end_chunk; if (memory_chunk[i].type != CHUNK_READ_WRITE) @@ -505,6 +510,11 @@ setup_memory(void) if (end_chunk > end_pfn) end_chunk = end_pfn; if (start_chunk < end_chunk) { + /* Initialize storage key for RAM pages */ + for (init_pfn = start_chunk ; init_pfn < end_chunk; + init_pfn++) + page_set_storage_key(init_pfn << PAGE_SHIFT, + PAGE_DEFAULT_KEY); free_bootmem(start_chunk << PAGE_SHIFT, (end_chunk - start_chunk) << PAGE_SHIFT); if (last_rw_end < start_chunk) @@ -513,6 +523,8 @@ setup_memory(void) } } + psw_set_key(PAGE_DEFAULT_KEY); + if (last_rw_end < end_pfn - 1) add_memory_hole(last_rw_end, end_pfn - 1); diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 99ce5a567982..1d9b3f18d8de 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.131 $ + * $Revision: 1.133 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -228,7 +228,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ int cio_start (struct subchannel *sch, struct ccw1 *cpa, __u8 lpm) { - return cio_start_key(sch, cpa, lpm, default_storage_key); + return cio_start_key(sch, cpa, lpm, PAGE_DEFAULT_KEY); } /* diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 11e260e0b9c9..02d01a0de16c 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.55 $ + * $Revision: 1.56 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -128,7 +128,7 @@ ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, unsigned long intparm, __u8 lpm, unsigned long flags) { return ccw_device_start_key(cdev, cpa, intparm, lpm, - default_storage_key, flags); + PAGE_DEFAULT_KEY, flags); } int @@ -137,7 +137,7 @@ ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, int expires) { return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, - default_storage_key, flags, + PAGE_DEFAULT_KEY, flags, expires); } diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 9ad14db24143..b6daadac4e8b 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -1,7 +1,9 @@ #ifndef _CIO_QDIO_H #define _CIO_QDIO_H -#define VERSION_CIO_QDIO_H "$Revision: 1.26 $" +#include + +#define VERSION_CIO_QDIO_H "$Revision: 1.32 $" #ifdef CONFIG_QDIO_DEBUG #define QDIO_VERBOSE_LEVEL 9 @@ -42,7 +44,7 @@ #define QDIO_Q_LAPS 5 -#define QDIO_STORAGE_KEY 0 +#define QDIO_STORAGE_KEY PAGE_DEFAULT_KEY #define L2_CACHELINE_SIZE 256 #define INDICATORS_PER_CACHELINE (L2_CACHELINE_SIZE/sizeof(__u32)) diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h index 614e2a93c703..2be287b9df88 100644 --- a/include/asm-s390/page.h +++ b/include/asm-s390/page.h @@ -16,6 +16,8 @@ #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_DEFAULT_ACC 0 +#define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index 88c272ca48bf..fb46e9090b50 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h @@ -245,7 +245,7 @@ static inline void enabled_wait(void) psw_t wait_psw; wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT | - PSW_MASK_MCHECK | PSW_MASK_WAIT; + PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY; #ifndef __s390x__ asm volatile ( " basr %0,0\n" diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index 1dc80666e97e..4eff8f2e3bf1 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h @@ -185,6 +185,7 @@ #include #include #include +#include typedef union { @@ -235,6 +236,7 @@ typedef struct #define PSW_ADDR_INSN 0x7FFFFFFFUL #define PSW_BASE_BITS 0x00080000UL +#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 20) #define PSW_ASC_PRIMARY 0x00000000UL #define PSW_ASC_ACCREG 0x00004000UL @@ -260,6 +262,7 @@ typedef struct #define PSW_BASE_BITS 0x0000000180000000UL #define PSW_BASE32_BITS 0x0000000080000000UL +#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 52) #define PSW_ASC_PRIMARY 0x0000000000000000UL #define PSW_ASC_ACCREG 0x0000400000000000UL @@ -268,14 +271,15 @@ typedef struct #define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ - PSW_MASK_PSTATE) + PSW_MASK_PSTATE | PSW_DEFAULT_KEY) #endif /* __s390x__ */ -#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY) +#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \ + PSW_DEFAULT_KEY) #define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ - PSW_MASK_PSTATE) + PSW_MASK_PSTATE | PSW_DEFAULT_KEY) /* This macro merges a NEW PSW mask specified by the user into the currently active PSW mask CURRENT, modifying only those @@ -470,6 +474,12 @@ struct user_regs_struct extern void show_regs(struct pt_regs * regs); #endif +static inline void +psw_set_key(unsigned int key) +{ + asm volatile ( "spka 0(%0)" : : "d" (key) ); +} + #endif /* __ASSEMBLY__ */ #endif /* _S390_PTRACE_H */ -- cgit v1.2.3 From e8f0641ef74eaa71ed9aa9d19c4b741c2143d752 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Sun, 1 May 2005 08:58:58 -0700 Subject: [PATCH] s390: allow longer debug feature names The current limitation of 16 characters of the debug feature names turned out to be insufficient. Increase it to 64 characters. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h index 28ef2354b1b2..6bbcdea42a86 100644 --- a/include/asm-s390/debug.h +++ b/include/asm-s390/debug.h @@ -43,7 +43,7 @@ struct __debug_entry{ #define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */ #define DEBUG_FLUSH_ALL -1 /* parameter to flush all areas */ #define DEBUG_MAX_VIEWS 10 /* max number of views in proc fs */ -#define DEBUG_MAX_PROCF_LEN 16 /* max length for a proc file name */ +#define DEBUG_MAX_PROCF_LEN 64 /* max length for a proc file name */ #define DEBUG_DEFAULT_LEVEL 3 /* initial debug level */ #define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */ -- cgit v1.2.3 From 4beb37097b20b61054b15c56848e4ffcef093819 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Sun, 1 May 2005 08:58:59 -0700 Subject: [PATCH] s390: remove ioctl32 from dasdcmb The ioctl32_conversion routines will be deprecated: Remove them from dasd_cmb and handle the three cmb ioctls like all other dasd ioctls. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/compat_ioctl.c | 7 ++++++- drivers/s390/block/dasd_cmb.c | 19 ++----------------- include/asm-s390/cmb.h | 2 +- 3 files changed, 9 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c index 96571ff7115d..03d03c6d3cbb 100644 --- a/arch/s390/kernel/compat_ioctl.c +++ b/arch/s390/kernel/compat_ioctl.c @@ -16,6 +16,7 @@ #define CODE #include "../../../fs/compat_ioctl.c" #include +#include #include static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, @@ -58,7 +59,11 @@ COMPATIBLE_IOCTL(BIODASDPRRD) COMPATIBLE_IOCTL(BIODASDPSRD) COMPATIBLE_IOCTL(BIODASDGATTR) COMPATIBLE_IOCTL(BIODASDSATTR) - +#if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE) +COMPATIBLE_IOCTL(BIODASDCMFENABLE) +COMPATIBLE_IOCTL(BIODASDCMFDISABLE) +COMPATIBLE_IOCTL(BIODASDREADALLCMB) +#endif #endif #if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE) diff --git a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c index ed1ab474c0c6..4f365bff275c 100644 --- a/drivers/s390/block/dasd_cmb.c +++ b/drivers/s390/block/dasd_cmb.c @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.6 $) + * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.9 $) * * Linux on zSeries Channel Measurement Facility support * (dasd device driver interface) @@ -23,7 +23,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include -#include #include #include #include @@ -84,27 +83,13 @@ dasd_ioctl_readall_cmb(struct block_device *bdev, int no, long args) static inline int ioctl_reg(unsigned int no, dasd_ioctl_fn_t handler) { - int ret; - ret = dasd_ioctl_no_register(THIS_MODULE, no, handler); -#ifdef CONFIG_COMPAT - if (ret) - return ret; - - ret = register_ioctl32_conversion(no, NULL); - if (ret) - dasd_ioctl_no_unregister(THIS_MODULE, no, handler); -#endif - return ret; + return dasd_ioctl_no_register(THIS_MODULE, no, handler); } static inline void ioctl_unreg(unsigned int no, dasd_ioctl_fn_t handler) { dasd_ioctl_no_unregister(THIS_MODULE, no, handler); -#ifdef CONFIG_COMPAT - unregister_ioctl32_conversion(no); -#endif - } static void diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h index 1bfe2bd630b5..dae1dd4fb937 100644 --- a/include/asm-s390/cmb.h +++ b/include/asm-s390/cmb.h @@ -52,7 +52,7 @@ struct cmbdata { #define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata) #ifdef __KERNEL__ - +struct ccw_device; /** * enable_cmf() - switch on the channel measurement for a specific device * @cdev: The ccw device to be enabled -- cgit v1.2.3 From e43379f10b42194b8a6e1de342cfb44463c0f6da Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Sun, 1 May 2005 08:59:00 -0700 Subject: [PATCH] nice and rt-prio rlimits Add a pair of rlimits for allowing non-root tasks to raise nice and rt priorities. Defaults to traditional behavior. Originally written by Chris Wright. The patch implements a simple rlimit ceiling for the RT (and nice) priorities a task can set. The rlimit defaults to 0, meaning no change in behavior by default. A value of 50 means RT priority levels 1-50 are allowed. A value of 100 means all 99 privilege levels from 1 to 99 are allowed. CAP_SYS_NICE is blanket permission. (akpm: see http://www.uwsg.iu.edu/hypermail/linux/kernel/0503.1/1921.html for tips on integrating this with PAM). Signed-off-by: Matt Mackall Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-generic/resource.h | 7 ++++++- include/linux/sched.h | 1 + kernel/sched.c | 25 +++++++++++++++++++------ kernel/sys.c | 2 +- 4 files changed, 27 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h index b1fcda9eac23..cfe3692b23e5 100644 --- a/include/asm-generic/resource.h +++ b/include/asm-generic/resource.h @@ -41,8 +41,11 @@ #define RLIMIT_LOCKS 10 /* maximum file locks held */ #define RLIMIT_SIGPENDING 11 /* max number of pending signals */ #define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */ +#define RLIMIT_NICE 13 /* max nice prio allowed to raise to + 0-39 for nice level 19 .. -20 */ +#define RLIMIT_RTPRIO 14 /* maximum realtime priority */ -#define RLIM_NLIMITS 13 +#define RLIM_NLIMITS 15 /* * SuS says limits have to be unsigned. @@ -81,6 +84,8 @@ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \ [RLIMIT_SIGPENDING] = { 0, 0 }, \ [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \ + [RLIMIT_NICE] = { 0, 0 }, \ + [RLIMIT_RTPRIO] = { 0, 0 }, \ } #endif /* __KERNEL__ */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 1cced971232c..8960f99ea128 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -845,6 +845,7 @@ extern void sched_idle_next(void); extern void set_user_nice(task_t *p, long nice); extern int task_prio(const task_t *p); extern int task_nice(const task_t *p); +extern int can_nice(const task_t *p, const int nice); extern int task_curr(const task_t *p); extern int idle_cpu(int cpu); extern int sched_setscheduler(struct task_struct *, int, struct sched_param *); diff --git a/kernel/sched.c b/kernel/sched.c index 9bb7489ee645..5dadcc6df7dd 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3223,6 +3223,19 @@ out_unlock: EXPORT_SYMBOL(set_user_nice); +/* + * can_nice - check if a task can reduce its nice value + * @p: task + * @nice: nice value + */ +int can_nice(const task_t *p, const int nice) +{ + /* convert nice value [19,-20] to rlimit style value [0,39] */ + int nice_rlim = 19 - nice; + return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur || + capable(CAP_SYS_NICE)); +} + #ifdef __ARCH_WANT_SYS_NICE /* @@ -3242,12 +3255,8 @@ asmlinkage long sys_nice(int increment) * We don't have to worry. Conceptually one call occurs first * and we have a single winner. */ - if (increment < 0) { - if (!capable(CAP_SYS_NICE)) - return -EPERM; - if (increment < -40) - increment = -40; - } + if (increment < -40) + increment = -40; if (increment > 40) increment = 40; @@ -3257,6 +3266,9 @@ asmlinkage long sys_nice(int increment) if (nice > 19) nice = 19; + if (increment < 0 && !can_nice(current, nice)) + return -EPERM; + retval = security_task_setnice(current, nice); if (retval) return retval; @@ -3372,6 +3384,7 @@ recheck: return -EINVAL; if ((policy == SCHED_FIFO || policy == SCHED_RR) && + param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur && !capable(CAP_SYS_NICE)) return -EPERM; if ((current->euid != p->euid) && (current->euid != p->uid) && diff --git a/kernel/sys.c b/kernel/sys.c index df2ddcc6863b..7f43d6e62c7a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -227,7 +227,7 @@ static int set_one_prio(struct task_struct *p, int niceval, int error) error = -EPERM; goto out; } - if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) { + if (niceval < task_nice(p) && !can_nice(p, niceval)) { error = -EACCES; goto out; } -- cgit v1.2.3 From c8538a7aa5527d02c7191ac5da124efadf6a2827 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Sun, 1 May 2005 08:59:01 -0700 Subject: [PATCH] remove all kernel BUGs This patch eliminates all kernel BUGs, trims about 35k off the typical kernel, and makes the system slightly faster. Signed-off-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/bug.h | 3 +++ include/asm-arm/bug.h | 3 +++ include/asm-arm26/bug.h | 3 +++ include/asm-frv/bug.h | 2 ++ include/asm-generic/bug.h | 19 +++++++++++++++++++ include/asm-i386/bug.h | 5 +++-- include/asm-ia64/bug.h | 5 ++++- include/asm-m68k/bug.h | 3 +++ include/asm-mips/bug.h | 4 +++- include/asm-parisc/bug.h | 2 ++ include/asm-ppc/bug.h | 3 +++ include/asm-ppc64/bug.h | 7 +++++-- include/asm-s390/bug.h | 3 +++ include/asm-sh/bug.h | 3 +++ include/asm-sparc/bug.h | 3 +++ include/asm-sparc64/bug.h | 3 +++ include/asm-v850/bug.h | 3 +++ include/asm-x86_64/bug.h | 4 +++- init/Kconfig | 10 ++++++++++ lib/Kconfig.debug | 1 + 20 files changed, 82 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/asm-alpha/bug.h b/include/asm-alpha/bug.h index ae1e0a5fa492..39a3e2a5017d 100644 --- a/include/asm-alpha/bug.h +++ b/include/asm-alpha/bug.h @@ -1,6 +1,7 @@ #ifndef _ALPHA_BUG_H #define _ALPHA_BUG_H +#ifdef CONFIG_BUG #include /* ??? Would be nice to use .gprel32 here, but we can't be sure that the @@ -10,6 +11,8 @@ : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__)) #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-arm/bug.h b/include/asm-arm/bug.h index 5e91b90a8181..24d11672eb60 100644 --- a/include/asm-arm/bug.h +++ b/include/asm-arm/bug.h @@ -3,6 +3,7 @@ #include +#ifdef CONFIG_BUG #ifdef CONFIG_DEBUG_BUGVERBOSE extern volatile void __bug(const char *file, int line, void *data); @@ -17,6 +18,8 @@ extern volatile void __bug(const char *file, int line, void *data); #endif #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-arm26/bug.h b/include/asm-arm26/bug.h index 920b70533368..7177c7399967 100644 --- a/include/asm-arm26/bug.h +++ b/include/asm-arm26/bug.h @@ -3,6 +3,7 @@ #include +#ifdef CONFIG_BUG #ifdef CONFIG_DEBUG_BUGVERBOSE extern volatile void __bug(const char *file, int line, void *data); /* give file/line information */ @@ -12,6 +13,8 @@ extern volatile void __bug(const char *file, int line, void *data); #endif #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-frv/bug.h b/include/asm-frv/bug.h index 011860b28818..074c0d5770eb 100644 --- a/include/asm-frv/bug.h +++ b/include/asm-frv/bug.h @@ -13,6 +13,7 @@ #include +#ifdef CONFIG_BUG /* * Tell the user there is some problem. */ @@ -45,6 +46,7 @@ do { \ #define HAVE_ARCH_KGDB_BAD_PAGE #define kgdb_bad_page(page) do { kgdb_raise(SIGABRT); } while(0) #endif +#endif #include diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index e5913c3b715a..6e5aaaa9a2fb 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -4,6 +4,7 @@ #include #include +#ifdef CONFIG_BUG #ifndef HAVE_ARCH_BUG #define BUG() do { \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ @@ -31,4 +32,22 @@ } while (0) #endif +#else /* !CONFIG_BUG */ +#ifndef HAVE_ARCH_BUG +#define BUG() +#endif + +#ifndef HAVE_ARCH_PAGE_BUG +#define PAGE_BUG(page) do { if (page) ; } while (0) +#endif + +#ifndef HAVE_ARCH_BUG_ON +#define BUG_ON(condition) do { if (condition) ; } while(0) +#endif + +#ifndef HAVE_ARCH_WARN_ON +#define WARN_ON(condition) do { if (condition) ; } while(0) +#endif +#endif + #endif diff --git a/include/asm-i386/bug.h b/include/asm-i386/bug.h index 706eb511c330..8f79de19eb94 100644 --- a/include/asm-i386/bug.h +++ b/include/asm-i386/bug.h @@ -9,6 +9,8 @@ * undefined" opcode for parsing in the trap handler. */ +#ifdef CONFIG_BUG +#define HAVE_ARCH_BUG #ifdef CONFIG_DEBUG_BUGVERBOSE #define BUG() \ __asm__ __volatile__( "ud2\n" \ @@ -18,8 +20,7 @@ #else #define BUG() __asm__ __volatile__("ud2\n") #endif +#endif -#define HAVE_ARCH_BUG #include - #endif diff --git a/include/asm-ia64/bug.h b/include/asm-ia64/bug.h index 2c0cd51e8856..3aa0a0a5474b 100644 --- a/include/asm-ia64/bug.h +++ b/include/asm-ia64/bug.h @@ -1,6 +1,7 @@ #ifndef _ASM_IA64_BUG_H #define _ASM_IA64_BUG_H +#ifdef CONFIG_BUG #if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) # define ia64_abort() __builtin_trap() #else @@ -8,8 +9,10 @@ #endif #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0) -/* should this BUG should be made generic? */ +/* should this BUG be made generic? */ #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-m68k/bug.h b/include/asm-m68k/bug.h index 3e1d2266fa69..072ce274d537 100644 --- a/include/asm-m68k/bug.h +++ b/include/asm-m68k/bug.h @@ -3,6 +3,7 @@ #include +#ifdef CONFIG_BUG #ifdef CONFIG_DEBUG_BUGVERBOSE #ifndef CONFIG_SUN3 #define BUG() do { \ @@ -22,6 +23,8 @@ #endif #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h index eb94bb96cfbc..3f594b440abc 100644 --- a/include/asm-mips/bug.h +++ b/include/asm-mips/bug.h @@ -3,12 +3,14 @@ #include +#ifdef CONFIG_BUG +#define HAVE_ARCH_BUG #define BUG() \ do { \ __asm__ __volatile__("break %0" : : "i" (BRK_BUG)); \ } while (0) +#endif -#define HAVE_ARCH_BUG #include #endif diff --git a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h index e72f6e2b4b9f..695588da41f8 100644 --- a/include/asm-parisc/bug.h +++ b/include/asm-parisc/bug.h @@ -1,12 +1,14 @@ #ifndef _PARISC_BUG_H #define _PARISC_BUG_H +#ifdef CONFIG_BUG #define HAVE_ARCH_BUG #define BUG() do { \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ dump_stack(); \ panic("BUG!"); \ } while (0) +#endif #include #endif diff --git a/include/asm-ppc/bug.h b/include/asm-ppc/bug.h index e99c6cb9d618..8b34fd682b0d 100644 --- a/include/asm-ppc/bug.h +++ b/include/asm-ppc/bug.h @@ -14,6 +14,7 @@ struct bug_entry { */ #define BUG_WARNING_TRAP 0x1000000 +#ifdef CONFIG_BUG #define BUG() do { \ __asm__ __volatile__( \ "1: twi 31,0,0\n" \ @@ -50,6 +51,8 @@ struct bug_entry { #define HAVE_ARCH_BUG #define HAVE_ARCH_BUG_ON #define HAVE_ARCH_WARN_ON +#endif + #include #endif diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h index db31dd22233c..169868fa307d 100644 --- a/include/asm-ppc64/bug.h +++ b/include/asm-ppc64/bug.h @@ -26,6 +26,8 @@ struct bug_entry *find_bug(unsigned long bugaddr); */ #define BUG_WARNING_TRAP 0x1000000 +#ifdef CONFIG_BUG + #define BUG() do { \ __asm__ __volatile__( \ "1: twi 31,0,0\n" \ @@ -55,11 +57,12 @@ struct bug_entry *find_bug(unsigned long bugaddr); "i" (__FILE__), "i" (__FUNCTION__)); \ } while (0) -#endif - #define HAVE_ARCH_BUG #define HAVE_ARCH_BUG_ON #define HAVE_ARCH_WARN_ON +#endif +#endif + #include #endif diff --git a/include/asm-s390/bug.h b/include/asm-s390/bug.h index 2b8d6d4dffcf..a2e7430aafa6 100644 --- a/include/asm-s390/bug.h +++ b/include/asm-s390/bug.h @@ -3,12 +3,15 @@ #include +#ifdef CONFIG_BUG #define BUG() do { \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ __asm__ __volatile__(".long 0"); \ } while (0) #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h index 70172217140f..70508a360cd6 100644 --- a/include/asm-sh/bug.h +++ b/include/asm-sh/bug.h @@ -3,6 +3,7 @@ #include +#ifdef CONFIG_BUG /* * Tell the user there is some problem. */ @@ -12,6 +13,8 @@ } while (0) #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-sparc/bug.h b/include/asm-sparc/bug.h index 0d30a67d87a3..04151208189f 100644 --- a/include/asm-sparc/bug.h +++ b/include/asm-sparc/bug.h @@ -1,6 +1,7 @@ #ifndef _SPARC_BUG_H #define _SPARC_BUG_H +#ifdef CONFIG_BUG /* Only use the inline asm until a gcc release that can handle __builtin_trap * -rob 2003-06-25 * @@ -26,6 +27,8 @@ extern void do_BUG(const char *file, int line); #endif #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h index 25c5b1dfe378..516bb27f3fc4 100644 --- a/include/asm-sparc64/bug.h +++ b/include/asm-sparc64/bug.h @@ -1,6 +1,7 @@ #ifndef _SPARC64_BUG_H #define _SPARC64_BUG_H +#ifdef CONFIG_BUG #include #ifdef CONFIG_DEBUG_BUGVERBOSE @@ -14,6 +15,8 @@ extern void do_BUG(const char *file, int line); #endif #define HAVE_ARCH_BUG +#endif + #include #endif diff --git a/include/asm-v850/bug.h b/include/asm-v850/bug.h index c778916bf7f2..b0ed2d35f3e8 100644 --- a/include/asm-v850/bug.h +++ b/include/asm-v850/bug.h @@ -14,9 +14,12 @@ #ifndef __V850_BUG_H__ #define __V850_BUG_H__ +#ifdef CONFIG_BUG extern void __bug (void) __attribute__ ((noreturn)); #define BUG() __bug() #define HAVE_ARCH_BUG +#endif + #include #endif /* __V850_BUG_H__ */ diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h index 19aed6e78fec..bdbf66eab6ee 100644 --- a/include/asm-x86_64/bug.h +++ b/include/asm-x86_64/bug.h @@ -15,11 +15,13 @@ struct bug_frame { unsigned short line; } __attribute__((packed)); +#ifdef CONFIG_BUG #define HAVE_ARCH_BUG #define BUG() \ asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \ "i"(__LINE__), "i" (__stringify(__FILE__))) void out_of_line_bug(void); -#include +#endif +#include #endif diff --git a/init/Kconfig b/init/Kconfig index abe2682a6ca6..42dca393b94e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -275,6 +275,16 @@ config KALLSYMS_EXTRA_PASS reported. KALLSYMS_EXTRA_PASS is only a temporary workaround while you wait for kallsyms to be fixed. +config BUG + bool "BUG() support" if EMBEDDED + default y + help + Disabling this option eliminates support for BUG and WARN, reducing + the size of your kernel image and potentially quietly ignoring + numerous fatal conditions. You should only consider disabling this + option for embedded systems with no facilities for reporting errors. + Just say Y. + config BASE_FULL default y bool "Enable full-sized data structures for core" if EMBEDDED diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 426a0cf7b11c..ac23847ce0e3 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -108,6 +108,7 @@ config DEBUG_HIGHMEM config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED + depends on BUG depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64) || FRV default !EMBEDDED help -- cgit v1.2.3 From cd7619d6bf36564cf54ff7218ef54e558a741913 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Sun, 1 May 2005 08:59:01 -0700 Subject: [PATCH] Exterminate PAGE_BUG Remove PAGE_BUG - repalce it with BUG and BUG_ON. Signed-off-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm26/mm/small_page.c | 6 ++---- fs/afs/file.c | 3 +-- fs/buffer.c | 3 +-- fs/jffs2/file.c | 3 +-- fs/udf/file.c | 6 ++---- fs/udf/inode.c | 4 ++-- include/asm-cris/page.h | 4 ---- include/asm-generic/bug.h | 11 ----------- include/asm-sh64/bug.h | 4 ---- mm/filemap.c | 3 +-- 10 files changed, 10 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/arch/arm26/mm/small_page.c b/arch/arm26/mm/small_page.c index 77be86cca789..30447106c25f 100644 --- a/arch/arm26/mm/small_page.c +++ b/arch/arm26/mm/small_page.c @@ -92,8 +92,7 @@ static unsigned long __get_small_page(int priority, struct order *order) page = list_entry(order->queue.next, struct page, lru); again: #ifdef PEDANTIC - if (USED_MAP(page) & ~order->all_used) - PAGE_BUG(page); + BUG_ON(USED_MAP(page) & ~order->all_used); #endif offset = ffz(USED_MAP(page)); SET_USED(page, offset); @@ -141,8 +140,7 @@ static void __free_small_page(unsigned long spage, struct order *order) goto non_small; #ifdef PEDANTIC - if (USED_MAP(page) & ~order->all_used) - PAGE_BUG(page); + BUG_ON(USED_MAP(page) & ~order->all_used); #endif spage = spage >> order->shift; diff --git a/fs/afs/file.c b/fs/afs/file.c index 6b6bb7c8abf6..23c125128024 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -131,8 +131,7 @@ static int afs_file_readpage(struct file *file, struct page *page) vnode = AFS_FS_I(inode); - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); ret = -ESTALE; if (vnode->flags & AFS_VNODE_DELETED) diff --git a/fs/buffer.c b/fs/buffer.c index 188365c79204..792cbacbbf41 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2078,8 +2078,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block) int nr, i; int fully_mapped = 1; - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); blocksize = 1 << inode->i_blkbits; if (!page_has_buffers(page)) create_empty_buffers(page, blocksize, 0); diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 0c607c1388f4..771a554701d6 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -79,8 +79,7 @@ static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) D2(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT)); - if (!PageLocked(pg)) - PAGE_BUG(pg); + BUG_ON(!PageLocked(pg)); pg_buf = kmap(pg); /* FIXME: Can kmap fail? */ diff --git a/fs/udf/file.c b/fs/udf/file.c index 2faa4172b9f7..bb40d63f328f 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -49,8 +49,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page) struct inode *inode = page->mapping->host; char *kaddr; - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); kaddr = kmap(page); memset(kaddr, 0, PAGE_CACHE_SIZE); @@ -67,8 +66,7 @@ static int udf_adinicb_writepage(struct page *page, struct writeback_control *wb struct inode *inode = page->mapping->host; char *kaddr; - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); kaddr = kmap(page); memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size); diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 0506e1173784..3d68de39fad6 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -167,8 +167,8 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) } page = grab_cache_page(inode->i_mapping, 0); - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); + if (!PageUptodate(page)) { kaddr = kmap(page); diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h index ddd8915e41e6..c767da1ef8f5 100644 --- a/include/asm-cris/page.h +++ b/include/asm-cris/page.h @@ -77,10 +77,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ } while (0) -#define PAGE_BUG(page) do { \ - BUG(); \ -} while (0) - /* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) { diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 6e5aaaa9a2fb..400c2b41896e 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -12,13 +12,6 @@ } while (0) #endif -#ifndef HAVE_ARCH_PAGE_BUG -#define PAGE_BUG(page) do { \ - printk("page BUG for page at %p\n", page); \ - BUG(); \ -} while (0) -#endif - #ifndef HAVE_ARCH_BUG_ON #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) #endif @@ -37,10 +30,6 @@ #define BUG() #endif -#ifndef HAVE_ARCH_PAGE_BUG -#define PAGE_BUG(page) do { if (page) ; } while (0) -#endif - #ifndef HAVE_ARCH_BUG_ON #define BUG_ON(condition) do { if (condition) ; } while(0) #endif diff --git a/include/asm-sh64/bug.h b/include/asm-sh64/bug.h index 3acd54d59566..5d659ec28e10 100644 --- a/include/asm-sh64/bug.h +++ b/include/asm-sh64/bug.h @@ -17,10 +17,6 @@ BUG(); \ } while(0) -#define PAGE_BUG(page) do { \ - BUG(); \ -} while (0) - #define WARN_ON(condition) do { \ if (unlikely((condition)!=0)) { \ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \ diff --git a/mm/filemap.c b/mm/filemap.c index ee79b5d3439f..c085af2332d8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -123,8 +123,7 @@ void remove_from_page_cache(struct page *page) { struct address_space *mapping = page->mapping; - if (unlikely(!PageLocked(page))) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); write_lock_irq(&mapping->tree_lock); __remove_from_page_cache(page); -- cgit v1.2.3 From d59745ce3e7aa13856bca16d3bcbb95041775ff6 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Sun, 1 May 2005 08:59:02 -0700 Subject: [PATCH] clean up kernel messages Arrange for all kernel printks to be no-ops. Only available if CONFIG_EMBEDDED. This patch saves about 375k on my laptop config and nearly 100k on minimal configs. Signed-off-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/head.S | 2 ++ include/linux/kernel.h | 9 +++++++++ init/Kconfig | 11 +++++++++++ kernel/printk.c | 27 +++++++++++++++++++++------ 4 files changed, 43 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index d273fd746192..e966fc8c44c4 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -380,6 +380,7 @@ rp_sidt: ALIGN ignore_int: cld +#ifdef CONFIG_PRINTK pushl %eax pushl %ecx pushl %edx @@ -400,6 +401,7 @@ ignore_int: popl %edx popl %ecx popl %eax +#endif iret /* diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 7c1cba4a5278..e25b97062ce1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -115,10 +115,19 @@ extern int __kernel_text_address(unsigned long addr); extern int kernel_text_address(unsigned long addr); extern int session_of_pgrp(int pgrp); +#ifdef CONFIG_PRINTK asmlinkage int vprintk(const char *fmt, va_list args) __attribute__ ((format (printf, 1, 0))); asmlinkage int printk(const char * fmt, ...) __attribute__ ((format (printf, 1, 2))); +#else +static inline int vprintk(const char *s, va_list args) + __attribute__ ((format (printf, 1, 0))); +static inline int vprintk(const char *s, va_list args) { return 0; } +static inline int printk(const char *s, ...) + __attribute__ ((format (printf, 1, 2))); +static inline int printk(const char *s, ...) { return 0; } +#endif unsigned long int_sqrt(unsigned long); diff --git a/init/Kconfig b/init/Kconfig index 42dca393b94e..40d286d1d118 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -275,6 +275,17 @@ config KALLSYMS_EXTRA_PASS reported. KALLSYMS_EXTRA_PASS is only a temporary workaround while you wait for kallsyms to be fixed. + +config PRINTK + default y + bool "Enable support for printk" if EMBEDDED + help + This option enables normal printk support. Removing it + eliminates most of the message strings from the kernel image + and makes the kernel more or less silent. As this makes it + very difficult to diagnose system problems, saying N here is + strongly discouraged. + config BUG bool "BUG() support" if EMBEDDED default y diff --git a/kernel/printk.c b/kernel/printk.c index 1498689548d1..290a07ce2c8a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -85,10 +85,6 @@ static int console_locked; */ static DEFINE_SPINLOCK(logbuf_lock); -static char __log_buf[__LOG_BUF_LEN]; -static char *log_buf = __log_buf; -static int log_buf_len = __LOG_BUF_LEN; - #define LOG_BUF_MASK (log_buf_len-1) #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) @@ -99,7 +95,6 @@ static int log_buf_len = __LOG_BUF_LEN; static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */ static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */ static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */ -static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */ /* * Array of consoles built from command line options (console=) @@ -120,6 +115,13 @@ static int preferred_console = -1; /* Flag: console code may call schedule() */ static int console_may_schedule; +#ifdef CONFIG_PRINTK + +static char __log_buf[__LOG_BUF_LEN]; +static char *log_buf = __log_buf; +static int log_buf_len = __LOG_BUF_LEN; +static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */ + /* * Setup a list of consoles. Called from init/main.c */ @@ -535,6 +537,7 @@ __setup("time", printk_time_setup); * then changes console_loglevel may break. This is because console_loglevel * is inspected when the actual printing occurs. */ + asmlinkage int printk(const char *fmt, ...) { va_list args; @@ -655,6 +658,18 @@ out: EXPORT_SYMBOL(printk); EXPORT_SYMBOL(vprintk); +#else + +asmlinkage long sys_syslog(int type, char __user * buf, int len) +{ + return 0; +} + +int do_syslog(int type, char __user * buf, int len) { return 0; } +static void call_console_drivers(unsigned long start, unsigned long end) {} + +#endif + /** * acquire_console_sem - lock the console system for exclusive use. * @@ -931,7 +946,7 @@ int unregister_console(struct console * console) return res; } EXPORT_SYMBOL(unregister_console); - + /** * tty_write_message - write a message to a certain tty, not just the console. * -- cgit v1.2.3 From 7f261b5f0dccd53ed3a9a95b55c36e24a698a92a Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sun, 1 May 2005 08:59:02 -0700 Subject: [PATCH] move SA_xxx defines to linux/signal.h The attached patch moves the IRQ-related SA_xxx flags (namely, SA_PROBE, SA_SAMPLE_RANDOM and SA_SHIRQ) from all the arch-specific headers to linux/signal.h. This looks like a left-over after the irq-handling code was consolidated. The code was moved to kernel/irq/*, but the flags are still left per-arch. Right now, adding a new IRQ flag to the arch-specific header, like this patch does: http://cvs.sourceforge.net/viewcvs.py/*checkout*/alsa/alsa-driver/utils/patches/pcsp-kernel-2.6.10-03.diff?rev=1.1 no longer works, it breaks the compilation for all other arches, unless you add that flag to all the other arch-specific headers too. So I think such a clean-up makes sense. Signed-off-by: Stas Sergeev Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/signal.h | 14 -------------- include/asm-arm/signal.h | 11 ----------- include/asm-arm26/signal.h | 11 ----------- include/asm-cris/signal.h | 14 -------------- include/asm-frv/signal.h | 14 -------------- include/asm-h8300/signal.h | 13 ------------- include/asm-i386/signal.h | 14 -------------- include/asm-ia64/signal.h | 10 ---------- include/asm-m32r/signal.h | 14 -------------- include/asm-m68k/signal.h | 13 ------------- include/asm-m68knommu/signal.h | 13 ------------- include/asm-mips/signal.h | 15 --------------- include/asm-parisc/signal.h | 11 ----------- include/asm-ppc/signal.h | 13 ------------- include/asm-ppc64/signal.h | 13 ------------- include/asm-s390/signal.h | 14 -------------- include/asm-sh/signal.h | 14 -------------- include/asm-sh64/signal.h | 14 -------------- include/asm-sparc/signal.h | 8 -------- include/asm-sparc64/signal.h | 8 -------- include/asm-v850/signal.h | 15 --------------- include/asm-x86_64/signal.h | 14 -------------- include/linux/signal.h | 11 +++++++++++ 23 files changed, 11 insertions(+), 280 deletions(-) (limited to 'include') diff --git a/include/asm-alpha/signal.h b/include/asm-alpha/signal.h index 25f98bc5576f..4e0842b415aa 100644 --- a/include/asm-alpha/signal.h +++ b/include/asm-alpha/signal.h @@ -109,20 +109,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 4096 #define SIGSTKSZ 16384 - -#ifdef __KERNEL__ -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x40000000 -#endif - #define SIG_BLOCK 1 /* for blocking signals */ #define SIG_UNBLOCK 2 /* for unblocking signals */ #define SIG_SETMASK 3 /* for setting the signal mask */ diff --git a/include/asm-arm/signal.h b/include/asm-arm/signal.h index b033e5fd60fa..b860dc3c5dc7 100644 --- a/include/asm-arm/signal.h +++ b/include/asm-arm/signal.h @@ -114,18 +114,7 @@ typedef unsigned long sigset_t; #define SIGSTKSZ 8192 #ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE 0x80000000 -#define SA_SAMPLE_RANDOM 0x10000000 #define SA_IRQNOMASK 0x08000000 -#define SA_SHIRQ 0x04000000 #endif #define SIG_BLOCK 0 /* for blocking signals */ diff --git a/include/asm-arm26/signal.h b/include/asm-arm26/signal.h index 6f62e51a2e5a..a1aacefa6562 100644 --- a/include/asm-arm26/signal.h +++ b/include/asm-arm26/signal.h @@ -114,18 +114,7 @@ typedef unsigned long sigset_t; #define SIGSTKSZ 8192 #ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE 0x80000000 -#define SA_SAMPLE_RANDOM 0x10000000 #define SA_IRQNOMASK 0x08000000 -#define SA_SHIRQ 0x04000000 #endif #define SIG_BLOCK 0 /* for blocking signals */ diff --git a/include/asm-cris/signal.h b/include/asm-cris/signal.h index 3f187ec4800a..2330769ba55d 100644 --- a/include/asm-cris/signal.h +++ b/include/asm-cris/signal.h @@ -108,20 +108,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-frv/signal.h b/include/asm-frv/signal.h index f18952f86a80..c930bb176875 100644 --- a/include/asm-frv/signal.h +++ b/include/asm-frv/signal.h @@ -107,20 +107,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-h8300/signal.h b/include/asm-h8300/signal.h index 3a08544a473e..ac3e01bd6396 100644 --- a/include/asm-h8300/signal.h +++ b/include/asm-h8300/signal.h @@ -107,19 +107,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h index 7ef343b6812d..0f082bd1c455 100644 --- a/include/asm-i386/signal.h +++ b/include/asm-i386/signal.h @@ -110,20 +110,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h index 660a759744dd..85a577ae9146 100644 --- a/include/asm-ia64/signal.h +++ b/include/asm-ia64/signal.h @@ -114,16 +114,6 @@ #define _NSIG_BPW 64 #define _NSIG_WORDS (_NSIG / _NSIG_BPW) -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 #define SA_PERCPU_IRQ 0x02000000 #endif /* __KERNEL__ */ diff --git a/include/asm-m32r/signal.h b/include/asm-m32r/signal.h index ce46eaea4494..6e55fd421883 100644 --- a/include/asm-m32r/signal.h +++ b/include/asm-m32r/signal.h @@ -114,20 +114,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h index 6681bb6a5523..1d016e9f19bf 100644 --- a/include/asm-m68k/signal.h +++ b/include/asm-m68k/signal.h @@ -105,19 +105,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-m68knommu/signal.h b/include/asm-m68knommu/signal.h index 486cbb0dc088..37c9c8a024ba 100644 --- a/include/asm-m68knommu/signal.h +++ b/include/asm-m68knommu/signal.h @@ -105,19 +105,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h index 994987db61be..d81356731eb6 100644 --- a/include/asm-mips/signal.h +++ b/include/asm-mips/signal.h @@ -98,21 +98,6 @@ typedef unsigned long old_sigset_t; /* at least 32 bits */ #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ flag is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x02000000 - -#endif /* __KERNEL__ */ - #define SIG_BLOCK 1 /* for blocking signals */ #define SIG_UNBLOCK 2 /* for unblocking signals */ #define SIG_SETMASK 3 /* for setting the signal mask */ diff --git a/include/asm-parisc/signal.h b/include/asm-parisc/signal.h index 358f577c8eb8..25cb23ef7dd1 100644 --- a/include/asm-parisc/signal.h +++ b/include/asm-parisc/signal.h @@ -89,17 +89,6 @@ #define _NSIG_BPW BITS_PER_LONG #define _NSIG_WORDS (_NSIG / _NSIG_BPW) -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 - #endif /* __KERNEL__ */ #define SIG_BLOCK 0 /* for blocking signals */ diff --git a/include/asm-ppc/signal.h b/include/asm-ppc/signal.h index 8cc8b88d4edd..d890dabd5a69 100644 --- a/include/asm-ppc/signal.h +++ b/include/asm-ppc/signal.h @@ -99,19 +99,6 @@ typedef struct { #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif /* __KERNEL__ */ #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ diff --git a/include/asm-ppc64/signal.h b/include/asm-ppc64/signal.h index fe5401adb41b..a2d7bbb4befd 100644 --- a/include/asm-ppc64/signal.h +++ b/include/asm-ppc64/signal.h @@ -96,19 +96,6 @@ typedef struct { #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ diff --git a/include/asm-s390/signal.h b/include/asm-s390/signal.h index f273cdcd1cf6..bfed83a818cc 100644 --- a/include/asm-s390/signal.h +++ b/include/asm-s390/signal.h @@ -117,20 +117,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-sh/signal.h b/include/asm-sh/signal.h index 0a7ff717c245..29f1ac1bf4df 100644 --- a/include/asm-sh/signal.h +++ b/include/asm-sh/signal.h @@ -108,20 +108,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-sh64/signal.h b/include/asm-sh64/signal.h index 77957e9b92d9..864c94ecc98c 100644 --- a/include/asm-sh64/signal.h +++ b/include/asm-sh64/signal.h @@ -107,20 +107,6 @@ typedef struct { #define MINSIGSTKSZ 2048 #define SIGSTKSZ THREAD_SIZE -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-sparc/signal.h b/include/asm-sparc/signal.h index d8211cb6e6b4..f792e10e704f 100644 --- a/include/asm-sparc/signal.h +++ b/include/asm-sparc/signal.h @@ -143,7 +143,6 @@ struct sigstack { #define SA_ONESHOT _SV_RESET #define SA_INTERRUPT 0x10u #define SA_NOMASK 0x20u -#define SA_SHIRQ 0x40u #define SA_NOCLDWAIT 0x100u #define SA_SIGINFO 0x200u @@ -162,11 +161,6 @@ struct sigstack { #ifdef __KERNEL__ /* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * * DJHR * SA_STATIC_ALLOC is used for the SPARC system to indicate that this * interrupt handler's irq structure should be statically allocated @@ -177,8 +171,6 @@ struct sigstack { * statically allocated data.. which is NOT GOOD. * */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART #define SA_STATIC_ALLOC 0x80 #endif diff --git a/include/asm-sparc64/signal.h b/include/asm-sparc64/signal.h index 6428e366c38c..466d021d7038 100644 --- a/include/asm-sparc64/signal.h +++ b/include/asm-sparc64/signal.h @@ -145,7 +145,6 @@ struct sigstack { #define SA_ONESHOT _SV_RESET #define SA_INTERRUPT 0x10u #define SA_NOMASK 0x20u -#define SA_SHIRQ 0x40u #define SA_NOCLDWAIT 0x100u #define SA_SIGINFO 0x200u @@ -165,11 +164,6 @@ struct sigstack { #ifdef __KERNEL__ /* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * * DJHR * SA_STATIC_ALLOC is used for the SPARC system to indicate that this * interrupt handler's irq structure should be statically allocated @@ -180,8 +174,6 @@ struct sigstack { * statically allocated data.. which is NOT GOOD. * */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART #define SA_STATIC_ALLOC 0x80 #endif diff --git a/include/asm-v850/signal.h b/include/asm-v850/signal.h index 407db875899c..ec3566c875d9 100644 --- a/include/asm-v850/signal.h +++ b/include/asm-v850/signal.h @@ -110,21 +110,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 - -#ifdef __KERNEL__ -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif /* __KERNEL__ */ - - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/asm-x86_64/signal.h b/include/asm-x86_64/signal.h index 643a20d73765..4987ad8082ba 100644 --- a/include/asm-x86_64/signal.h +++ b/include/asm-x86_64/signal.h @@ -116,20 +116,6 @@ typedef unsigned long sigset_t; #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 -#ifdef __KERNEL__ - -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - * SA_SHIRQ is for shared interrupt support on PCI and EISA. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#define SA_SHIRQ 0x04000000 -#endif - #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/include/linux/signal.h b/include/linux/signal.h index 99c97ad026c8..78bfb266e4f7 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -8,6 +8,17 @@ #ifdef __KERNEL__ +/* + * These values of sa_flags are used only by the kernel as part of the + * irq handling routines. + * + * SA_INTERRUPT is also used by the irq handling routines. + * SA_SHIRQ is for shared interrupt support on PCI and EISA. + */ +#define SA_PROBE SA_ONESHOT +#define SA_SAMPLE_RANDOM SA_RESTART +#define SA_SHIRQ 0x04000000 + /* * Real Time signals may be queued. */ -- cgit v1.2.3 From 512345be2549308b8ae8e85a3ff7f6d56a38e5f6 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 1 May 2005 08:59:03 -0700 Subject: [PATCH] Add deprecated_for_modules Add a deprecated_for_modules macro that allows symbols to be deprecated only when used by modules, as suggested by Andrew Morton some months back. Signed-off-by: Paul E. McKenney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compiler.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 487725cf0d0d..d7378215b851 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -90,6 +90,12 @@ extern void __chk_io_ptr(void __iomem *); # define __deprecated /* unimplemented */ #endif +#ifdef MODULE +#define __deprecated_for_modules __deprecated +#else +#define __deprecated_for_modules +#endif + #ifndef __must_check #define __must_check #endif -- cgit v1.2.3 From 9b06e818985d139fd9e82c28297f7744e1b484e1 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 1 May 2005 08:59:04 -0700 Subject: [PATCH] Deprecate synchronize_kernel, GPL replacement The synchronize_kernel() primitive is used for quite a few different purposes: waiting for RCU readers, waiting for NMIs, waiting for interrupts, and so on. This makes RCU code harder to read, since synchronize_kernel() might or might not have matching rcu_read_lock()s. This patch creates a new synchronize_rcu() that is to be used for RCU readers and a new synchronize_sched() that is used for the rest. These two new primitives currently have the same implementation, but this is might well change with additional real-time support. Both new primitives are GPL-only, the old primitive is deprecated. Signed-off-by: Paul E. McKenney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rcupdate.h | 23 ++++++++++++++++++++--- kernel/rcupdate.c | 16 ++++++++++++++-- 2 files changed, 34 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 4d747433916b..fd276adf0fd5 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -157,9 +157,9 @@ static inline int rcu_pending(int cpu) /** * rcu_read_lock - mark the beginning of an RCU read-side critical section. * - * When synchronize_kernel() is invoked on one CPU while other CPUs + * When synchronize_rcu() is invoked on one CPU while other CPUs * are within RCU read-side critical sections, then the - * synchronize_kernel() is guaranteed to block until after all the other + * synchronize_rcu() is guaranteed to block until after all the other * CPUs exit their critical sections. Similarly, if call_rcu() is invoked * on one CPU while other CPUs are within RCU read-side critical * sections, invocation of the corresponding RCU callback is deferred @@ -256,6 +256,21 @@ static inline int rcu_pending(int cpu) (p) = (v); \ }) +/** + * synchronize_sched - block until all CPUs have exited any non-preemptive + * kernel code sequences. + * + * This means that all preempt_disable code sequences, including NMI and + * hardware-interrupt handlers, in progress on entry will have completed + * before this primitive returns. However, this does not guarantee that + * softirq handlers will have completed, since in some kernels + * + * This primitive provides the guarantees made by the (deprecated) + * synchronize_kernel() API. In contrast, synchronize_rcu() only + * guarantees that rcu_read_lock() sections will have completed. + */ +#define synchronize_sched() synchronize_rcu() + extern void rcu_init(void); extern void rcu_check_callbacks(int cpu, int user); extern void rcu_restart_cpu(int cpu); @@ -265,7 +280,9 @@ extern void FASTCALL(call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *head))); extern void FASTCALL(call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *head))); -extern void synchronize_kernel(void); +extern __deprecated_for_modules void synchronize_kernel(void); +extern void synchronize_rcu(void); +void synchronize_idle(void); #endif /* __KERNEL__ */ #endif /* __LINUX_RCUPDATE_H */ diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index ad497722f04f..f436993bd590 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -444,15 +444,18 @@ static void wakeme_after_rcu(struct rcu_head *head) } /** - * synchronize_kernel - wait until a grace period has elapsed. + * synchronize_rcu - wait until a grace period has elapsed. * * Control will return to the caller some time after a full grace * period has elapsed, in other words after all currently executing RCU * read-side critical sections have completed. RCU read-side critical * sections are delimited by rcu_read_lock() and rcu_read_unlock(), * and may be nested. + * + * If your read-side code is not protected by rcu_read_lock(), do -not- + * use synchronize_rcu(). */ -void synchronize_kernel(void) +void synchronize_rcu(void) { struct rcu_synchronize rcu; @@ -464,7 +467,16 @@ void synchronize_kernel(void) wait_for_completion(&rcu.completion); } +/* + * Deprecated, use synchronize_rcu() or synchronize_sched() instead. + */ +void synchronize_kernel(void) +{ + synchronize_rcu(); +} + module_param(maxbatch, int, 0); EXPORT_SYMBOL(call_rcu); /* WARNING: GPL-only in April 2006. */ EXPORT_SYMBOL(call_rcu_bh); /* WARNING: GPL-only in April 2006. */ +EXPORT_SYMBOL_GPL(synchronize_rcu); EXPORT_SYMBOL(synchronize_kernel); /* WARNING: GPL-only in April 2006. */ -- cgit v1.2.3 From 4750e2c0c59e0c84c6c036b3d96ebd88365ae7ee Mon Sep 17 00:00:00 2001 From: Joe Korty Date: Sun, 1 May 2005 08:59:06 -0700 Subject: [PATCH] add EOWNERDEAD and ENOTRECOVERABLE version 2 Add EOWNERDEAD and ENOTRECOVERABLE to all architectures. This is to support the upcoming patches for robust mutexes. We normally don't reserve parts of the name/number space for external patches, but robust mutexes are sufficiently popular and important to justify it in this case. Signed-off-by: Joe Korty Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/errno.h | 4 ++++ include/asm-generic/errno.h | 4 ++++ include/asm-mips/errno.h | 4 ++++ include/asm-parisc/errno.h | 4 ++++ include/asm-sparc/errno.h | 4 ++++ include/asm-sparc64/errno.h | 4 ++++ 6 files changed, 24 insertions(+) (limited to 'include') diff --git a/include/asm-alpha/errno.h b/include/asm-alpha/errno.h index c85ab6b9d6c6..69e2655249d2 100644 --- a/include/asm-alpha/errno.h +++ b/include/asm-alpha/errno.h @@ -116,4 +116,8 @@ #define EKEYREVOKED 134 /* Key has been revoked */ #define EKEYREJECTED 135 /* Key was rejected by service */ +/* for robust mutexes */ +#define EOWNERDEAD 136 /* Owner died */ +#define ENOTRECOVERABLE 137 /* State not recoverable */ + #endif diff --git a/include/asm-generic/errno.h b/include/asm-generic/errno.h index 4dd2384bc38d..e8852c092fea 100644 --- a/include/asm-generic/errno.h +++ b/include/asm-generic/errno.h @@ -102,4 +102,8 @@ #define EKEYREVOKED 128 /* Key has been revoked */ #define EKEYREJECTED 129 /* Key was rejected by service */ +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + #endif diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h index 2b458f9538cd..3c0d840e4577 100644 --- a/include/asm-mips/errno.h +++ b/include/asm-mips/errno.h @@ -115,6 +115,10 @@ #define EKEYREVOKED 163 /* Key has been revoked */ #define EKEYREJECTED 164 /* Key was rejected by service */ +/* for robust mutexes */ +#define EOWNERDEAD 165 /* Owner died */ +#define ENOTRECOVERABLE 166 /* State not recoverable */ + #define EDQUOT 1133 /* Quota exceeded */ #ifdef __KERNEL__ diff --git a/include/asm-parisc/errno.h b/include/asm-parisc/errno.h index a10f109770f1..08464c405471 100644 --- a/include/asm-parisc/errno.h +++ b/include/asm-parisc/errno.h @@ -115,5 +115,9 @@ #define ENOTSUP 252 /* Function not implemented (POSIX.4 / HPUX) */ #define ECANCELLED 253 /* aio request was canceled before complete (POSIX.4 / HPUX) */ +/* for robust mutexes */ +#define EOWNERDEAD 254 /* Owner died */ +#define ENOTRECOVERABLE 255 /* State not recoverable */ + #endif diff --git a/include/asm-sparc/errno.h b/include/asm-sparc/errno.h index 8c01c5f3b06d..ed41c8bac1fa 100644 --- a/include/asm-sparc/errno.h +++ b/include/asm-sparc/errno.h @@ -107,4 +107,8 @@ #define EKEYREVOKED 130 /* Key has been revoked */ #define EKEYREJECTED 131 /* Key was rejected by service */ +/* for robust mutexes */ +#define EOWNERDEAD 132 /* Owner died */ +#define ENOTRECOVERABLE 133 /* State not recoverable */ + #endif diff --git a/include/asm-sparc64/errno.h b/include/asm-sparc64/errno.h index cc98a73b55a7..ea3509ee1b0b 100644 --- a/include/asm-sparc64/errno.h +++ b/include/asm-sparc64/errno.h @@ -107,4 +107,8 @@ #define EKEYREVOKED 130 /* Key has been revoked */ #define EKEYREJECTED 131 /* Key was rejected by service */ +/* for robust mutexes */ +#define EOWNERDEAD 132 /* Owner died */ +#define ENOTRECOVERABLE 133 /* State not recoverable */ + #endif /* !(_SPARC64_ERRNO_H) */ -- cgit v1.2.3 From a71c1ab50a2a0f4dd9834bf5a917a2f064535c6b Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 1 May 2005 08:59:08 -0700 Subject: [PATCH] consolidate SIGEV_PAD_SIZE Discussing with Matthew Wilcox some of his outstanding patches lead me to this patch (among others). The preamble in struct sigevent can be expressed independently of the architecture. Also use __ARCH_SI_PREAMBLE_SIZE on ia64. Signed-off-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/siginfo.h | 2 -- include/asm-generic/siginfo.h | 13 ++++++++++--- include/asm-ia64/siginfo.h | 4 +--- include/asm-mips/siginfo.h | 2 -- include/asm-s390/siginfo.h | 6 ------ include/asm-sparc64/siginfo.h | 2 -- include/asm-x86_64/siginfo.h | 2 -- 7 files changed, 11 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/asm-alpha/siginfo.h b/include/asm-alpha/siginfo.h index 86bcab59c52b..9822362a8424 100644 --- a/include/asm-alpha/siginfo.h +++ b/include/asm-alpha/siginfo.h @@ -4,8 +4,6 @@ #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #define __ARCH_SI_TRAPNO -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) - #include #endif diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h index 9cac8e8dde51..8786e01e0db8 100644 --- a/include/asm-generic/siginfo.h +++ b/include/asm-generic/siginfo.h @@ -236,11 +236,18 @@ typedef struct siginfo { #define SIGEV_THREAD 2 /* deliver via thread creation */ #define SIGEV_THREAD_ID 4 /* deliver to thread */ -#define SIGEV_MAX_SIZE 64 -#ifndef SIGEV_PAD_SIZE -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3) +/* + * This works because the alignment is ok on all current architectures + * but we leave open this being overridden in the future + */ +#ifndef __ARCH_SIGEV_PREAMBLE_SIZE +#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(int) * 2 + sizeof(sigval_t)) #endif +#define SIGEV_MAX_SIZE 64 +#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE) \ + / sizeof(int)) + typedef struct sigevent { sigval_t sigev_value; int sigev_signo; diff --git a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h index d55f139cbcdc..9294e4b0c8bc 100644 --- a/include/asm-ia64/siginfo.h +++ b/include/asm-ia64/siginfo.h @@ -8,9 +8,7 @@ * David Mosberger-Tang , Hewlett-Packard Co */ -#define SI_PAD_SIZE ((SI_MAX_SIZE/sizeof(int)) - 4) - -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) +#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #define HAVE_ARCH_SIGINFO_T #define HAVE_ARCH_COPY_SIGINFO diff --git a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h index 8ddd3c99bcf7..a0e26e6c994d 100644 --- a/include/asm-mips/siginfo.h +++ b/include/asm-mips/siginfo.h @@ -11,8 +11,6 @@ #include -#define SIGEV_HEAD_SIZE (sizeof(long) + 2*sizeof(int)) -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE-SIGEV_HEAD_SIZE) / sizeof(int)) #undef __ARCH_SI_TRAPNO /* exception code needs to fill this ... */ #define HAVE_ARCH_SIGINFO_T diff --git a/include/asm-s390/siginfo.h b/include/asm-s390/siginfo.h index 72303537b732..e0ff1ab054be 100644 --- a/include/asm-s390/siginfo.h +++ b/include/asm-s390/siginfo.h @@ -13,12 +13,6 @@ #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #endif -#ifdef CONFIG_ARCH_S390X -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) -#else -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3) -#endif - #include #endif diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h index 7160449e7cab..df17e47abc1c 100644 --- a/include/asm-sparc64/siginfo.h +++ b/include/asm-sparc64/siginfo.h @@ -3,8 +3,6 @@ #define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) - #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #define __ARCH_SI_TRAPNO #define __ARCH_SI_BAND_T int diff --git a/include/asm-x86_64/siginfo.h b/include/asm-x86_64/siginfo.h index 7bc15985f124..d09a1e6e7246 100644 --- a/include/asm-x86_64/siginfo.h +++ b/include/asm-x86_64/siginfo.h @@ -3,8 +3,6 @@ #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) -#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) - #include #endif -- cgit v1.2.3 From e49332bd12e92da2df6d002f857ec62675ba2648 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 1 May 2005 08:59:08 -0700 Subject: [PATCH] misc verify_area cleanups There were still a few comments left refering to verify_area, and two functions, verify_area_skas & verify_area_tt that just wrap corresponding access_ok_skas & access_ok_tt functions, just like verify_area does for access_ok - deprecate those. There was also a few places that still used verify_area in commented-out code, fix those up to use access_ok. After applying this one there should not be anything left but finally removing verify_area completely, which will happen after a kernel release or two. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/vm86.c | 2 +- arch/um/kernel/skas/include/uaccess-skas.h | 2 +- arch/um/kernel/tt/include/uaccess-tt.h | 2 +- drivers/char/dtlk.c | 2 +- drivers/char/specialix.c | 11 ++++------- include/asm-frv/pgtable.h | 4 ++-- include/asm-i386/checksum.h | 2 +- include/asm-i386/pgtable.h | 4 ++-- include/asm-parisc/uaccess.h | 2 +- include/asm-sh/checksum.h | 2 +- include/asm-sh64/checksum.h | 2 +- include/asm-sparc/uaccess.h | 2 +- net/8021q/vlanproc.c | 2 +- net/atm/common.c | 4 ++-- net/core/iovec.c | 2 +- net/wanrouter/wanmain.c | 4 ++-- 16 files changed, 23 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index d3b4c540eb64..ec0f68ce6886 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -222,7 +222,7 @@ asmlinkage int sys_vm86(struct pt_regs regs) goto out; case VM86_PLUS_INSTALL_CHECK: /* NOTE: on old vm86 stuff this will return the error - from verify_area(), because the subfunction is + from access_ok(), because the subfunction is interpreted as (invalid) address to vm86_struct. So the installation check works. */ diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 11986c9b9ddf..c35620385da0 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h @@ -18,7 +18,7 @@ ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) -static inline int verify_area_skas(int type, const void * addr, +static inline int __deprecated verify_area_skas(int type, const void * addr, unsigned long size) { return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index f0bad010cebd..bb69d6b7d022 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h @@ -33,7 +33,7 @@ extern unsigned long uml_physmem; (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ (under_task_size(addr, size) || is_stack(addr, size)))) -static inline int verify_area_tt(int type, const void * addr, +static inline int __deprecated verify_area_tt(int type, const void * addr, unsigned long size) { return(access_ok_tt(type, addr, size) ? 0 : -EFAULT); diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index 903e4c3cc209..a229915ce1b2 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -52,7 +52,7 @@ #define KERNEL #include #include -#include /* for verify_area */ +#include #include /* for -EBUSY */ #include /* for request_region */ #include /* for loops_per_jiffy */ diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index c789d5ceac76..50e0b612a8a2 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1987,10 +1987,9 @@ static inline int sx_set_serial_info(struct specialix_port * port, func_enter(); /* - error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp)); - if (error) { + if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) { func_exit(); - return error; + return -EFAULT; } */ if (copy_from_user(&tmp, newinfo, sizeof(tmp))) { @@ -2046,14 +2045,12 @@ static inline int sx_get_serial_info(struct specialix_port * port, { struct serial_struct tmp; struct specialix_board *bp = port_Board(port); - // int error; func_enter(); /* - error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)); - if (error) - return error; + if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp))) + return -EFAULT; */ memset(&tmp, 0, sizeof(tmp)); diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h index 3c6d42a22dfe..d0a9c2f9c13e 100644 --- a/include/asm-frv/pgtable.h +++ b/include/asm-frv/pgtable.h @@ -349,9 +349,9 @@ static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address) /* * Define this to warn about kernel memory accesses that are - * done without a 'verify_area(VERIFY_WRITE,..)' + * done without a 'access_ok(VERIFY_WRITE,..)' */ -#undef TEST_VERIFY_AREA +#undef TEST_ACCESS_OK #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) #define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h index d76a5f081c91..641342002bcd 100644 --- a/include/asm-i386/checksum.h +++ b/include/asm-i386/checksum.h @@ -33,7 +33,7 @@ asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsi * passed in an incorrect kernel address to one of these functions. * * If you use these functions directly please don't forget the - * verify_area(). + * access_ok(). */ static __inline__ unsigned int csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst, diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 5c725425d863..8d60c2b4b003 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -193,9 +193,9 @@ extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC; /* * Define this if things work differently on an i386 and an i486: * it will (on an i486) warn about kernel memory accesses that are - * done without a 'verify_area(VERIFY_WRITE,..)' + * done without a 'access_ok(VERIFY_WRITE,..)' */ -#undef TEST_VERIFY_AREA +#undef TEST_ACCESS_OK /* The boot page tables (all created as a single array) */ extern unsigned long pg0[]; diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h index 8a08423b7570..c1b5bdea53ee 100644 --- a/include/asm-parisc/uaccess.h +++ b/include/asm-parisc/uaccess.h @@ -24,7 +24,7 @@ /* * Note that since kernel addresses are in a separate address space on - * parisc, we don't need to do anything for access_ok() or verify_area(). + * parisc, we don't need to do anything for access_ok(). * We just let the page fault handler do the right thing. This also means * that put_user is the same as __put_user, etc. */ diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h index 5113c7f8a739..5ebd0f24299e 100644 --- a/include/asm-sh/checksum.h +++ b/include/asm-sh/checksum.h @@ -42,7 +42,7 @@ asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsi * passed in an incorrect kernel address to one of these functions. * * If you use these functions directly please don't forget the - * verify_area(). + * access_ok(). */ static __inline__ unsigned int csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst, diff --git a/include/asm-sh64/checksum.h b/include/asm-sh64/checksum.h index aa3911a99490..fd034e9ae6e3 100644 --- a/include/asm-sh64/checksum.h +++ b/include/asm-sh64/checksum.h @@ -34,7 +34,7 @@ asmlinkage unsigned int csum_partial(const unsigned char *buff, int len, * passed in an incorrect kernel address to one of these functions. * * If you use these functions directly please don't forget the - * verify_area(). + * access_ok(). */ diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h index 3f47889883b7..f461144067ee 100644 --- a/include/asm-sparc/uaccess.h +++ b/include/asm-sparc/uaccess.h @@ -18,7 +18,7 @@ #ifndef __ASSEMBLY__ -/* Sparc is not segmented, however we need to be able to fool verify_area() +/* Sparc is not segmented, however we need to be able to fool access_ok() * when doing system calls from kernel mode legitimately. * * "For historical reasons, these macros are grossly misnamed." -Linus diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index c32d27af0a3f..7b214cffc956 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -23,7 +23,7 @@ #include /* return codes */ #include #include /* kmalloc(), kfree() */ -#include /* verify_area(), etc. */ +#include #include /* inline mem*, str* functions */ #include /* __initfunc et al. */ #include /* htons(), etc. */ diff --git a/net/atm/common.c b/net/atm/common.c index 6d16be334ea0..e93e838069e8 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -12,7 +12,7 @@ #include /* SOL_SOCKET */ #include /* error codes */ #include -#include /* verify_area */ +#include #include #include /* struct timeval */ #include @@ -540,7 +540,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, error = -EMSGSIZE; goto out; } - /* verify_area is done by net/socket.c */ + eff = (size+3) & ~3; /* align to word boundary */ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); error = 0; diff --git a/net/core/iovec.c b/net/core/iovec.c index d57ace949ab8..65e4b56fbc77 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -33,7 +33,7 @@ * Verify iovec. The caller must ensure that the iovec is big enough * to hold the message iovec. * - * Save time not doing verify_area. copy_*_user will make this work + * Save time not doing access_ok. copy_*_user will make this work * in any case. */ diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 956c17f6c548..d6844ac226f5 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -48,8 +48,8 @@ #include #include #include /* support for loadable modules */ -#include /* kmalloc(), kfree() */ -#include /* verify_area(), etc. */ +#include /* kmalloc(), kfree() */ +#include #include /* inline mem*, str* functions */ #include /* htons(), etc. */ -- cgit v1.2.3 From f78fc874f42f63a460bcebc2aeb98db526280d1c Mon Sep 17 00:00:00 2001 From: Vinay K Nallamothu Date: Sun, 1 May 2005 08:59:09 -0700 Subject: [PATCH] __attribute__ placement fixes The variable attributes "packed" and "align" when used with struct, should have the following order: struct ... {...} __attribute__((packed)) var; This patch fixes few instances where the variable and attributes are placed the other way around and had no effect. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/gt96100eth.h | 4 ++-- include/asm-m68knommu/MC68328.h | 2 +- include/asm-m68knommu/MC68EZ328.h | 2 +- include/asm-m68knommu/MC68VZ328.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/net/gt96100eth.h b/drivers/net/gt96100eth.h index 2f4bfd4dacbe..395869c5ed3e 100644 --- a/drivers/net/gt96100eth.h +++ b/drivers/net/gt96100eth.h @@ -214,7 +214,7 @@ typedef struct { u32 cmdstat; u32 next; u32 buff_ptr; -} gt96100_td_t __attribute__ ((packed)); +} __attribute__ ((packed)) gt96100_td_t; typedef struct { #ifdef DESC_BE @@ -227,7 +227,7 @@ typedef struct { u32 cmdstat; u32 next; u32 buff_ptr; -} gt96100_rd_t __attribute__ ((packed)); +} __attribute__ ((packed)) gt96100_rd_t; /* Values for the Tx command-status descriptor entry. */ diff --git a/include/asm-m68knommu/MC68328.h b/include/asm-m68knommu/MC68328.h index 4f5a9845f5be..a337e56d09bf 100644 --- a/include/asm-m68knommu/MC68328.h +++ b/include/asm-m68knommu/MC68328.h @@ -993,7 +993,7 @@ typedef volatile struct { volatile unsigned short int pad1; volatile unsigned short int pad2; volatile unsigned short int pad3; -} m68328_uart __attribute__((packed)); +} __attribute__((packed)) m68328_uart; /********** diff --git a/include/asm-m68knommu/MC68EZ328.h b/include/asm-m68knommu/MC68EZ328.h index 801933da4c70..69b7f9139e5e 100644 --- a/include/asm-m68knommu/MC68EZ328.h +++ b/include/asm-m68knommu/MC68EZ328.h @@ -815,7 +815,7 @@ typedef volatile struct { volatile unsigned short int nipr; volatile unsigned short int pad1; volatile unsigned short int pad2; -} m68328_uart __attribute__((packed)); +} __attribute__((packed)) m68328_uart; /********** diff --git a/include/asm-m68knommu/MC68VZ328.h b/include/asm-m68knommu/MC68VZ328.h index df74322f37ed..2b9bf626a0a5 100644 --- a/include/asm-m68knommu/MC68VZ328.h +++ b/include/asm-m68knommu/MC68VZ328.h @@ -909,7 +909,7 @@ typedef struct { volatile unsigned short int nipr; volatile unsigned short int hmark; volatile unsigned short int unused; -} m68328_uart __attribute__((packed)); +} __attribute__((packed)) m68328_uart; -- cgit v1.2.3 From 7d87e14c236d6c4cab66d87cf0bc1e0f0375d308 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 1 May 2005 08:59:12 -0700 Subject: [PATCH] consolidate sys_shmat Signed-off-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/osf_sys.c | 16 ---------------- arch/alpha/kernel/systbls.S | 2 +- arch/arm/kernel/sys_arm.c | 12 ------------ arch/ia64/kernel/entry.S | 2 +- arch/ia64/kernel/sys_ia64.c | 14 -------------- arch/mips/kernel/syscall.c | 16 ---------------- arch/parisc/kernel/sys_parisc.c | 11 ----------- arch/parisc/kernel/syscall_table.S | 2 +- arch/sh64/kernel/sys_sh64.c | 15 --------------- arch/sh64/kernel/syscalls.S | 2 +- arch/um/include/sysdep-x86_64/syscalls.h | 1 - arch/um/sys-x86_64/syscalls.c | 8 -------- arch/x86_64/kernel/sys_x86_64.c | 6 ------ include/asm-x86_64/unistd.h | 2 +- include/linux/syscalls.h | 3 +-- ipc/shm.c | 14 ++++++++++++++ kernel/sys_ni.c | 1 + 17 files changed, 21 insertions(+), 106 deletions(-) (limited to 'include') diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index b5d0fd2bb10a..64e450dddb49 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -457,22 +457,6 @@ osf_getdomainname(char __user *name, int namelen) return 0; } -asmlinkage long -osf_shmat(int shmid, void __user *shmaddr, int shmflg) -{ - unsigned long raddr; - long err; - - err = do_shmat(shmid, shmaddr, shmflg, &raddr); - - /* - * This works because all user-level addresses are - * non-negative longs! - */ - return err ? err : (long)raddr; -} - - /* * The following stuff should move into a header file should it ever * be labeled "officially supported." Right now, there is just enough diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 3864b33562ee..052120882876 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -227,7 +227,7 @@ sys_call_table: .quad sys_semop .quad osf_utsname .quad sys_lchown - .quad osf_shmat + .quad sys_shmat .quad sys_shmctl /* 210 */ .quad sys_shmdt .quad sys_shmget diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 7ba6342cf93d..ef32577da304 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -227,18 +227,6 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third, } } -asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg, - unsigned long __user *addr) -{ - unsigned long ret; - long err; - - err = do_shmat(shmid, shmaddr, shmflg, &ret); - if (err == 0) - err = put_user(ret, addr); - return err; -} - /* Fork a new task - this creates a new program thread. * This is called indirectly via a small wrapper */ diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index bd86fea49a0c..d3f093820bc7 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1417,7 +1417,7 @@ sys_call_table: data8 sys_msgrcv data8 sys_msgctl data8 sys_shmget - data8 ia64_shmat + data8 sys_shmat data8 sys_shmdt // 1115 data8 sys_shmctl data8 sys_syslog diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 3ac216e1c8bb..a8cf6d8a509c 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -92,20 +92,6 @@ sys_getpagesize (void) return PAGE_SIZE; } -asmlinkage unsigned long -ia64_shmat (int shmid, void __user *shmaddr, int shmflg) -{ - unsigned long raddr; - int retval; - - retval = do_shmat(shmid, shmaddr, shmflg, &raddr); - if (retval < 0) - return retval; - - force_successful_syscall_return(); - return raddr; -} - asmlinkage unsigned long ia64_brk (unsigned long brk) { diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 598bfe7426a2..ae2a1312d4ef 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -373,22 +373,6 @@ asmlinkage int sys_ipc (uint call, int first, int second, } } -/* - * Native ABI that is O32 or N64 version - */ -asmlinkage long sys_shmat(int shmid, char __user *shmaddr, - int shmflg, unsigned long *addr) -{ - unsigned long raddr; - int err; - - err = do_shmat(shmid, shmaddr, shmflg, &raddr); - if (err) - return err; - - return put_user(raddr, addr); -} - /* * No implemented yet ... */ diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 7958cd8c8bf8..d15a1d53e101 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -161,17 +161,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, } } -long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag) -{ - unsigned long raddr; - int r; - - r = do_shmat(shmid, shmaddr, shmflag, &raddr); - if (r < 0) - return r; - return raddr; -} - /* Fucking broken ABI */ #ifdef CONFIG_64BIT diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 779b537100ec..dcfa4d3d0e7d 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -297,7 +297,7 @@ ENTRY_DIFF(msgrcv) ENTRY_SAME(msgget) /* 190 */ ENTRY_SAME(msgctl) - ENTRY_SAME(shmat_wrapper) + ENTRY_SAME(shmat) ENTRY_SAME(shmdt) ENTRY_SAME(shmget) ENTRY_SAME(shmctl) /* 195 */ diff --git a/arch/sh64/kernel/sys_sh64.c b/arch/sh64/kernel/sys_sh64.c index 4546845b9caf..58ff7d522d81 100644 --- a/arch/sh64/kernel/sys_sh64.c +++ b/arch/sh64/kernel/sys_sh64.c @@ -283,18 +283,3 @@ asmlinkage int sys_uname(struct old_utsname * name) up_read(&uts_sem); return err?-EFAULT:0; } - -/* Copy from mips version */ -asmlinkage long sys_shmatcall(int shmid, char __user *shmaddr, - int shmflg) -{ - unsigned long raddr; - int err; - - err = do_shmat(shmid, shmaddr, shmflg, &raddr); - if (err) - return err; - - err = raddr; - return err; -} diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S index 8ed417df3dc6..6aabc63e4518 100644 --- a/arch/sh64/kernel/syscalls.S +++ b/arch/sh64/kernel/syscalls.S @@ -268,7 +268,7 @@ sys_call_table: .long sys_msgrcv .long sys_msgget .long sys_msgctl - .long sys_shmatcall + .long sys_shmat .long sys_shmdt /* 245 */ .long sys_shmget .long sys_shmctl diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h index b56b335c3514..67923cca5691 100644 --- a/arch/um/include/sysdep-x86_64/syscalls.h +++ b/arch/um/include/sysdep-x86_64/syscalls.h @@ -26,7 +26,6 @@ extern syscall_handler_t *ia32_sys_call_table[]; extern long old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff); -extern syscall_handler_t wrap_sys_shmat; extern syscall_handler_t sys_modify_ldt; extern syscall_handler_t sys_arch_prctl; diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index 15768c96ceb4..ab4b0abf8af3 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -14,14 +14,6 @@ #include "asm/prctl.h" /* XXX This should get the constants from libc */ #include "choose-mode.h" -/* XXX: copied from x86-64: arch/x86_64/kernel/sys_x86_64.c */ -asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg) -{ - unsigned long raddr; - - return do_shmat(shmid, shmaddr, shmflg, &raddr) ?: (long) raddr; -} - asmlinkage long sys_uname64(struct new_utsname __user * name) { int err; diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c index 477d8be57d64..dbebd5ccba6b 100644 --- a/arch/x86_64/kernel/sys_x86_64.c +++ b/arch/x86_64/kernel/sys_x86_64.c @@ -152,12 +152,6 @@ asmlinkage long sys_uname(struct new_utsname __user * name) return err ? -EFAULT : 0; } -asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg) -{ - unsigned long raddr; - return do_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr; -} - asmlinkage long sys_time64(long __user * tloc) { struct timeval now; diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 3d65d240dc95..3c9af6fd4332 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -76,7 +76,7 @@ __SYSCALL(__NR_madvise, sys_madvise) #define __NR_shmget 29 __SYSCALL(__NR_shmget, sys_shmget) #define __NR_shmat 30 -__SYSCALL(__NR_shmat, wrap_sys_shmat) +__SYSCALL(__NR_shmat, sys_shmat) #define __NR_shmctl 31 __SYSCALL(__NR_shmctl, sys_shmctl) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 757cd9be7743..c39f6f72cbbc 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -456,8 +456,7 @@ asmlinkage long sys_semctl(int semid, int semnum, int cmd, union semun arg); asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops, unsigned nsops, const struct timespec __user *timeout); -asmlinkage long sys_shmat(int shmid, char __user *shmaddr, - int shmflg, unsigned long __user *addr); +asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg); asmlinkage long sys_shmget(key_t key, size_t size, int flag); asmlinkage long sys_shmdt(char __user *shmaddr); asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); diff --git a/ipc/shm.c b/ipc/shm.c index 06cd5c91056f..cce022435dbc 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include "util.h" @@ -771,6 +773,18 @@ out: return err; } +asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg) +{ + unsigned long ret; + long err; + + err = do_shmat(shmid, shmaddr, shmflg, &ret); + if (err) + return err; + force_successful_syscall_return(); + return (long)ret; +} + /* * detach and kill segment if marked destroyed. * The work is done in shm_close. diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 1802a311dd3f..0dda70ed1f98 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -52,6 +52,7 @@ cond_syscall(sys_msgsnd); cond_syscall(sys_msgrcv); cond_syscall(sys_msgctl); cond_syscall(sys_shmget); +cond_syscall(sys_shmat); cond_syscall(sys_shmdt); cond_syscall(sys_shmctl); cond_syscall(sys_mq_open); -- cgit v1.2.3 From e5bdd883a189243541e7a132385580703b049102 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 1 May 2005 08:59:13 -0700 Subject: [PATCH] new valid_signal() function This patch adds a new function valid_signal() that tests if its argument is a valid signal number. The reasons for adding this new function are: - some code currently testing _NSIG directly has off-by-one errors. Using this function instead avoids such errors. - some code currently tests unsigned signal numbers for <0 which is pointless and generates warnings when building with gcc -W. Using this function instead avoids such warnings. I considered various places to add this function but eventually settled on include/linux/signal.h as the most logical place for it. If there's some reason this is a bad choice then please let me know (hints as to a better location are then welcome of course). Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/signal.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/linux/signal.h b/include/linux/signal.h index 78bfb266e4f7..0a98f5ec5cae 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -220,6 +220,12 @@ static inline void init_sigpending(struct sigpending *sig) INIT_LIST_HEAD(&sig->list); } +/* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */ +static inline int valid_signal(unsigned long sig) +{ + return sig <= _NSIG ? 1 : 0; +} + extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p); extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); extern long do_sigpending(void __user *, unsigned long); -- cgit v1.2.3 From d46aa455dd5457fdbebad17db4ff4df655cbfbae Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Sun, 1 May 2005 08:59:17 -0700 Subject: [PATCH] autofs4: bump version number Bump autofs4 version so we know what's going on. Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/auto_fs4.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h index d1c7b0ec7c22..a1657fb99516 100644 --- a/include/linux/auto_fs4.h +++ b/include/linux/auto_fs4.h @@ -23,7 +23,7 @@ #define AUTOFS_MIN_PROTO_VERSION 3 #define AUTOFS_MAX_PROTO_VERSION 4 -#define AUTOFS_PROTO_SUBVERSION 5 +#define AUTOFS_PROTO_SUBVERSION 6 /* Mask for expire behaviour */ #define AUTOFS_EXP_IMMEDIATE 1 -- cgit v1.2.3 From 6a3a16f2ef6f335286e2b2bf8284b0ab4ff38ec0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:17 -0700 Subject: [PATCH] reiserfs endianness: clone struct reiserfs_key struct reiserfs_key cloned; (currently) identical struct in_core_key added. Places that expect host-endian data in reiserfs_key switched to in_core_key. Basically, we get annotation of reiserfs_key users and keep the resulting tree obviously equivalent to original. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/bitmap.c | 4 ++-- fs/reiserfs/stree.c | 1 + fs/reiserfs/super.c | 4 ++-- include/linux/reiserfs_fs.h | 32 +++++++++++++++++++++++++++++--- 4 files changed, 34 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index a4e2ed544bbe..f4f16fada14c 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -736,7 +736,7 @@ static inline int this_blocknr_allocation_would_make_it_a_large_file(reiserfs_bl #ifdef DISPLACE_NEW_PACKING_LOCALITIES static inline void displace_new_packing_locality (reiserfs_blocknr_hint_t *hint) { - struct reiserfs_key * key = &hint->key; + struct in_core_key * key = &hint->key; hint->th->displace_new_blocks = 0; hint->search_start = hint->beg + keyed_hash((char*)(&key->k_objectid),4) % (hint->end - hint->beg); @@ -777,7 +777,7 @@ static inline int old_way (reiserfs_blocknr_hint_t * hint) static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint) { - struct reiserfs_key * key = &hint->key; + struct in_core_key * key = &hint->key; b_blocknr_t slice_start; slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100); diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 73ec5212178b..1d380a5da39c 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -229,6 +229,7 @@ const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; /* Maximal possible key. It is never in the tree. */ const struct reiserfs_key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; +const struct in_core_key MAX_IN_CORE_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index bc5e8893b5d5..d6d1d7e2801f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -110,7 +110,7 @@ static void reiserfs_unlockfs(struct super_block *s) { reiserfs_allow_writes(s) ; } -extern const struct reiserfs_key MAX_KEY; +extern const struct in_core_key MAX_IN_CORE_KEY; /* this is used to delete "save link" when there are no items of a @@ -164,7 +164,7 @@ static int finish_unfinished (struct super_block * s) /* compose key to look for "save" links */ max_cpu_key.version = KEY_FORMAT_3_5; - max_cpu_key.on_disk_key = MAX_KEY; + max_cpu_key.on_disk_key = MAX_IN_CORE_KEY; max_cpu_key.key_length = 3; #ifdef CONFIG_QUOTA diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index bccff8b17dc4..d0867873a1b5 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -433,6 +433,23 @@ static inline void set_offset_v2_k_offset( struct offset_v2 *v2, loff_t offset ) # define set_offset_v2_k_offset(v2,val) (offset_v2_k_offset(v2) = (val)) #endif +struct in_core_offset_v1 { + __u32 k_offset; + __u32 k_uniqueness; +} __attribute__ ((__packed__)); + +struct in_core_offset_v2 { +#ifdef __LITTLE_ENDIAN + /* little endian version */ + __u64 k_offset:60; + __u64 k_type: 4; +#else + /* big endian version */ + __u64 k_type: 4; + __u64 k_offset:60; +#endif +} __attribute__ ((__packed__)); + /* Key of an item determines its location in the S+tree, and is composed of 4 components */ struct reiserfs_key { @@ -445,9 +462,18 @@ struct reiserfs_key { } __attribute__ ((__packed__)) u; } __attribute__ ((__packed__)); +struct in_core_key { + __u32 k_dir_id; /* packing locality: by default parent + directory object id */ + __u32 k_objectid; /* object identifier */ + union { + struct in_core_offset_v1 k_offset_v1; + struct in_core_offset_v2 k_offset_v2; + } __attribute__ ((__packed__)) u; +} __attribute__ ((__packed__)); struct cpu_key { - struct reiserfs_key on_disk_key; + struct in_core_key on_disk_key; int version; int key_length; /* 3 in all cases but direct2indirect and indirect2direct conversion */ @@ -1476,7 +1502,7 @@ struct tree_balance int fs_gen; /* saved value of `reiserfs_generation' counter see FILESYSTEM_CHANGED() macro in reiserfs_fs.h */ #ifdef DISPLACE_NEW_PACKING_LOCALITIES - struct reiserfs_key key; /* key pointer, to pass to block allocator or + struct in_core_key key; /* key pointer, to pass to block allocator or another low-level subsystem */ #endif } ; @@ -2117,7 +2143,7 @@ struct buffer_head * get_FEB (struct tree_balance *); struct __reiserfs_blocknr_hint { struct inode * inode; /* inode passed to allocator, if we allocate unf. nodes */ long block; /* file offset, in blocks */ - struct reiserfs_key key; + struct in_core_key key; struct path * path; /* search path, used by allocator to deternine search_start by * various ways */ struct reiserfs_transaction_handle * th; /* transaction handle is needed to log super blocks and -- cgit v1.2.3 From 3e8962be915bacc1d70e4849a075041838d60a3f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:18 -0700 Subject: [PATCH] reiserfs endianness: annotate little-endian objects little-endian objects annotated as such; again, obviously no changes of resulting code, we only replace __u16 with __le16, etc. in relevant places. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/bitmap.c | 7 +- fs/reiserfs/dir.c | 8 +- fs/reiserfs/file.c | 4 +- fs/reiserfs/inode.c | 10 +-- fs/reiserfs/item_ops.c | 5 +- fs/reiserfs/objectid.c | 18 ++--- fs/reiserfs/procfs.c | 4 +- fs/reiserfs/stree.c | 22 ++++-- fs/reiserfs/super.c | 6 +- include/linux/reiserfs_acl.h | 12 +-- include/linux/reiserfs_fs.h | 168 ++++++++++++++++++++--------------------- include/linux/reiserfs_xattr.h | 4 +- 12 files changed, 138 insertions(+), 130 deletions(-) (limited to 'include') diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index f4f16fada14c..49c479c9454a 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -260,8 +260,9 @@ static inline int block_group_used(struct super_block *s, u32 id) { /* * the packing is returned in disk byte order */ -u32 reiserfs_choose_packing(struct inode *dir) { - u32 packing; +__le32 reiserfs_choose_packing(struct inode *dir) +{ + __le32 packing; if (TEST_OPTION(packing_groups, dir->i_sb)) { u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id); /* @@ -655,7 +656,7 @@ static int get_left_neighbor(reiserfs_blocknr_hint_t *hint) struct buffer_head * bh; struct item_head * ih; int pos_in_item; - __u32 * item; + __le32 * item; int ret = 0; if (!hint->path) /* reiserfs code can call this function w/o pointer to path diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index d1514a9b0514..fbde4b01a325 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -209,8 +209,8 @@ static int reiserfs_readdir (struct file * filp, void * dirent, filldir_t filldi /* compose directory item containing "." and ".." entries (entries are not aligned to 4 byte boundary) */ /* the last four params are LE */ -void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid) +void make_empty_dir_item_v1 (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid) { struct reiserfs_de_head * deh; @@ -242,8 +242,8 @@ void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, } /* compose directory item containing "." and ".." entries */ -void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid) +void make_empty_dir_item (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid) { struct reiserfs_de_head * deh; diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index f6860e83521d..2230afff1870 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -166,7 +166,7 @@ static int reiserfs_allocate_blocks_for_region( struct cpu_key key; // cpu key of item that we are going to deal with struct item_head *ih; // pointer to item head that we are going to deal with struct buffer_head *bh; // Buffer head that contains items that we are going to deal with - __u32 * item; // pointer to item we are going to deal with + __le32 * item; // pointer to item we are going to deal with INITIALIZE_PATH(path); // path to item, that we are going to deal with. b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored. reiserfs_blocknr_hint_t hint; // hint structure for block allocator. @@ -891,7 +891,7 @@ static int reiserfs_prepare_file_region_for_write( struct item_head *ih = NULL; // pointer to item head that we are going to deal with struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with INITIALIZE_PATH(path); // path to item, that we are going to deal with. - __u32 * item=NULL; // pointer to item we are going to deal with + __le32 * item=NULL; // pointer to item we are going to deal with int item_pos=-1; /* Position in indirect item */ diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 7543031396f4..5fdb9f97b99e 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -173,7 +173,7 @@ static inline void fix_tail_page_for_writing(struct page *page) { done already or non-hole position has been found in the indirect item */ static inline int allocation_needed (int retval, b_blocknr_t allocated, struct item_head * ih, - __u32 * item, int pos_in_item) + __le32 * item, int pos_in_item) { if (allocated) return 0; @@ -278,7 +278,7 @@ research: bh = get_last_bh (&path); ih = get_ih (&path); if (is_indirect_le_ih (ih)) { - __u32 * ind_item = (__u32 *)B_I_PITEM (bh, ih); + __le32 * ind_item = (__le32 *)B_I_PITEM (bh, ih); /* FIXME: here we could cache indirect item or part of it in the inode to avoid search_by_key in case of subsequent @@ -581,7 +581,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block, struct cpu_key key; struct buffer_head * bh, * unbh = NULL; struct item_head * ih, tmp_ih; - __u32 * item; + __le32 * item; int done; int fs_gen; struct reiserfs_transaction_handle *th = NULL; @@ -746,7 +746,7 @@ start_trans: done = 0; do { if (is_statdata_le_ih (ih)) { - __u32 unp = 0; + __le32 unp = 0; struct cpu_key tmp_key; /* indirect item has to be inserted */ @@ -2067,7 +2067,7 @@ static int map_block_for_writepage(struct inode *inode, struct item_head tmp_ih ; struct item_head *ih ; struct buffer_head *bh ; - __u32 *item ; + __le32 *item ; struct cpu_key key ; INITIALIZE_PATH(path) ; int pos_in_item ; diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c index 9cf7c13b120d..0ce33db1acdf 100644 --- a/fs/reiserfs/item_ops.c +++ b/fs/reiserfs/item_ops.c @@ -296,10 +296,11 @@ static void print_sequence (__u32 start, int len) static void indirect_print_item (struct item_head * ih, char * item) { int j; - __u32 * unp, prev = INT_MAX; + __le32 * unp; + __u32 prev = INT_MAX; int num; - unp = (__u32 *)item; + unp = (__le32 *)item; if (ih_item_len(ih) % UNFM_P_SIZE) reiserfs_warning (NULL, "indirect_print_item: invalid item len"); diff --git a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c index 0785c43a7486..bfe8e25ef293 100644 --- a/fs/reiserfs/objectid.c +++ b/fs/reiserfs/objectid.c @@ -11,13 +11,13 @@ // find where objectid map starts #define objectid_map(s,rs) (old_format_only (s) ? \ - (__u32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\ - (__u32 *)((rs) + 1)) + (__le32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\ + (__le32 *)((rs) + 1)) #ifdef CONFIG_REISERFS_CHECK -static void check_objectid_map (struct super_block * s, __u32 * map) +static void check_objectid_map (struct super_block * s, __le32 * map) { if (le32_to_cpu (map[0]) != 1) reiserfs_panic (s, "vs-15010: check_objectid_map: map corrupted: %lx", @@ -27,7 +27,7 @@ static void check_objectid_map (struct super_block * s, __u32 * map) } #else -static void check_objectid_map (struct super_block * s, __u32 * map) +static void check_objectid_map (struct super_block * s, __le32 * map) {;} #endif @@ -52,7 +52,7 @@ __u32 reiserfs_get_unused_objectid (struct reiserfs_transaction_handle *th) { struct super_block * s = th->t_super; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s); - __u32 * map = objectid_map (s, rs); + __le32 * map = objectid_map (s, rs); __u32 unused_objectid; BUG_ON (!th->t_trans_id); @@ -97,7 +97,7 @@ void reiserfs_release_objectid (struct reiserfs_transaction_handle *th, { struct super_block * s = th->t_super; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s); - __u32 * map = objectid_map (s, rs); + __le32 * map = objectid_map (s, rs); int i = 0; BUG_ON (!th->t_trans_id); @@ -172,12 +172,12 @@ int reiserfs_convert_objectid_map_v1(struct super_block *s) { int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2 ; int old_max = sb_oid_maxsize(disk_sb); struct reiserfs_super_block_v1 *disk_sb_v1 ; - __u32 *objectid_map, *new_objectid_map ; + __le32 *objectid_map, *new_objectid_map ; int i ; disk_sb_v1=(struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data); - objectid_map = (__u32 *)(disk_sb_v1 + 1) ; - new_objectid_map = (__u32 *)(disk_sb + 1) ; + objectid_map = (__le32 *)(disk_sb_v1 + 1) ; + new_objectid_map = (__le32 *)(disk_sb + 1) ; if (cur_size > new_size) { /* mark everyone used that was listed as free at the end of the objectid diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index f4ea81ae0e0f..e242ebc7f6f6 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c @@ -73,8 +73,8 @@ int reiserfs_global_version_in_proc( char *buffer, char **start, off_t offset, #define DFL( x ) D4C( rs -> s_v1.x ) #define objectid_map( s, rs ) (old_format_only (s) ? \ - (__u32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \ - (__u32 *)(rs + 1)) + (__le32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \ + (__le32 *)(rs + 1)) #define MAP( i ) D4C( objectid_map( sb, rs )[ i ] ) #define DJF( x ) le32_to_cpu( rs -> x ) diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 1d380a5da39c..15fa4cbdce3e 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -87,10 +87,11 @@ inline void copy_item_head(struct item_head * p_v_to, inline int comp_short_keys (const struct reiserfs_key * le_key, const struct cpu_key * cpu_key) { - __u32 * p_s_le_u32, * p_s_cpu_u32; + __le32 * p_s_le_u32; + __u32 * p_s_cpu_u32; int n_key_length = REISERFS_SHORT_KEY_LEN; - p_s_le_u32 = (__u32 *)le_key; + p_s_le_u32 = (__le32 *)le_key; p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key; for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) { if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 ) @@ -228,7 +229,12 @@ extern struct tree_balance * cur_tb; const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; /* Maximal possible key. It is never in the tree. */ -const struct reiserfs_key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; +const struct reiserfs_key MAX_KEY = { + __constant_cpu_to_le32(0xffffffff), + __constant_cpu_to_le32(0xffffffff), + {{__constant_cpu_to_le32(0xffffffff), + __constant_cpu_to_le32(0xffffffff)},} +}; const struct in_core_key MAX_IN_CORE_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; @@ -998,7 +1004,7 @@ static char prepare_for_delete_or_cut( int n_unfm_number, /* Number of the item unformatted nodes. */ n_counter, n_blk_size; - __u32 * p_n_unfm_pointer; /* Pointer to the unformatted node number. */ + __le32 * p_n_unfm_pointer; /* Pointer to the unformatted node number. */ __u32 tmp; struct item_head s_ih; /* Item header. */ char c_mode; /* Returned mode of the balance. */ @@ -1060,7 +1066,7 @@ static char prepare_for_delete_or_cut( /* pointers to be cut */ n_unfm_number -= pos_in_item (p_s_path); /* Set pointer to the last unformatted node pointer that is to be cut. */ - p_n_unfm_pointer = (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed; + p_n_unfm_pointer = (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed; /* We go through the unformatted nodes pointers of the indirect @@ -1082,8 +1088,8 @@ static char prepare_for_delete_or_cut( need_research = 1 ; break; } - RFALSE( p_n_unfm_pointer < (__u32 *)B_I_PITEM(p_s_bh, &s_ih) || - p_n_unfm_pointer > (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1, + RFALSE( p_n_unfm_pointer < (__le32 *)B_I_PITEM(p_s_bh, &s_ih) || + p_n_unfm_pointer > (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1, "vs-5265: pointer out of range"); /* Hole, nothing to remove. */ @@ -1432,7 +1438,7 @@ int reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inode #if defined( USE_INODE_GENERATION_COUNTER ) if( !old_format_only ( th -> t_super ) ) { - __u32 *inode_generation; + __le32 *inode_generation; inode_generation = &REISERFS_SB(th -> t_super) -> s_rs -> s_inode_generation; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index d6d1d7e2801f..2283f18aa1dc 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -216,7 +216,7 @@ static int finish_unfinished (struct super_block * s) /* reiserfs_iget needs k_dirid and k_objectid only */ item = B_I_PITEM (bh, ih); - obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__u32 *)item); + obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__le32 *)item); obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid); obj_key.on_disk_key.u.k_offset_v1.k_offset = 0; obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0; @@ -304,7 +304,7 @@ void add_save_link (struct reiserfs_transaction_handle * th, int retval; struct cpu_key key; struct item_head ih; - __u32 link; + __le32 link; BUG_ON (!th->t_trans_id); @@ -1336,7 +1336,7 @@ static int read_super_block (struct super_block * s, int offset) return 1; } - if ( rs->s_v1.s_root_block == -1 ) { + if ( rs->s_v1.s_root_block == cpu_to_le32(-1) ) { brelse(bh) ; reiserfs_warning (s, "Unfinished reiserfsck --rebuild-tree run detected. Please run\n" "reiserfsck --rebuild-tree and wait for a completion. If that fails\n" diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h index a57e973af0bd..2aef9c3f5ce8 100644 --- a/include/linux/reiserfs_acl.h +++ b/include/linux/reiserfs_acl.h @@ -5,18 +5,18 @@ #define REISERFS_ACL_VERSION 0x0001 typedef struct { - __u16 e_tag; - __u16 e_perm; - __u32 e_id; + __le16 e_tag; + __le16 e_perm; + __le32 e_id; } reiserfs_acl_entry; typedef struct { - __u16 e_tag; - __u16 e_perm; + __le16 e_tag; + __le16 e_perm; } reiserfs_acl_entry_short; typedef struct { - __u32 a_version; + __le32 a_version; } reiserfs_acl_header; static inline size_t reiserfs_acl_size(int count) diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index d0867873a1b5..cc39c5305b80 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -114,47 +114,47 @@ if( !( cond ) ) \ struct journal_params { - __u32 jp_journal_1st_block; /* where does journal start from on its + __le32 jp_journal_1st_block; /* where does journal start from on its * device */ - __u32 jp_journal_dev; /* journal device st_rdev */ - __u32 jp_journal_size; /* size of the journal */ - __u32 jp_journal_trans_max; /* max number of blocks in a transaction. */ - __u32 jp_journal_magic; /* random value made on fs creation (this + __le32 jp_journal_dev; /* journal device st_rdev */ + __le32 jp_journal_size; /* size of the journal */ + __le32 jp_journal_trans_max; /* max number of blocks in a transaction. */ + __le32 jp_journal_magic; /* random value made on fs creation (this * was sb_journal_block_count) */ - __u32 jp_journal_max_batch; /* max number of blocks to batch into a + __le32 jp_journal_max_batch; /* max number of blocks to batch into a * trans */ - __u32 jp_journal_max_commit_age; /* in seconds, how old can an async + __le32 jp_journal_max_commit_age; /* in seconds, how old can an async * commit be */ - __u32 jp_journal_max_trans_age; /* in seconds, how old can a transaction + __le32 jp_journal_max_trans_age; /* in seconds, how old can a transaction * be */ }; /* this is the super from 3.5.X, where X >= 10 */ struct reiserfs_super_block_v1 { - __u32 s_block_count; /* blocks count */ - __u32 s_free_blocks; /* free blocks count */ - __u32 s_root_block; /* root block number */ + __le32 s_block_count; /* blocks count */ + __le32 s_free_blocks; /* free blocks count */ + __le32 s_root_block; /* root block number */ struct journal_params s_journal; - __u16 s_blocksize; /* block size */ - __u16 s_oid_maxsize; /* max size of object id array, see + __le16 s_blocksize; /* block size */ + __le16 s_oid_maxsize; /* max size of object id array, see * get_objectid() commentary */ - __u16 s_oid_cursize; /* current size of object id array */ - __u16 s_umount_state; /* this is set to 1 when filesystem was + __le16 s_oid_cursize; /* current size of object id array */ + __le16 s_umount_state; /* this is set to 1 when filesystem was * umounted, to 2 - when not */ char s_magic[10]; /* reiserfs magic string indicates that * file system is reiserfs: * "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */ - __u16 s_fs_state; /* it is set to used by fsck to mark which + __le16 s_fs_state; /* it is set to used by fsck to mark which * phase of rebuilding is done */ - __u32 s_hash_function_code; /* indicate, what hash function is being use + __le32 s_hash_function_code; /* indicate, what hash function is being use * to sort names in a directory*/ - __u16 s_tree_height; /* height of disk tree */ - __u16 s_bmap_nr; /* amount of bitmap blocks needed to address + __le16 s_tree_height; /* height of disk tree */ + __le16 s_bmap_nr; /* amount of bitmap blocks needed to address * each block of file system */ - __u16 s_version; /* this field is only reliable on filesystem + __le16 s_version; /* this field is only reliable on filesystem * with non-standard journal */ - __u16 s_reserved_for_journal; /* size in blocks of journal area on main + __le16 s_reserved_for_journal; /* size in blocks of journal area on main * device, we need to keep after * making fs with non-standard journal */ } __attribute__ ((__packed__)); @@ -165,8 +165,8 @@ struct reiserfs_super_block_v1 struct reiserfs_super_block { struct reiserfs_super_block_v1 s_v1; - __u32 s_inode_generation; - __u32 s_flags; /* Right now used only by inode-attributes, if enabled */ + __le32 s_inode_generation; + __le32 s_flags; /* Right now used only by inode-attributes, if enabled */ unsigned char s_uuid[16]; /* filesystem unique identifier */ unsigned char s_label[16]; /* filesystem volume label */ char s_unused[88] ; /* zero filled by mkreiserfs and @@ -269,7 +269,7 @@ int is_reiserfs_jr (struct reiserfs_super_block * rs); #define QUOTA_EXCEEDED -6 typedef __u32 b_blocknr_t; -typedef __u32 unp_t; +typedef __le32 unp_t; struct unfm_nodeinfo { unp_t unfm_nodenum; @@ -376,8 +376,8 @@ static inline struct reiserfs_sb_info *REISERFS_SB(const struct super_block *sb) // directories use this key as well as old files // struct offset_v1 { - __u32 k_offset; - __u32 k_uniqueness; + __le32 k_offset; + __le32 k_uniqueness; } __attribute__ ((__packed__)); struct offset_v2 { @@ -453,9 +453,9 @@ struct in_core_offset_v2 { /* Key of an item determines its location in the S+tree, and is composed of 4 components */ struct reiserfs_key { - __u32 k_dir_id; /* packing locality: by default parent + __le32 k_dir_id; /* packing locality: by default parent directory object id */ - __u32 k_objectid; /* object identifier */ + __le32 k_objectid; /* object identifier */ union { struct offset_v1 k_offset_v1; struct offset_v2 k_offset_v2; @@ -534,15 +534,15 @@ struct item_head item. Note that the key, not this field, is used to determine the item type, and thus which field this union contains. */ - __u16 ih_free_space_reserved; + __le16 ih_free_space_reserved; /* Iff this is a directory item, this field equals the number of directory entries in the directory item. */ - __u16 ih_entry_count; + __le16 ih_entry_count; } __attribute__ ((__packed__)) u; - __u16 ih_item_len; /* total size of the item body */ - __u16 ih_item_location; /* an offset to the item body + __le16 ih_item_len; /* total size of the item body */ + __le16 ih_item_location; /* an offset to the item body * within the block */ - __u16 ih_version; /* 0 for all old items, 2 for new + __le16 ih_version; /* 0 for all old items, 2 for new ones. Highest bit is set by fsck temporary, cleaned after all done */ @@ -778,10 +778,10 @@ extern struct reiserfs_key root_key; /* Header of a disk block. More precisely, header of a formatted leaf or internal node, and not the header of an unformatted node. */ struct block_head { - __u16 blk_level; /* Level of a block in the tree. */ - __u16 blk_nr_item; /* Number of keys/items in a block. */ - __u16 blk_free_space; /* Block free space in bytes. */ - __u16 blk_reserved; + __le16 blk_level; /* Level of a block in the tree. */ + __le16 blk_nr_item; /* Number of keys/items in a block. */ + __le16 blk_free_space; /* Block free space in bytes. */ + __le16 blk_reserved; /* dump this in v4/planA */ struct reiserfs_key blk_right_delim_key; /* kept only for compatibility */ }; @@ -845,19 +845,19 @@ struct block_head { // struct stat_data_v1 { - __u16 sd_mode; /* file type, permissions */ - __u16 sd_nlink; /* number of hard links */ - __u16 sd_uid; /* owner */ - __u16 sd_gid; /* group */ - __u32 sd_size; /* file size */ - __u32 sd_atime; /* time of last access */ - __u32 sd_mtime; /* time file was last modified */ - __u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ + __le16 sd_mode; /* file type, permissions */ + __le16 sd_nlink; /* number of hard links */ + __le16 sd_uid; /* owner */ + __le16 sd_gid; /* group */ + __le32 sd_size; /* file size */ + __le32 sd_atime; /* time of last access */ + __le32 sd_mtime; /* time file was last modified */ + __le32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ union { - __u32 sd_rdev; - __u32 sd_blocks; /* number of blocks file uses */ + __le32 sd_rdev; + __le32 sd_blocks; /* number of blocks file uses */ } __attribute__ ((__packed__)) u; - __u32 sd_first_direct_byte; /* first byte of file which is stored + __le32 sd_first_direct_byte; /* first byte of file which is stored in a direct item: except that if it equals 1 it is a symlink and if it equals ~(__u32)0 there is no @@ -923,20 +923,20 @@ struct stat_data_v1 /* Stat Data on disk (reiserfs version of UFS disk inode minus the address blocks) */ struct stat_data { - __u16 sd_mode; /* file type, permissions */ - __u16 sd_attrs; /* persistent inode flags */ - __u32 sd_nlink; /* number of hard links */ - __u64 sd_size; /* file size */ - __u32 sd_uid; /* owner */ - __u32 sd_gid; /* group */ - __u32 sd_atime; /* time of last access */ - __u32 sd_mtime; /* time file was last modified */ - __u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ - __u32 sd_blocks; + __le16 sd_mode; /* file type, permissions */ + __le16 sd_attrs; /* persistent inode flags */ + __le32 sd_nlink; /* number of hard links */ + __le64 sd_size; /* file size */ + __le32 sd_uid; /* owner */ + __le32 sd_gid; /* group */ + __le32 sd_atime; /* time of last access */ + __le32 sd_mtime; /* time file was last modified */ + __le32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ + __le32 sd_blocks; union { - __u32 sd_rdev; - __u32 sd_generation; - //__u32 sd_first_direct_byte; + __le32 sd_rdev; + __le32 sd_generation; + //__le32 sd_first_direct_byte; /* first byte of file which is stored in a direct item: except that if it equals 1 it is a symlink and if it equals @@ -1019,12 +1019,12 @@ struct stat_data { struct reiserfs_de_head { - __u32 deh_offset; /* third component of the directory entry key */ - __u32 deh_dir_id; /* objectid of the parent directory of the object, that is referenced + __le32 deh_offset; /* third component of the directory entry key */ + __le32 deh_dir_id; /* objectid of the parent directory of the object, that is referenced by directory entry */ - __u32 deh_objectid; /* objectid of the object, that is referenced by directory entry */ - __u16 deh_location; /* offset of name in the whole item */ - __u16 deh_state; /* whether 1) entry contains stat data (for future), and 2) whether + __le32 deh_objectid; /* objectid of the object, that is referenced by directory entry */ + __le16 deh_location; /* offset of name in the whole item */ + __le16 deh_state; /* whether 1) entry contains stat data (for future), and 2) whether entry is hidden (unlinked) */ } __attribute__ ((__packed__)); #define DEH_SIZE sizeof(struct reiserfs_de_head) @@ -1084,10 +1084,10 @@ struct reiserfs_de_head #define de_visible(deh) test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) #define de_hidden(deh) !test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) -extern void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid); -extern void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid); +extern void make_empty_dir_item_v1 (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid); +extern void make_empty_dir_item (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid); /* array of the entry headers */ /* get item body */ @@ -1186,9 +1186,9 @@ struct reiserfs_dir_entry /* Disk child pointer: The pointer from an internal node of the tree to a node that is on disk. */ struct disk_child { - __u32 dc_block_number; /* Disk child's block number. */ - __u16 dc_size; /* Disk child's used space. */ - __u16 dc_reserved; + __le32 dc_block_number; /* Disk child's block number. */ + __le16 dc_size; /* Disk child's used space. */ + __le16 dc_reserved; }; #define DC_SIZE (sizeof(struct disk_child)) @@ -1656,10 +1656,10 @@ struct reiserfs_iget_args { /* first block written in a commit. */ struct reiserfs_journal_desc { - __u32 j_trans_id ; /* id of commit */ - __u32 j_len ; /* length of commit. len +1 is the commit block */ - __u32 j_mount_id ; /* mount id of this trans*/ - __u32 j_realblock[1] ; /* real locations for each block */ + __le32 j_trans_id ; /* id of commit */ + __le32 j_len ; /* length of commit. len +1 is the commit block */ + __le32 j_mount_id ; /* mount id of this trans*/ + __le32 j_realblock[1] ; /* real locations for each block */ } ; #define get_desc_trans_id(d) le32_to_cpu((d)->j_trans_id) @@ -1672,9 +1672,9 @@ struct reiserfs_journal_desc { /* last block written in a commit */ struct reiserfs_journal_commit { - __u32 j_trans_id ; /* must match j_trans_id from the desc block */ - __u32 j_len ; /* ditto */ - __u32 j_realblock[1] ; /* real locations for each block */ + __le32 j_trans_id ; /* must match j_trans_id from the desc block */ + __le32 j_len ; /* ditto */ + __le32 j_realblock[1] ; /* real locations for each block */ } ; #define get_commit_trans_id(c) le32_to_cpu((c)->j_trans_id) @@ -1689,9 +1689,9 @@ struct reiserfs_journal_commit { ** and this transaction does not need to be replayed. */ struct reiserfs_journal_header { - __u32 j_last_flush_trans_id ; /* id of last fully flushed transaction */ - __u32 j_first_unflushed_offset ; /* offset in the log of where to start replay after a crash */ - __u32 j_mount_id ; + __le32 j_last_flush_trans_id ; /* id of last fully flushed transaction */ + __le32 j_first_unflushed_offset ; /* offset in the log of where to start replay after a crash */ + __le32 j_mount_id ; /* 12 */ struct journal_params jh_journal; } ; @@ -2170,7 +2170,7 @@ void reiserfs_init_alloc_options (struct super_block *s); * to use for a new object underneat it. The locality is returned * in disk byte order (le). */ -u32 reiserfs_choose_packing(struct inode *dir); +__le32 reiserfs_choose_packing(struct inode *dir); int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value); void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *, b_blocknr_t, int for_unformatted); diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index 1eaa48eca811..9244c5748820 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h @@ -10,8 +10,8 @@ #define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */ struct reiserfs_xattr_header { - __u32 h_magic; /* magic number for identification */ - __u32 h_hash; /* hash of the value */ + __le32 h_magic; /* magic number for identification */ + __le32 h_hash; /* hash of the value */ }; #ifdef __KERNEL__ -- cgit v1.2.3 From b8cc936f6295bba23513a49d858ea82f64982faf Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:18 -0700 Subject: [PATCH] reiserfs endianness: fix endianness bugs fixes for a couple of bugs exposed by the above: le32_to_cpu() used on 16bit value and missing conversion in comparison of host- and little-endian values. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/journal.c | 2 +- include/linux/reiserfs_fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index b16d65acb550..3072cfdee959 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2391,7 +2391,7 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo jh = (struct reiserfs_journal_header *)(bhjh->b_data); /* make sure that journal matches to the super block */ - if (is_reiserfs_jr(rs) && (jh->jh_journal.jp_journal_magic != sb_jp_journal_magic(rs))) { + if (is_reiserfs_jr(rs) && (le32_to_cpu(jh->jh_journal.jp_journal_magic) != sb_jp_journal_magic(rs))) { reiserfs_warning (p_s_sb, "sh-460: journal header magic %x " "(device %s) does not match to magic found in super " "block %x", diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index cc39c5305b80..2f7a34d636dd 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -225,7 +225,7 @@ struct reiserfs_super_block #define SB_ONDISK_JOURNAL_DEVICE(s) \ le32_to_cpu ((SB_ONDISK_JP(s)->jp_journal_dev)) #define SB_ONDISK_RESERVED_FOR_JOURNAL(s) \ - le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_reserved_for_journal)) + le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_reserved_for_journal)) #define is_block_in_log_or_reserved_area(s, block) \ block >= SB_JOURNAL_1st_RESERVED_BLOCK(s) \ -- cgit v1.2.3 From 6b9f5829e6e3af44f20c681e26524c637d4f82ff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:19 -0700 Subject: [PATCH] reiserfs endianness: comp_short_keys() cleanup comp_short_keys() massaged into sane form, which kills the last place where pointer to in_core_key (or any object containing such) would be cast to or from something else. At that point we are free to change layout of in_core_key - nothing depends on it anymore. So we drop the mess with union in there and simply use (unconditional) __u64 k_offset and __u8 k_type instead; places using in_core_key switched to those. That gives _far_ better code than current mess - on all platforms. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/inode.c | 4 ++-- fs/reiserfs/stree.c | 36 ++++++++++++++------------------- fs/reiserfs/super.c | 4 ++-- include/linux/reiserfs_fs.h | 49 ++++++++------------------------------------- 4 files changed, 27 insertions(+), 66 deletions(-) (limited to 'include') diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 5fdb9f97b99e..2711dff1b7b4 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1341,8 +1341,8 @@ void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args key.version = KEY_FORMAT_3_5; key.on_disk_key.k_dir_id = dirino; key.on_disk_key.k_objectid = inode->i_ino; - key.on_disk_key.u.k_offset_v1.k_offset = SD_OFFSET; - key.on_disk_key.u.k_offset_v1.k_uniqueness = SD_UNIQUENESS; + key.on_disk_key.k_offset = 0; + key.on_disk_key.k_type = 0; /* look for the object's stat data */ retval = search_item (inode->i_sb, &key, &path_to_sd); diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 15fa4cbdce3e..da23ba75f3d5 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -87,23 +87,20 @@ inline void copy_item_head(struct item_head * p_v_to, inline int comp_short_keys (const struct reiserfs_key * le_key, const struct cpu_key * cpu_key) { - __le32 * p_s_le_u32; - __u32 * p_s_cpu_u32; - int n_key_length = REISERFS_SHORT_KEY_LEN; - - p_s_le_u32 = (__le32 *)le_key; - p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key; - for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) { - if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 ) + __u32 n; + n = le32_to_cpu(le_key->k_dir_id); + if (n < cpu_key->on_disk_key.k_dir_id) return -1; - if ( le32_to_cpu (*p_s_le_u32) > *p_s_cpu_u32 ) + if (n > cpu_key->on_disk_key.k_dir_id) + return 1; + n = le32_to_cpu(le_key->k_objectid); + if (n < cpu_key->on_disk_key.k_objectid) + return -1; + if (n > cpu_key->on_disk_key.k_objectid) return 1; - } - return 0; } - /* k1 is pointer to on-disk structure which is stored in little-endian form. k2 is pointer to cpu variable. Compare keys using all 4 key fields. @@ -153,18 +150,15 @@ inline int comp_short_le_keys (const struct reiserfs_key * key1, const struct re inline void le_key2cpu_key (struct cpu_key * to, const struct reiserfs_key * from) { + int version; to->on_disk_key.k_dir_id = le32_to_cpu (from->k_dir_id); to->on_disk_key.k_objectid = le32_to_cpu (from->k_objectid); // find out version of the key - to->version = le_key_version (from); - if (to->version == KEY_FORMAT_3_5) { - to->on_disk_key.u.k_offset_v1.k_offset = le32_to_cpu (from->u.k_offset_v1.k_offset); - to->on_disk_key.u.k_offset_v1.k_uniqueness = le32_to_cpu (from->u.k_offset_v1.k_uniqueness); - } else { - to->on_disk_key.u.k_offset_v2.k_offset = offset_v2_k_offset(&from->u.k_offset_v2); - to->on_disk_key.u.k_offset_v2.k_type = offset_v2_k_type(&from->u.k_offset_v2); - } + version = le_key_version (from); + to->version = version; + to->on_disk_key.k_offset = le_key_k_offset(version, from); + to->on_disk_key.k_type = le_key_k_type(version, from); } @@ -235,8 +229,8 @@ const struct reiserfs_key MAX_KEY = { {{__constant_cpu_to_le32(0xffffffff), __constant_cpu_to_le32(0xffffffff)},} }; -const struct in_core_key MAX_IN_CORE_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; +const struct in_core_key MAX_IN_CORE_KEY = {~0U, ~0U, ~0ULL>>4, 15}; /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom of the path, and going upwards. We must check the path's validity at each step. If the key is not in diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 2283f18aa1dc..31e75125f48b 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -218,8 +218,8 @@ static int finish_unfinished (struct super_block * s) item = B_I_PITEM (bh, ih); obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__le32 *)item); obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid); - obj_key.on_disk_key.u.k_offset_v1.k_offset = 0; - obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0; + obj_key.on_disk_key.k_offset = 0; + obj_key.on_disk_key.k_type = 0; pathrelse (&path); diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 2f7a34d636dd..d445b682ce00 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -433,23 +433,6 @@ static inline void set_offset_v2_k_offset( struct offset_v2 *v2, loff_t offset ) # define set_offset_v2_k_offset(v2,val) (offset_v2_k_offset(v2) = (val)) #endif -struct in_core_offset_v1 { - __u32 k_offset; - __u32 k_uniqueness; -} __attribute__ ((__packed__)); - -struct in_core_offset_v2 { -#ifdef __LITTLE_ENDIAN - /* little endian version */ - __u64 k_offset:60; - __u64 k_type: 4; -#else - /* big endian version */ - __u64 k_type: 4; - __u64 k_offset:60; -#endif -} __attribute__ ((__packed__)); - /* Key of an item determines its location in the S+tree, and is composed of 4 components */ struct reiserfs_key { @@ -466,11 +449,9 @@ struct in_core_key { __u32 k_dir_id; /* packing locality: by default parent directory object id */ __u32 k_objectid; /* object identifier */ - union { - struct in_core_offset_v1 k_offset_v1; - struct in_core_offset_v2 k_offset_v2; - } __attribute__ ((__packed__)) u; -} __attribute__ ((__packed__)); + __u64 k_offset; + __u8 k_type; +}; struct cpu_key { struct in_core_key on_disk_key; @@ -696,43 +677,29 @@ static inline void set_le_ih_k_type (struct item_head * ih, int type) // static inline loff_t cpu_key_k_offset (const struct cpu_key * key) { - return (key->version == KEY_FORMAT_3_5) ? - key->on_disk_key.u.k_offset_v1.k_offset : - key->on_disk_key.u.k_offset_v2.k_offset; + return key->on_disk_key.k_offset; } static inline loff_t cpu_key_k_type (const struct cpu_key * key) { - return (key->version == KEY_FORMAT_3_5) ? - uniqueness2type (key->on_disk_key.u.k_offset_v1.k_uniqueness) : - key->on_disk_key.u.k_offset_v2.k_type; + return key->on_disk_key.k_type; } static inline void set_cpu_key_k_offset (struct cpu_key * key, loff_t offset) { - (key->version == KEY_FORMAT_3_5) ? - (key->on_disk_key.u.k_offset_v1.k_offset = offset) : - (key->on_disk_key.u.k_offset_v2.k_offset = offset); + key->on_disk_key.k_offset = offset; } - static inline void set_cpu_key_k_type (struct cpu_key * key, int type) { - (key->version == KEY_FORMAT_3_5) ? - (key->on_disk_key.u.k_offset_v1.k_uniqueness = type2uniqueness (type)): - (key->on_disk_key.u.k_offset_v2.k_type = type); + key->on_disk_key.k_type = type; } - static inline void cpu_key_k_offset_dec (struct cpu_key * key) { - if (key->version == KEY_FORMAT_3_5) - key->on_disk_key.u.k_offset_v1.k_offset --; - else - key->on_disk_key.u.k_offset_v2.k_offset --; + key->on_disk_key.k_offset --; } - #define is_direntry_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRENTRY) #define is_direct_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRECT) #define is_indirect_cpu_key(key) (cpu_key_k_type (key) == TYPE_INDIRECT) -- cgit v1.2.3 From f8e08a8466c4ac5f61b4bdb6338fd97eedb9c9e8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:19 -0700 Subject: [PATCH] reiserfs endianness: sanitize reiserfs_key union Since we only access reiserfs_key ->u.k_offset_v2 guts in four helper functions, we are free to sanitize those, as long as - layout of the structure is unchanged (it's on-disk object) - behaviour of these helpers is same as before. Patch kills the mess with endianness-dependent bitfields and replaces them with a single __le64. Helpers are switched to straightforward shift/and/or. Benefits: - exact same definitions for little- and big-endian architectures; no ifdefs in sight. - generate the same code on little-endian and improved on big-endian. - doesn't rely on lousy bitfields handling in gcc codegenerator. - happens to be standard C (unsigned long long is not a valid type for a bitfield; it's a gccism and not well-implemented one, at that). Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/reiserfs_fs.h | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index d445b682ce00..32148625fc2f 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -381,57 +381,29 @@ struct offset_v1 { } __attribute__ ((__packed__)); struct offset_v2 { -#ifdef __LITTLE_ENDIAN - /* little endian version */ - __u64 k_offset:60; - __u64 k_type: 4; -#else - /* big endian version */ - __u64 k_type: 4; - __u64 k_offset:60; -#endif + __le64 v; } __attribute__ ((__packed__)); -#ifndef __LITTLE_ENDIAN -typedef union { - struct offset_v2 offset_v2; - __u64 linear; -} __attribute__ ((__packed__)) offset_v2_esafe_overlay; - static inline __u16 offset_v2_k_type( const struct offset_v2 *v2 ) { - offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2; - tmp.linear = le64_to_cpu( tmp.linear ); - return (tmp.offset_v2.k_type <= TYPE_MAXTYPE)?tmp.offset_v2.k_type:TYPE_ANY; + __u8 type = le64_to_cpu(v2->v) >> 60; + return (type <= TYPE_MAXTYPE)?type:TYPE_ANY; } static inline void set_offset_v2_k_type( struct offset_v2 *v2, int type ) { - offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2; - tmp->linear = le64_to_cpu(tmp->linear); - tmp->offset_v2.k_type = type; - tmp->linear = cpu_to_le64(tmp->linear); + v2->v = (v2->v & cpu_to_le64(~0ULL>>4)) | cpu_to_le64((__u64)type<<60); } static inline loff_t offset_v2_k_offset( const struct offset_v2 *v2 ) { - offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2; - tmp.linear = le64_to_cpu( tmp.linear ); - return tmp.offset_v2.k_offset; + return le64_to_cpu(v2->v) & (~0ULL>>4); } static inline void set_offset_v2_k_offset( struct offset_v2 *v2, loff_t offset ){ - offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2; - tmp->linear = le64_to_cpu(tmp->linear); - tmp->offset_v2.k_offset = offset; - tmp->linear = cpu_to_le64(tmp->linear); + offset &= (~0ULL>>4); + v2->v = (v2->v & cpu_to_le64(15ULL<<60)) | cpu_to_le64(offset); } -#else -# define offset_v2_k_type(v2) ((v2)->k_type) -# define set_offset_v2_k_type(v2,val) (offset_v2_k_type(v2) = (val)) -# define offset_v2_k_offset(v2) ((v2)->k_offset) -# define set_offset_v2_k_offset(v2,val) (offset_v2_k_offset(v2) = (val)) -#endif /* Key of an item determines its location in the S+tree, and is composed of 4 components */ -- cgit v1.2.3 From 7149437669f79b497830e643a2b13d26a017b038 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 1 May 2005 08:59:22 -0700 Subject: [PATCH] fbdev: Batch cmap changes at driver level This patch adds to the fbdev interface a set_cmap callback that allow the driver to "batch" palette changes. This is useful for drivers like radeonfb which might require lenghtly workarounds on palette accesses, thus allowing to factor out those workarounds efficiently. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_base.c | 118 ++++++++++++++++++++++++++++++++-------- drivers/video/fbcmap.c | 32 ++++++++++- include/linux/fb.h | 3 + 3 files changed, 127 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index e8eb124754b1..ee25b9e8db60 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1057,13 +1057,14 @@ static int radeonfb_blank (int blank, struct fb_info *info) return radeon_screen_blank(rinfo, blank, 0); } -static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, struct fb_info *info) +static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct radeonfb_info *rinfo) { - struct radeonfb_info *rinfo = info->par; u32 pindex; unsigned int i; - + + if (regno > 255) return 1; @@ -1078,20 +1079,7 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, pindex = regno; if (!rinfo->asleep) { - u32 dac_cntl2, vclk_cntl = 0; - radeon_fifo_wait(9); - if (rinfo->is_mobility) { - vclk_cntl = INPLL(VCLK_ECP_CNTL); - OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); - } - - /* Make sure we are on first palette */ - if (rinfo->has_CRTC2) { - dac_cntl2 = INREG(DAC_CNTL2); - dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL; - OUTREG(DAC_CNTL2, dac_cntl2); - } if (rinfo->bpp == 16) { pindex = regno * 8; @@ -1101,24 +1089,27 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, if (rinfo->depth == 15 && regno > 31) return 1; - /* For 565, the green component is mixed one order below */ + /* For 565, the green component is mixed one order + * below + */ if (rinfo->depth == 16) { OUTREG(PALETTE_INDEX, pindex>>1); - OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) | - (green << 8) | (rinfo->palette[regno>>1].blue)); + OUTREG(PALETTE_DATA, + (rinfo->palette[regno>>1].red << 16) | + (green << 8) | + (rinfo->palette[regno>>1].blue)); green = rinfo->palette[regno<<1].green; } } if (rinfo->depth != 16 || regno < 32) { OUTREG(PALETTE_INDEX, pindex); - OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue); + OUTREG(PALETTE_DATA, (red << 16) | + (green << 8) | blue); } - if (rinfo->is_mobility) - OUTPLL(VCLK_ECP_CNTL, vclk_cntl); } if (regno < 16) { - u32 *pal = info->pseudo_palette; + u32 *pal = rinfo->info->pseudo_palette; switch (rinfo->depth) { case 15: pal[regno] = (regno << 10) | (regno << 5) | regno; @@ -1138,6 +1129,84 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, return 0; } +static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = info->par; + u32 dac_cntl2, vclk_cntl = 0; + int rc; + + if (!rinfo->asleep) { + if (rinfo->is_mobility) { + vclk_cntl = INPLL(VCLK_ECP_CNTL); + OUTPLL(VCLK_ECP_CNTL, + vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); + } + + /* Make sure we are on first palette */ + if (rinfo->has_CRTC2) { + dac_cntl2 = INREG(DAC_CNTL2); + dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL; + OUTREG(DAC_CNTL2, dac_cntl2); + } + } + + rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo); + + if (!rinfo->asleep && rinfo->is_mobility) + OUTPLL(VCLK_ECP_CNTL, vclk_cntl); + + return rc; +} + +static int radeonfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) +{ + struct radeonfb_info *rinfo = info->par; + u16 *red, *green, *blue, *transp; + u32 dac_cntl2, vclk_cntl = 0; + int i, start, rc = 0; + + if (!rinfo->asleep) { + if (rinfo->is_mobility) { + vclk_cntl = INPLL(VCLK_ECP_CNTL); + OUTPLL(VCLK_ECP_CNTL, + vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); + } + + /* Make sure we are on first palette */ + if (rinfo->has_CRTC2) { + dac_cntl2 = INREG(DAC_CNTL2); + dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL; + OUTREG(DAC_CNTL2, dac_cntl2); + } + } + + red = cmap->red; + green = cmap->green; + blue = cmap->blue; + transp = cmap->transp; + start = cmap->start; + + for (i = 0; i < cmap->len; i++) { + u_int hred, hgreen, hblue, htransp = 0xffff; + + hred = *red++; + hgreen = *green++; + hblue = *blue++; + if (transp) + htransp = *transp++; + rc = radeon_setcolreg (start++, hred, hgreen, hblue, htransp, + rinfo); + if (rc) + break; + } + + if (!rinfo->asleep && rinfo->is_mobility) + OUTPLL(VCLK_ECP_CNTL, vclk_cntl); + + return rc; +} static void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save) @@ -1796,6 +1865,7 @@ static struct fb_ops radeonfb_ops = { .fb_check_var = radeonfb_check_var, .fb_set_par = radeonfb_set_par, .fb_setcolreg = radeonfb_setcolreg, + .fb_setcmap = radeonfb_setcmap, .fb_pan_display = radeonfb_pan_display, .fb_blank = radeonfb_blank, .fb_ioctl = radeonfb_ioctl, diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index c51f8fb5c1de..4e5ce8f7d65e 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -222,8 +222,11 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info) transp = cmap->transp; start = cmap->start; - if (start < 0 || !info->fbops->fb_setcolreg) + if (start < 0 || (!info->fbops->fb_setcolreg && + !info->fbops->fb_setcmap)) return -EINVAL; + if (info->fbops->fb_setcmap) + return info->fbops->fb_setcmap(cmap, info); for (i = 0; i < cmap->len; i++) { hred = *red++; hgreen = *green++; @@ -250,8 +253,33 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) transp = cmap->transp; start = cmap->start; - if (start < 0 || !info->fbops->fb_setcolreg) + if (start < 0 || (!info->fbops->fb_setcolreg && + !info->fbops->fb_setcmap)) return -EINVAL; + + /* If we can batch, do it */ + if (info->fbops->fb_setcmap && cmap->len > 1) { + struct fb_cmap umap; + int size = cmap->len * sizeof(u16); + int rc; + + memset(&umap, 0, sizeof(struct fb_cmap)); + rc = fb_alloc_cmap(&umap, cmap->len, transp != NULL); + if (rc) + return rc; + if (copy_from_user(umap.red, red, size) || + copy_from_user(umap.green, green, size) || + copy_from_user(umap.blue, blue, size) || + (transp && copy_from_user(umap.transp, transp, size))) { + rc = -EFAULT; + } + umap.start = start; + if (rc == 0) + rc = info->fbops->fb_setcmap(&umap, info); + fb_dealloc_cmap(&umap); + return rc; + } + for (i = 0; i < cmap->len; i++, red++, blue++, green++) { if (get_user(hred, red) || get_user(hgreen, green) || diff --git a/include/linux/fb.h b/include/linux/fb.h index b45d3e2d711a..b468bf496547 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -563,6 +563,9 @@ struct fb_ops { int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info); + /* set color registers in batch */ + int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); + /* blank display */ int (*fb_blank)(int blank, struct fb_info *info); -- cgit v1.2.3 From 5f76be80d96f60adfc91f2acf22b146ce0e3072f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 1 May 2005 08:59:23 -0700 Subject: [PATCH] fbdev: edid.h cleanups This patch removes some completely unused code. Signed-off-by: Adrian Bunk Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/boot/compressed/misc.c | 1 - drivers/video/fbmon.c | 1 - drivers/video/vesafb.c | 3 --- include/video/edid.h | 9 --------- 4 files changed, 14 deletions(-) (limited to 'include') diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index fa67045234a3..cedc55cc47de 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -12,7 +12,6 @@ #include #include #include -#include