From bafe68034e3ef5e9f512bd0468001caf34981c41 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 10 Mar 2008 12:56:12 +0100 Subject: avr32: Work around byteswap bug in gcc < 4.2 gcc versions earlier than 4.2 sign-extends the result of le16_to_cpu() and friends when we implement __arch__swabX() using __builtin_bswap_X(). Disable our arch-specific optimizations when those gcc versions are being used. Signed-off-by: Haavard Skinnemoen --- include/asm-avr32/byteorder.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/asm-avr32/byteorder.h b/include/asm-avr32/byteorder.h index 402ff4125cdc..d77b48ba7338 100644 --- a/include/asm-avr32/byteorder.h +++ b/include/asm-avr32/byteorder.h @@ -12,8 +12,14 @@ extern unsigned long __builtin_bswap_32(unsigned long x); extern unsigned short __builtin_bswap_16(unsigned short x); #endif +/* + * avr32-linux-gcc versions earlier than 4.2 improperly sign-extends + * the result. + */ +#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2) #define __arch__swab32(x) __builtin_bswap_32(x) #define __arch__swab16(x) __builtin_bswap_16(x) +#endif #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) # define __BYTEORDER_HAS_U64__ -- cgit v1.2.3 From 6dba1b67601685ff00ef5d08cc4f11db00cff598 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 14 Mar 2008 17:21:09 +0900 Subject: sh: Fix more user header breakage from sh64 integration. posix_types.h and byteorder.h were sticking purely with the Kconfig symbols, which doesn't work when we scrub the headers for user use. Fixes a very unhelpful build error in current klibc. Signed-off-by: Paul Mundt --- include/asm-sh/byteorder.h | 15 +++++++-------- include/asm-sh/posix_types.h | 6 ++++++ 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/asm-sh/byteorder.h b/include/asm-sh/byteorder.h index 0eb9904b6545..4c13e6117563 100644 --- a/include/asm-sh/byteorder.h +++ b/include/asm-sh/byteorder.h @@ -11,13 +11,13 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { __asm__( -#ifdef CONFIG_SUPERH32 +#ifdef __SH5__ + "byterev %0, %0\n\t" + "shari %0, 32, %0" +#else "swap.b %0, %0\n\t" "swap.w %0, %0\n\t" "swap.b %0, %0" -#else - "byterev %0, %0\n\t" - "shari %0, 32, %0" #endif : "=r" (x) : "0" (x)); @@ -28,12 +28,11 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) static inline __attribute_const__ __u16 ___arch__swab16(__u16 x) { __asm__( -#ifdef CONFIG_SUPERH32 - "swap.b %0, %0" -#else +#ifdef __SH5__ "byterev %0, %0\n\t" "shari %0, 32, %0" - +#else + "swap.b %0, %0" #endif : "=r" (x) : "0" (x)); diff --git a/include/asm-sh/posix_types.h b/include/asm-sh/posix_types.h index 4b9d11c9fc77..4eeb723aee7e 100644 --- a/include/asm-sh/posix_types.h +++ b/include/asm-sh/posix_types.h @@ -4,4 +4,10 @@ # else # include "posix_types_64.h" # endif +#else +# ifdef __SH5__ +# include "posix_types_64.h" +# else +# include "posix_types_32.h" +# endif #endif /* __KERNEL__ */ -- cgit v1.2.3 From 2af3e6017e53065ddf40bb19190a29199b7ffee3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 6 Mar 2008 16:02:42 +0100 Subject: The ps2esdi driver was marked as BROKEN more than two years ago due to being no longer working for some time. A driver that had been marked as BROKEN for such a long time seems to be unlikely to be revived in the forseeable future. But if anyone wants to ever revive this driver, the code is still present in the older kernel releases. Signed-off-by: Adrian Bunk Acked-by: Alan Cox Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- Documentation/mca.txt | 17 +- drivers/block/Kconfig | 10 - drivers/block/Makefile | 1 - drivers/block/ps2esdi.c | 1079 ----------------------------------------------- include/linux/Kbuild | 1 - include/linux/ps2esdi.h | 98 ----- 6 files changed, 5 insertions(+), 1201 deletions(-) delete mode 100644 drivers/block/ps2esdi.c delete mode 100644 include/linux/ps2esdi.h (limited to 'include') diff --git a/Documentation/mca.txt b/Documentation/mca.txt index aabce4ad90f9..510375d4209a 100644 --- a/Documentation/mca.txt +++ b/Documentation/mca.txt @@ -143,14 +143,7 @@ MCA Device Drivers Currently, there are a number of MCA-specific device drivers. -1) PS/2 ESDI - drivers/block/ps2esdi.c - include/linux/ps2esdi.h - Uses major number 36, and should use /dev files /dev/eda, /dev/edb. - Supports two drives, but only one controller. May use the - command-line args "ed=cyl,head,sec" and "tp720". - -2) PS/2 SCSI +1) PS/2 SCSI drivers/scsi/ibmmca.c drivers/scsi/ibmmca.h The driver for the IBM SCSI subsystem. Includes both integrated @@ -159,25 +152,25 @@ Currently, there are a number of MCA-specific device drivers. machine with a front-panel display (i.e. model 95), you can use "ibmmcascsi=display" to enable a drive activity indicator. -3) 3c523 +2) 3c523 drivers/net/3c523.c drivers/net/3c523.h 3Com 3c523 Etherlink/MC ethernet driver. -4) SMC Ultra/MCA and IBM Adapter/A +3) SMC Ultra/MCA and IBM Adapter/A drivers/net/smc-mca.c drivers/net/smc-mca.h Driver for the MCA version of the SMC Ultra and various other OEM'ed and work-alike cards (Elite, Adapter/A, etc). -5) NE/2 +4) NE/2 driver/net/ne2.c driver/net/ne2.h The NE/2 is the MCA version of the NE2000. This may not work with clones that have a different adapter id than the original NE/2. -6) Future Domain MCS-600/700, OEM'd IBM Fast SCSI Adapter/A and +5) Future Domain MCS-600/700, OEM'd IBM Fast SCSI Adapter/A and Reply Sound Blaster/SCSI (SCSI part) Better support for these cards than the driver for ISA. Supports multiple cards with IRQ sharing. diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b6d230b3209f..0d1d2133d9bc 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -44,16 +44,6 @@ config MAC_FLOPPY If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) floppy controller, say Y here. Most commonly found in PowerMacs. -config BLK_DEV_PS2 - tristate "PS/2 ESDI hard disk support" - depends on MCA && MCA_LEGACY && BROKEN - help - Say Y here if you have a PS/2 machine with a MCA bus and an ESDI - hard disk. - - To compile this driver as a module, choose M here: the - module will be called ps2esdi. - config AMIGA_Z2RAM tristate "Amiga Zorro II ramdisk support" depends on ZORRO diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 01c972415cb2..5e584306be99 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o obj-$(CONFIG_BLK_DEV_LOOP) += loop.o -obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o obj-$(CONFIG_BLK_DEV_XD) += xd.o obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c deleted file mode 100644 index 3c796e236253..000000000000 --- a/drivers/block/ps2esdi.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* ps2esdi driver based on assembler code by Arindam Banerji, - written by Peter De Schrijver */ -/* Reassuring note to IBM : This driver was NOT developed by vice-versa - engineering the PS/2's BIOS */ -/* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those - other lovely fish out there... */ -/* This code was written during the long and boring WINA - elections 1994 */ -/* Thanks to Arindam Banerij for giving me the source of his driver */ -/* This code may be freely distributed and modified in any way, - as long as these notes remain intact */ - -/* Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */ -/* Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be) - Thanks to Arindam Banerij for sending me the docs of the adapter */ - -/* BA Modified for ThinkPad 720 by Boris Ashkinazi */ -/* (bash@vnet.ibm.com) 08/08/95 */ - -/* Modified further for ThinkPad-720C by Uri Blumenthal */ -/* (uri@watson.ibm.com) Sep 11, 1995 */ - -/* TODO : - + Timeouts - + Get disk parameters - + DMA above 16MB - + reset after read/write error - */ - -#define DEVICE_NAME "PS/2 ESDI" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define PS2ESDI_IRQ 14 -#define MAX_HD 2 -#define MAX_RETRIES 5 -#define MAX_16BIT 65536 -#define ESDI_TIMEOUT 0xf000 -#define ESDI_STAT_TIMEOUT 4 - -#define TYPE_0_CMD_BLK_LENGTH 2 -#define TYPE_1_CMD_BLK_LENGTH 4 - -static void reset_ctrl(void); - -static int ps2esdi_geninit(void); - -static void do_ps2esdi_request(struct request_queue * q); - -static void ps2esdi_readwrite(int cmd, struct request *req); - -static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, -u_short cyl, u_short head, u_short sector, u_short length, u_char drive); - -static int ps2esdi_out_cmd_blk(u_short * cmd_blk); - -static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode); - -static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id); -static void (*current_int_handler) (u_int) = NULL; -static void ps2esdi_normal_interrupt_handler(u_int); -static void ps2esdi_initial_reset_int_handler(u_int); -static void ps2esdi_geometry_int_handler(u_int); -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo); - -static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); - -static void dump_cmd_complete_status(u_int int_ret_code); - -static void ps2esdi_get_device_cfg(void); - -static void ps2esdi_reset_timer(unsigned long unused); - -static u_int dma_arb_level; /* DMA arbitration level */ - -static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); - -static int no_int_yet; -static int ps2esdi_drives; -static u_short io_base; -static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0); -static int reset_status; -static int ps2esdi_slot = -1; -static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ -static int intg_esdi = 0; /* If integrated adapter */ -struct ps2esdi_i_struct { - unsigned int head, sect, cyl, wpcom, lzone, ctl; -}; -static DEFINE_SPINLOCK(ps2esdi_lock); -static struct request_queue *ps2esdi_queue; -static struct request *current_req; - -#if 0 -#if 0 /* try both - I don't know which one is better... UB */ -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {4, 48, 1553, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; -#else -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {64, 32, 161, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; -#endif -#endif -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; - -static struct block_device_operations ps2esdi_fops = -{ - .owner = THIS_MODULE, - .getgeo = ps2esdi_getgeo, -}; - -static struct gendisk *ps2esdi_gendisk[2]; - -/* initialization routine called by ll_rw_blk.c */ -static int __init ps2esdi_init(void) -{ - - int error = 0; - - /* register the device - pass the name and major number */ - if (register_blkdev(PS2ESDI_MAJOR, "ed")) - return -EBUSY; - - /* set up some global information - indicating device specific info */ - ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock); - if (!ps2esdi_queue) { - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - return -ENOMEM; - } - - /* some minor housekeeping - setup the global gendisk structure */ - error = ps2esdi_geninit(); - if (error) { - printk(KERN_WARNING "PS2ESDI: error initialising" - " device, releasing resources\n"); - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - blk_cleanup_queue(ps2esdi_queue); - return error; - } - return 0; -} /* ps2esdi_init */ - -#ifndef MODULE - -module_init(ps2esdi_init); - -#else - -static int cyl[MAX_HD] = {-1,-1}; -static int head[MAX_HD] = {-1, -1}; -static int sect[MAX_HD] = {-1, -1}; - -module_param(tp720esdi, bool, 0); -module_param_array(cyl, int, NULL, 0); -module_param_array(head, int, NULL, 0); -module_param_array(sect, int, NULL, 0); -MODULE_LICENSE("GPL"); - -int init_module(void) { - int drive; - - for(drive = 0; drive < MAX_HD; drive++) { - struct ps2esdi_i_struct *info = &ps2esdi_info[drive]; - - if (cyl[drive] != -1) { - info->cyl = info->lzone = cyl[drive]; - info->wpcom = 0; - } - if (head[drive] != -1) { - info->head = head[drive]; - info->ctl = (head[drive] > 8 ? 8 : 0); - } - if (sect[drive] != -1) info->sect = sect[drive]; - } - return ps2esdi_init(); -} - -void -cleanup_module(void) { - int i; - if(ps2esdi_slot) { - mca_mark_as_unused(ps2esdi_slot); - mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); - } - release_region(io_base, 4); - free_dma(dma_arb_level); - free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - blk_cleanup_queue(ps2esdi_queue); - for (i = 0; i < ps2esdi_drives; i++) { - del_gendisk(ps2esdi_gendisk[i]); - put_disk(ps2esdi_gendisk[i]); - } -} -#endif /* MODULE */ - -/* handles boot time command line parameters */ -void __init tp720_setup(char *str, int *ints) -{ - /* no params, just sets the tp720esdi flag if it exists */ - - printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME); - tp720esdi = 1; -} - -void __init ed_setup(char *str, int *ints) -{ - int hdind = 0; - - /* handles 3 parameters only - corresponding to - 1. Number of cylinders - 2. Number of heads - 3. Sectors/track - */ - - if (ints[0] != 3) - return; - - /* print out the information - seen at boot time */ - printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n", - DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]); - - /* set the index into device specific information table */ - if (ps2esdi_info[0].head != 0) - hdind = 1; - - /* set up all the device information */ - ps2esdi_info[hdind].head = ints[2]; - ps2esdi_info[hdind].sect = ints[3]; - ps2esdi_info[hdind].cyl = ints[1]; - ps2esdi_info[hdind].wpcom = 0; - ps2esdi_info[hdind].lzone = ints[1]; - ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); -#if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */ - ps2esdi_drives = hdind + 1; /* increment index for the next time */ -#endif -} /* ed_setup */ - -static int ps2esdi_getinfo(char *buf, int slot, void *d) -{ - int len = 0; - - len += sprintf(buf + len, "DMA Arbitration Level: %d\n", - dma_arb_level); - len += sprintf(buf + len, "IO Port: %x\n", io_base); - len += sprintf(buf + len, "IRQ: 14\n"); - len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives); - - return len; -} - -/* ps2 esdi specific initialization - called thru the gendisk chain */ -static int __init ps2esdi_geninit(void) -{ - /* - The first part contains the initialization code - for the ESDI disk subsystem. All we really do - is search for the POS registers of the controller - to do some simple setup operations. First, we - must ensure that the controller is installed, - enabled, and configured as PRIMARY. Then we must - determine the DMA arbitration level being used by - the controller so we can handle data transfer - operations properly. If all of this works, then - we will set the INIT_FLAG to a non-zero value. - */ - - int slot = 0, i, reset_start, reset_end; - u_char status; - unsigned short adapterID; - int error = 0; - - if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) { - adapterID = INTG_ESDI_ID; - printk("%s: integrated ESDI adapter found in slot %d\n", - DEVICE_NAME, slot+1); -#ifndef MODULE - mca_set_adapter_name(slot, "PS/2 Integrated ESDI"); -#endif - } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) { - adapterID = NRML_ESDI_ID; - printk("%s: normal ESDI adapter found in slot %d\n", - DEVICE_NAME, slot+1); - mca_set_adapter_name(slot, "PS/2 ESDI"); - } else { - return -ENODEV; - } - - ps2esdi_slot = slot; - mca_mark_as_used(slot); - mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL); - - /* Found the slot - read the POS register 2 to get the necessary - configuration and status information. POS register 2 has the - following information : - Bit Function - 7 reserved = 0 - 6 arbitration method - 0 - fairness enabled - 1 - fairness disabled, linear priority assignment - 5-2 arbitration level - 1 alternate address - 1 alternate address - 0 - use addresses 0x3510 - 0x3517 - 0 adapter enable - */ - - status = mca_read_stored_pos(slot, 2); - /* is it enabled ? */ - if (!(status & STATUS_ENABLED)) { - printk("%s: ESDI adapter disabled\n", DEVICE_NAME); - error = -ENODEV; - goto err_out1; - } - /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can - share with the SCSI driver */ - if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, - IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) - && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, - IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) - ) { - printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ); - error = -EBUSY; - goto err_out1; - } - if (status & STATUS_ALTERNATE) - io_base = ALT_IO_BASE; - else - io_base = PRIMARY_IO_BASE; - - if (!request_region(io_base, 4, "ed")) { - printk(KERN_WARNING"Unable to request region 0x%x\n", io_base); - error = -EBUSY; - goto err_out2; - } - /* get the dma arbitration level */ - dma_arb_level = (status >> 2) & 0xf; - - /* BA */ - printk("%s: DMA arbitration level : %d\n", - DEVICE_NAME, dma_arb_level); - - LITE_ON; - current_int_handler = ps2esdi_initial_reset_int_handler; - reset_ctrl(); - reset_status = 0; - reset_start = jiffies; - while (!reset_status) { - init_timer(&esdi_timer); - esdi_timer.expires = jiffies + HZ; - esdi_timer.data = 0; - add_timer(&esdi_timer); - sleep_on(&ps2esdi_int); - } - reset_end = jiffies; - LITE_OFF; - printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n", - DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ, - (reset_end - reset_start) % HZ); - - - /* Integrated ESDI Disk and Controller has only one drive! */ - if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */ - ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1; - } - - - - /* finally this part sets up some global data structures etc. */ - - ps2esdi_get_device_cfg(); - - /* some annoyance in the above routine returns TWO drives? - Is something else happining in the background? - Regaurdless we fix the # of drives again. AJK */ - /* Integrated ESDI Disk and Controller has only one drive! */ - if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */ - ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */ - - current_int_handler = ps2esdi_normal_interrupt_handler; - - if (request_dma(dma_arb_level, "ed") !=0) { - printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n" - ,(int) dma_arb_level); - error = -EBUSY; - goto err_out3; - } - blk_queue_max_sectors(ps2esdi_queue, 128); - - error = -ENOMEM; - for (i = 0; i < ps2esdi_drives; i++) { - struct gendisk *disk = alloc_disk(64); - if (!disk) - goto err_out4; - disk->major = PS2ESDI_MAJOR; - disk->first_minor = i<<6; - sprintf(disk->disk_name, "ed%c", 'a'+i); - disk->fops = &ps2esdi_fops; - ps2esdi_gendisk[i] = disk; - } - - for (i = 0; i < ps2esdi_drives; i++) { - struct gendisk *disk = ps2esdi_gendisk[i]; - set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect * - ps2esdi_info[i].cyl); - disk->queue = ps2esdi_queue; - disk->private_data = &ps2esdi_info[i]; - add_disk(disk); - } - return 0; -err_out4: - while (i--) - put_disk(ps2esdi_gendisk[i]); -err_out3: - release_region(io_base, 4); -err_out2: - free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); -err_out1: - if(ps2esdi_slot) { - mca_mark_as_unused(ps2esdi_slot); - mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); - } - return error; -} - -static void __init ps2esdi_get_device_cfg(void) -{ - u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; - - /*BA */ printk("%s: Drive 0\n", DEVICE_NAME); - current_int_handler = ps2esdi_geometry_int_handler; - cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600; - cmd_blk[1] = 0; - no_int_yet = TRUE; - ps2esdi_out_cmd_blk(cmd_blk); - if (no_int_yet) - sleep_on(&ps2esdi_int); - - if (ps2esdi_drives > 1) { - printk("%s: Drive 1\n", DEVICE_NAME); /*BA */ - cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600; - cmd_blk[1] = 0; - no_int_yet = TRUE; - ps2esdi_out_cmd_blk(cmd_blk); - if (no_int_yet) - sleep_on(&ps2esdi_int); - } /* if second physical drive is present */ - return; -} - -/* strategy routine that handles most of the IO requests */ -static void do_ps2esdi_request(struct request_queue * q) -{ - struct request *req; - /* since, this routine is called with interrupts cleared - they - must be before it finishes */ - - req = elv_next_request(q); - if (!req) - return; - -#if 0 - printk("%s:got request. device : %s command : %d sector : %ld count : %ld, buffer: %p\n", - DEVICE_NAME, - req->rq_disk->disk_name, - req->cmd, req->sector, - req->current_nr_sectors, req->buffer); -#endif - - /* check for above 16Mb dmas */ - if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) { - printk("%s: DMA above 16MB not supported\n", DEVICE_NAME); - end_request(req, FAIL); - return; - } - - if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) { - printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n", - ps2esdi_drives, req->sector, - (unsigned long long)get_capacity(req->rq_disk)); - end_request(req, FAIL); - return; - } - - switch (rq_data_dir(req)) { - case READ: - ps2esdi_readwrite(READ, req); - break; - case WRITE: - ps2esdi_readwrite(WRITE, req); - break; - default: - printk("%s: Unknown command\n", req->rq_disk->disk_name); - end_request(req, FAIL); - break; - } /* handle different commands */ -} /* main strategy routine */ - -/* resets the ESDI adapter */ -static void reset_ctrl(void) -{ - - u_long expire; - u_short status; - - /* enable interrupts on the controller */ - status = inb(ESDI_INTRPT); - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have - any interrupt pending... */ - outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL); - - /* read the ESDI status port - if the controller is not busy, - simply do a soft reset (fast) - otherwise we'll have to do a - hard (slow) reset. */ - if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) { - /*BA */ printk("%s: soft reset...\n", DEVICE_NAME); - outb_p(CTRL_SOFT_RESET, ESDI_ATTN); - } - /* soft reset */ - else { - /*BA */ - printk("%s: hard reset...\n", DEVICE_NAME); - outb_p(CTRL_HARD_RESET, ESDI_CONTROL); - expire = jiffies + 2*HZ; - while (time_before(jiffies, expire)); - outb_p(1, ESDI_CONTROL); - } /* hard reset */ - - -} /* reset the controller */ - -/* called by the strategy routine to handle read and write requests */ -static void ps2esdi_readwrite(int cmd, struct request *req) -{ - struct ps2esdi_i_struct *p = req->rq_disk->private_data; - unsigned block = req->sector; - unsigned count = req->current_nr_sectors; - int drive = p - ps2esdi_info; - u_short track, head, cylinder, sector; - u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH]; - - /* do some relevant arithmatic */ - track = block / p->sect; - head = track % p->head; - cylinder = track / p->head; - sector = block % p->sect; - -#if 0 - printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector); -#endif - /* call the routine that actually fills out a command block */ - ps2esdi_fill_cmd_block - (cmd_blk, - (cmd == READ) ? CMD_READ : CMD_WRITE, - cylinder, head, sector, count, drive); - - /* send the command block to the controller */ - current_req = req; - spin_unlock_irq(&ps2esdi_lock); - if (ps2esdi_out_cmd_blk(cmd_blk)) { - spin_lock_irq(&ps2esdi_lock); - printk("%s: Controller failed\n", DEVICE_NAME); - if ((++req->errors) >= MAX_RETRIES) - end_request(req, FAIL); - } - /* check for failure to put out the command block */ - else { - spin_lock_irq(&ps2esdi_lock); -#if 0 - printk("%s: waiting for xfer\n", DEVICE_NAME); -#endif - /* turn disk lights on */ - LITE_ON; - } - -} /* ps2esdi_readwrite */ - -/* fill out the command block */ -static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, - u_short cyl, u_short head, u_short sector, u_short length, u_char drive) -{ - - cmd_blk[0] = (drive << 5) | cmd; - cmd_blk[1] = length; - cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector; - cmd_blk[3] = (cyl & 0x3E0) >> 5; - -} /* fill out the command block */ - -/* write a command block to the controller */ -static int ps2esdi_out_cmd_blk(u_short * cmd_blk) -{ - - int i; - unsigned long jif; - u_char status; - - /* enable interrupts */ - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - - /* do not write to the controller, if it is busy */ - for (jif = jiffies + ESDI_STAT_TIMEOUT; - time_after(jif, jiffies) && - (inb(ESDI_STATUS) & STATUS_BUSY); ) - ; - -#if 0 - printk("%s: i(1)=%ld\n", DEVICE_NAME, jif); -#endif - - /* if device is still busy - then just time out */ - if (inb(ESDI_STATUS) & STATUS_BUSY) { - printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME); - return ERROR; - } /* timeout ??? */ - /* Set up the attention register in the controller */ - outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN); - -#if 0 - printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1); -#endif - - /* one by one send each word out */ - for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) { - status = inb(ESDI_STATUS); - for (jif = jiffies + ESDI_STAT_TIMEOUT; - time_after(jif, jiffies) && (status & STATUS_BUSY) && - (status & STATUS_CMD_INF); status = inb(ESDI_STATUS)); - if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) { -#if 0 - printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk); -#endif - outw(*cmd_blk++, ESDI_CMD_INT); - } else { - printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n", - DEVICE_NAME, status); - return ERROR; - } - } /* send all words out */ - return OK; -} /* send out the commands */ - - -/* prepare for dma - do all the necessary setup */ -static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode) -{ - unsigned long flags = claim_dma_lock(); - - mca_disable_dma(dma_arb_level); - - mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer)); - - mca_set_dma_count(dma_arb_level, length * 512 / 2); - - mca_set_dma_mode(dma_arb_level, dma_xmode); - - mca_enable_dma(dma_arb_level); - - release_dma_lock(flags); - -} /* prepare for dma */ - - - -static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id) -{ - u_int int_ret_code; - - if (inb(ESDI_STATUS) & STATUS_INTR) { - int_ret_code = inb(ESDI_INTRPT); - if (current_int_handler) { - /* Disable adapter interrupts till processing is finished */ - outb(CTRL_DISABLE_INTR, ESDI_CONTROL); - current_int_handler(int_ret_code); - } else - printk("%s: help ! No interrupt handler.\n", DEVICE_NAME); - } else { - return IRQ_NONE; - } - return IRQ_HANDLED; -} - -static void ps2esdi_initial_reset_int_handler(u_int int_ret_code) -{ - - switch (int_ret_code & 0xf) { - case INT_RESET: - /*BA */ - printk("%s: initial reset completed.\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - wake_up(&ps2esdi_int); - break; - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS)); - break; - default: - printk("%s: initial reset handler received interrupt: %02X\n", - DEVICE_NAME, int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); -} - - -static void ps2esdi_geometry_int_handler(u_int int_ret_code) -{ - u_int status, drive_num; - unsigned long rba; - int i; - - drive_num = int_ret_code >> 5; - switch (int_ret_code & 0xf) { - case INT_CMD_COMPLETE: - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - status = inw(ESDI_STT_INT); - if ((status & 0x1F) == CMD_GET_DEV_CONFIG) { -#define REPLY_WORDS 5 /* we already read word 0 */ - u_short reply[REPLY_WORDS]; - - if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) { - /*BA */ - printk("%s: Device Configuration Status for drive %u\n", - DEVICE_NAME, drive_num); - - printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8); - - printk - ("Config bits: %s%s%s%s%s\n", - (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", - ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) - ? "Zero Defect, " : "Defects Present, ", - (reply[0] & CONFIG_SF) ? "Skewed Format, " : "", - (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ", - (reply[0] & CONFIG_RT) ? "No Retries" : "Retries"); - - rba = reply[1] | ((unsigned long) reply[2] << 16); - printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba); - - printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n", - DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff); - - if (!ps2esdi_info[drive_num].head) { - ps2esdi_info[drive_num].head = 64; - ps2esdi_info[drive_num].sect = 32; - ps2esdi_info[drive_num].cyl = rba / (64 * 32); - ps2esdi_info[drive_num].wpcom = 0; - ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl; - ps2esdi_info[drive_num].ctl = 8; - if (tp720esdi) { /* store the retrieved parameters */ - ps2esdi_info[0].head = reply[4] & 0Xff; - ps2esdi_info[0].sect = reply[4] >> 8; - ps2esdi_info[0].cyl = reply[3]; - ps2esdi_info[0].wpcom = 0; - ps2esdi_info[0].lzone = reply[3]; - } else { - if (!intg_esdi) - ps2esdi_drives++; - } - } -#ifdef OBSOLETE - if (!ps2esdi_info[drive_num].head) { - ps2esdi_info[drive_num].head = reply[4] & 0Xff; - ps2esdi_info[drive_num].sect = reply[4] >> 8; - ps2esdi_info[drive_num].cyl = reply[3]; - ps2esdi_info[drive_num].wpcom = 0; - ps2esdi_info[drive_num].lzone = reply[3]; - if (tp720esdi) { /* store the retrieved parameters */ - ps2esdi_info[0].head = reply[4] & 0Xff; - ps2esdi_info[0].sect = reply[4] >> 8; - ps2esdi_info[0].cyl = reply[3]; - ps2esdi_info[0].wpcom = 0; - ps2esdi_info[0].lzone = reply[3]; - } else { - ps2esdi_drives++; - } - } -#endif - - } else - printk("%s: failed while getting device config\n", DEVICE_NAME); -#undef REPLY_WORDS - } else - printk("%s: command %02X unknown by geometry handler\n", - DEVICE_NAME, status & 0x1f); - - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - printk("%s: Device not available\n", DEVICE_NAME); - break; - case INT_CMD_ECC: - case INT_CMD_RETRY: - case INT_CMD_ECC_RETRY: - case INT_CMD_WARNING: - case INT_CMD_ABORT: - case INT_CMD_FAILED: - case INT_DMA_ERR: - case INT_CMD_BLK_ERR: - /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME); - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - default: - printk("%s: Unknown interrupt reason: %02X\n", - DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - - wake_up(&ps2esdi_int); - no_int_yet = FALSE; - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - -} - -static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) -{ - unsigned long flags; - u_int status; - u_int ending; - int i; - - switch (int_ret_code & 0x0f) { - case INT_TRANSFER_REQ: - ps2esdi_prep_dma(current_req->buffer, - current_req->current_nr_sectors, - (rq_data_dir(current_req) == READ) - ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER - : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ); - outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = FAIL; - break; - - case INT_CMD_COMPLETE: - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - if ((++current_req->errors) >= MAX_RETRIES) - ending = FAIL; - else - ending = -1; - break; - } - status = inw(ESDI_STT_INT); - switch (status & 0x1F) { - case (CMD_READ & 0xff): - case (CMD_WRITE & 0xff): - LITE_OFF; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = SUCCES; - break; - default: - printk("%s: interrupt for unknown command %02X\n", - DEVICE_NAME, status & 0x1f); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - } - break; - case INT_CMD_ECC: - case INT_CMD_RETRY: - case INT_CMD_ECC_RETRY: - LITE_OFF; - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = SUCCES; - break; - case INT_CMD_WARNING: - case INT_CMD_ABORT: - case INT_CMD_FAILED: - case INT_DMA_ERR: - LITE_OFF; - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - if ((++current_req->errors) >= MAX_RETRIES) - ending = FAIL; - else - ending = -1; - break; - - case INT_CMD_BLK_ERR: - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = FAIL; - break; - - case INT_CMD_FORMAT: - printk("%s: huh ? Who issued this format command ?\n" - ,DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - case INT_RESET: - /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - default: - printk("%s: Unknown interrupt reason: %02X\n", - DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - } - if(ending != -1) { - spin_lock_irqsave(&ps2esdi_lock, flags); - end_request(current_req, ending); - current_req = NULL; - do_ps2esdi_request(ps2esdi_queue); - spin_unlock_irqrestore(&ps2esdi_lock, flags); - } -} /* handle interrupts */ - - - -static int ps2esdi_read_status_words(int num_words, - int max_words, - u_short * buffer) -{ - int i; - - for (; max_words && num_words; max_words--, num_words--, buffer++) { - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - return FAIL; - } - *buffer = inw(ESDI_STT_INT); - } - return SUCCES; -} - - - - -static void dump_cmd_complete_status(u_int int_ret_code) -{ -#define WAIT_FOR_STATUS \ - for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \ - if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \ - printk("%s: timeout reading status word\n",DEVICE_NAME); \ - return; \ - } - - int i, word_count; - u_short stat_word; - u_long rba; - - printk("%s: Device: %u, interrupt ID: %02X\n", - DEVICE_NAME, int_ret_code >> 5, - int_ret_code & 0xf); - - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - word_count = (stat_word >> 8) - 1; - printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count, - stat_word & 0xff); - - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: command status code: %02X, command error code: %02X\n", - DEVICE_NAME, stat_word >> 8, stat_word & 0xff); - } - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME, - (stat_word & 0x1000) ? "Ready, " : "Not Ready, ", - (stat_word & 0x0800) ? "Selected, " : "Not Selected, ", - (stat_word & 0x0400) ? "Write Fault, " : "", - (stat_word & 0x0200) ? "Track 0, " : "", - (stat_word & 0x0100) ? "Seek or command complete, " : "", - stat_word >> 8); - } - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word); - } - if (word_count -= 2) { - WAIT_FOR_STATUS; - rba = inw(ESDI_STT_INT); - WAIT_FOR_STATUS; - rba |= inw(ESDI_STT_INT) << 16; - printk(", Last Cyl: %u Head: %u Sector: %u\n", - (u_short) ((rba & 0x1ff80000) >> 11), - (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f)); - } else - printk("\n"); - - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word); - } - printk("\n"); - -#undef WAIT_FOR_STATUS - -} - -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ps2esdi_i_struct *p = bdev->bd_disk->private_data; - - geo->heads = p->head; - geo->sectors = p->sect; - geo->cylinders = p->cyl; - return 0; -} - -static void ps2esdi_reset_timer(unsigned long unused) -{ - - int status; - - status = inb(ESDI_INTRPT); - if ((status & 0xf) == INT_RESET) { - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - reset_status = 1; - } - wake_up(&ps2esdi_int); -} diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 0fac822c1157..4108b38ebb16 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -127,7 +127,6 @@ header-y += pkt_sched.h header-y += posix_types.h header-y += ppdev.h header-y += prctl.h -header-y += ps2esdi.h header-y += qnxtypes.h header-y += quotaio_v1.h header-y += quotaio_v2.h diff --git a/include/linux/ps2esdi.h b/include/linux/ps2esdi.h deleted file mode 100644 index c0e050b1dfe9..000000000000 --- a/include/linux/ps2esdi.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _PS2ESDI_H_ -#define _PS2ESDI_H_ - -#define NRML_ESDI_ID 0xddff -#define INTG_ESDI_ID 0xdf9f - -#define PRIMARY_IO_BASE 0x3510 -#define ALT_IO_BASE 0x3518 - -#define ESDI_CMD_INT (io_base+0) -#define ESDI_STT_INT (io_base+0) -#define ESDI_CONTROL (io_base+2) -#define ESDI_STATUS (io_base+2) -#define ESDI_ATTN (io_base+3) -#define ESDI_INTRPT (io_base+3) - -#define STATUS_ENABLED 0x01 -#define STATUS_ALTERNATE 0x02 -#define STATUS_BUSY 0x10 -#define STATUS_STAT_AVAIL 0x08 -#define STATUS_INTR 0x01 -#define STATUS_RESET_FAIL 0xea -#define STATUS_CMD_INF 0x04 - -#define CTRL_SOFT_RESET 0xe4 -#define CTRL_HARD_RESET 0x80 -#define CTRL_EOI 0xe2 -#define CTRL_ENABLE_DMA 0x02 -#define CTRL_ENABLE_INTR 0x01 -#define CTRL_DISABLE_INTR 0x00 - -#define ATT_EOI 0x02 - -/* bits of word 0 of configuration status block. more info see p.38 of tech ref */ -#define CONFIG_IS 0x10 /* Invalid Secondary */ -#define CONFIG_ZD 0x08 /* Zero Defect */ -#define CONFIG_SF 0x04 /* Skewed Format */ -#define CONFIG_FR 0x02 /* Removable */ -#define CONFIG_RT 0x01 /* Retries */ - -#define PORT_SYS_A 0x92 -#define PORT_DMA_FN 0x18 -#define PORT_DMA_EX 0x1a - -#define ON (unsigned char)0x40 -#define OFF (unsigned char)~ON -#define LITE_ON outb(inb(PORT_SYS_A) | ON,PORT_SYS_A) -#define LITE_OFF outb((inb(PORT_SYS_A) & OFF),PORT_SYS_A) - -#define FAIL 0 -#define SUCCES 1 - -#define INT_CMD_COMPLETE 0x01 -#define INT_CMD_ECC 0x03 -#define INT_CMD_RETRY 0x05 -#define INT_CMD_FORMAT 0x06 -#define INT_CMD_ECC_RETRY 0x07 -#define INT_CMD_WARNING 0x08 -#define INT_CMD_ABORT 0x09 -#define INT_RESET 0x0A -#define INT_TRANSFER_REQ 0x0B -#define INT_CMD_FAILED 0x0C -#define INT_DMA_ERR 0x0D -#define INT_CMD_BLK_ERR 0x0E -#define INT_ATTN_ERROR 0x0F - -#define DMA_MASK_CHAN 0x90 -#define DMA_UNMASK_CHAN 0xA0 -#define DMA_WRITE_ADDR 0x20 -#define DMA_WRITE_TC 0x40 -#define DMA_WRITE_MODE 0x70 - -#define CMD_GET_DEV_CONFIG 0x09 -#define CMD_READ 0x4601 -#define CMD_WRITE 0x4602 -#define DMA_READ_16 0x4C -#define DMA_WRITE_16 0x44 - - -#define MB 1024*1024 -#define SECT_SIZE 512 - -#define ERROR 1 -#define OK 0 - -#define HDIO_GETGEO 0x0301 - -#define FALSE 0 -#define TRUE !FALSE - -struct ps2esdi_geometry { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - unsigned long start; -}; - -#endif /* _PS2ESDI_H_ */ -- cgit v1.2.3 From 4ae7d5cefd4aa3560e359a3b0f03e12adc8b5c86 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 19 Mar 2008 01:42:00 +0100 Subject: sched: improve affine wakeups improve affine wakeups. Maintain the 'overlap' metric based on CFS's sum_exec_runtime - which means the amount of time a task executes after it wakes up some other task. Use the 'overlap' for the wakeup decisions: if the 'overlap' is short, it means there's strong workload coupling between this task and the woken up task. If the 'overlap' is large then the workload is decoupled and the scheduler will move them to separate CPUs more easily. ( Also slightly move the preempt_check within try_to_wake_up() - this has no effect on functionality but allows 'early wakeups' (for still-on-rq tasks) to be correctly accounted as well.) Signed-off-by: Ingo Molnar --- include/linux/sched.h | 3 +++ kernel/sched.c | 5 ++++- kernel/sched_debug.c | 1 + kernel/sched_fair.c | 58 +++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 50 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index 11d8e9a74eff..3625fcaf5d0f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -929,6 +929,9 @@ struct sched_entity { u64 vruntime; u64 prev_sum_exec_runtime; + u64 last_wakeup; + u64 avg_overlap; + #ifdef CONFIG_SCHEDSTATS u64 wait_start; u64 wait_max; diff --git a/kernel/sched.c b/kernel/sched.c index d1ad69b270ca..adbd475cfd25 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1855,10 +1855,11 @@ out_activate: schedstat_inc(p, se.nr_wakeups_remote); update_rq_clock(rq); activate_task(rq, p, 1); - check_preempt_curr(rq, p); success = 1; out_running: + check_preempt_curr(rq, p); + p->state = TASK_RUNNING; #ifdef CONFIG_SMP if (p->sched_class->task_wake_up) @@ -1892,6 +1893,8 @@ static void __sched_fork(struct task_struct *p) p->se.exec_start = 0; p->se.sum_exec_runtime = 0; p->se.prev_sum_exec_runtime = 0; + p->se.last_wakeup = 0; + p->se.avg_overlap = 0; #ifdef CONFIG_SCHEDSTATS p->se.wait_start = 0; diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 4b5e24cf2f4a..ef358ba07683 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -288,6 +288,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) PN(se.exec_start); PN(se.vruntime); PN(se.sum_exec_runtime); + PN(se.avg_overlap); nr_switches = p->nvcsw + p->nivcsw; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index b5a357396b49..87c9d3a2aafa 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -556,6 +556,21 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) account_entity_enqueue(cfs_rq, se); } +static void update_avg(u64 *avg, u64 sample) +{ + s64 diff = sample - *avg; + *avg += diff >> 3; +} + +static void update_avg_stats(struct cfs_rq *cfs_rq, struct sched_entity *se) +{ + if (!se->last_wakeup) + return; + + update_avg(&se->avg_overlap, se->sum_exec_runtime - se->last_wakeup); + se->last_wakeup = 0; +} + static void dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) { @@ -566,6 +581,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) update_stats_dequeue(cfs_rq, se); if (sleep) { + update_avg_stats(cfs_rq, se); #ifdef CONFIG_SCHEDSTATS if (entity_is_task(se)) { struct task_struct *tsk = task_of(se); @@ -981,12 +997,15 @@ static inline int wake_idle(int cpu, struct task_struct *p) #ifdef CONFIG_SMP +static const struct sched_class fair_sched_class; + static int -wake_affine(struct rq *rq, struct sched_domain *this_sd, struct task_struct *p, - int prev_cpu, int this_cpu, int sync, int idx, - unsigned long load, unsigned long this_load, +wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq, + struct task_struct *p, int prev_cpu, int this_cpu, int sync, + int idx, unsigned long load, unsigned long this_load, unsigned int imbalance) { + struct task_struct *curr = this_rq->curr; unsigned long tl = this_load; unsigned long tl_per_task; @@ -994,10 +1013,15 @@ wake_affine(struct rq *rq, struct sched_domain *this_sd, struct task_struct *p, return 0; /* - * Attract cache-cold tasks on sync wakeups: + * If the currently running task will sleep within + * a reasonable amount of time then attract this newly + * woken task: */ - if (sync && !task_hot(p, rq->clock, this_sd)) - return 1; + if (sync && curr->sched_class == &fair_sched_class) { + if (curr->se.avg_overlap < sysctl_sched_migration_cost && + p->se.avg_overlap < sysctl_sched_migration_cost) + return 1; + } schedstat_inc(p, se.nr_wakeups_affine_attempts); tl_per_task = cpu_avg_load_per_task(this_cpu); @@ -1030,18 +1054,16 @@ static int select_task_rq_fair(struct task_struct *p, int sync) struct sched_domain *sd, *this_sd = NULL; int prev_cpu, this_cpu, new_cpu; unsigned long load, this_load; + struct rq *rq, *this_rq; unsigned int imbalance; - struct rq *rq; int idx; prev_cpu = task_cpu(p); rq = task_rq(p); this_cpu = smp_processor_id(); + this_rq = cpu_rq(this_cpu); new_cpu = prev_cpu; - if (prev_cpu == this_cpu) - goto out; - /* * 'this_sd' is the first domain that both * this_cpu and prev_cpu are present in: @@ -1069,11 +1091,12 @@ static int select_task_rq_fair(struct task_struct *p, int sync) load = source_load(prev_cpu, idx); this_load = target_load(this_cpu, idx); - if (wake_affine(rq, this_sd, p, prev_cpu, this_cpu, sync, idx, - load, this_load, imbalance)) { - new_cpu = this_cpu; + if (wake_affine(rq, this_sd, this_rq, p, prev_cpu, this_cpu, sync, idx, + load, this_load, imbalance)) + return this_cpu; + + if (prev_cpu == this_cpu) goto out; - } /* * Start passive balancing when half the imbalance_pct @@ -1083,8 +1106,7 @@ static int select_task_rq_fair(struct task_struct *p, int sync) if (imbalance*this_load <= 100*load) { schedstat_inc(this_sd, ttwu_move_balance); schedstat_inc(p, se.nr_wakeups_passive); - new_cpu = this_cpu; - goto out; + return this_cpu; } } @@ -1111,6 +1133,10 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) return; } + se->last_wakeup = se->sum_exec_runtime; + if (unlikely(se == pse)) + return; + cfs_rq_of(pse)->next = pse; /* -- cgit v1.2.3 From 33b0c4217dcd67b788318c3192a2912b530e4eef Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 16 Mar 2008 11:14:30 +0100 Subject: sched: tune multi-core idle balancing WAKE_IDLE is too agressive on multi-core CPUs with the new wake-affine code, keep it on for SMT/HT balancing alone (where there's no cache affinity at all between logical CPUs). Signed-off-by: Ingo Molnar --- include/linux/topology.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/topology.h b/include/linux/topology.h index 2352f46160d3..2d8dac8799cf 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -138,7 +138,6 @@ | SD_BALANCE_FORK \ | SD_BALANCE_EXEC \ | SD_WAKE_AFFINE \ - | SD_WAKE_IDLE \ | SD_SHARE_PKG_RESOURCES\ | BALANCE_FOR_MC_POWER, \ .last_balance = jiffies, \ -- cgit v1.2.3 From 4cfea5a7dfcc2766251e50ca30271a782d5004ad Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Mar 2008 01:04:48 -0700 Subject: [SPARC64]: Fix atomic backoff limit. 4096 will not fit into the immediate field of a compare instruction, in fact it will end up being -4096 causing the check to fail every time and thus disabling backoff. Signed-off-by: David S. Miller --- include/asm-sparc64/backoff.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-sparc64/backoff.h b/include/asm-sparc64/backoff.h index dadd6c385c6c..fa1fdf67e350 100644 --- a/include/asm-sparc64/backoff.h +++ b/include/asm-sparc64/backoff.h @@ -12,7 +12,8 @@ mov reg, tmp; \ 88: brnz,pt tmp, 88b; \ sub tmp, 1, tmp; \ - cmp reg, BACKOFF_LIMIT; \ + set BACKOFF_LIMIT, tmp; \ + cmp reg, tmp; \ bg,pn %xcc, label; \ nop; \ ba,pt %xcc, label; \ -- cgit v1.2.3 From ae66be9b71b12f16b84129860d06bbfe37fbec51 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 19 Mar 2008 17:00:57 -0700 Subject: rcu: fix misplaced mb() in rcu_enter/exit_nohz() In the process of writing up the mechanical proof of correctness for the dynticks/preemptable-RCU interface, I noticed misplaced memory barriers in rcu_enter_nohz() and rcu_exit_nohz(). This patch puts them in the right place and adds a comment. The key thing to keep in mind is that rcu_enter_nohz() is -exiting- the mode that can legally execute RCU read-side critical sections. The memory barrier must be between any potential RCU read-side critical sections and the increment of the per-CPU dynticks_progress_counter, and thus must come -before- this increment. And vice versa for rcu_exit_nohz(). The locking in the scheduler is probably saving us for the moment. Also, switch to smp_mb() - we don't need a barrier for uniprocessor kernels. Signed-off-by: Paul E. McKenney Acked-by: Steven Rostedt Cc: Nick Piggin Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rcupreempt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h index 01152ed532c8..d038aa6e5ee1 100644 --- a/include/linux/rcupreempt.h +++ b/include/linux/rcupreempt.h @@ -87,15 +87,15 @@ DECLARE_PER_CPU(long, dynticks_progress_counter); static inline void rcu_enter_nohz(void) { + smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */ __get_cpu_var(dynticks_progress_counter)++; WARN_ON(__get_cpu_var(dynticks_progress_counter) & 0x1); - mb(); } static inline void rcu_exit_nohz(void) { - mb(); __get_cpu_var(dynticks_progress_counter)++; + smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ WARN_ON(!(__get_cpu_var(dynticks_progress_counter) & 0x1)); } -- cgit v1.2.3 From a6b91919e0881a0d0a4ae5211d5c879a8c7ca92b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 19 Mar 2008 17:01:00 -0700 Subject: fs: fix kernel-doc notation warnings Fix kernel-doc notation warnings in fs/. Warning(mmotm-2008-0314-1449//fs/super.c:560): missing initial short description on line: * mark_files_ro Warning(mmotm-2008-0314-1449//fs/locks.c:1277): missing initial short description on line: * lease_get_mtime Warning(mmotm-2008-0314-1449//fs/locks.c:1277): missing initial short description on line: * lease_get_mtime Warning(mmotm-2008-0314-1449//fs/namei.c:1368): missing initial short description on line: * lookup_one_len: filesystem helper to lookup single pathname component Warning(mmotm-2008-0314-1449//fs/buffer.c:3221): missing initial short description on line: * bh_uptodate_or_lock: Test whether the buffer is uptodate Warning(mmotm-2008-0314-1449//fs/buffer.c:3240): missing initial short description on line: * bh_submit_read: Submit a locked buffer for reading Warning(mmotm-2008-0314-1449//fs/fs-writeback.c:30): missing initial short description on line: * writeback_acquire: attempt to get exclusive writeback access to a device Warning(mmotm-2008-0314-1449//fs/fs-writeback.c:47): missing initial short description on line: * writeback_in_progress: determine whether there is writeback in progress Warning(mmotm-2008-0314-1449//fs/fs-writeback.c:58): missing initial short description on line: * writeback_release: relinquish exclusive writeback access against a device. Warning(mmotm-2008-0314-1449//include/linux/jbd.h:351): contents before sections Warning(mmotm-2008-0314-1449//include/linux/jbd.h:561): contents before sections Warning(mmotm-2008-0314-1449//fs/jbd/transaction.c:1935): missing initial short description on line: * void journal_invalidatepage() Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 4 ++-- fs/fs-writeback.c | 6 +++--- fs/jbd/transaction.c | 5 ++--- fs/locks.c | 4 ++-- fs/namei.c | 6 +++--- fs/super.c | 6 +++--- include/linux/jbd.h | 11 ++--------- 7 files changed, 17 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/fs/buffer.c b/fs/buffer.c index ddfdd2c80bf9..7ba58386beee 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3213,7 +3213,7 @@ static int buffer_cpu_notify(struct notifier_block *self, } /** - * bh_uptodate_or_lock: Test whether the buffer is uptodate + * bh_uptodate_or_lock - Test whether the buffer is uptodate * @bh: struct buffer_head * * Return true if the buffer is up-to-date and false, @@ -3232,7 +3232,7 @@ int bh_uptodate_or_lock(struct buffer_head *bh) EXPORT_SYMBOL(bh_uptodate_or_lock); /** - * bh_submit_read: Submit a locked buffer for reading + * bh_submit_read - Submit a locked buffer for reading * @bh: struct buffer_head * * Returns zero on success and -EIO on error. diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c0076077d338..06557679ca41 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -751,7 +751,7 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int EXPORT_SYMBOL(generic_osync_inode); /** - * writeback_acquire: attempt to get exclusive writeback access to a device + * writeback_acquire - attempt to get exclusive writeback access to a device * @bdi: the device's backing_dev_info structure * * It is a waste of resources to have more than one pdflush thread blocked on @@ -768,7 +768,7 @@ int writeback_acquire(struct backing_dev_info *bdi) } /** - * writeback_in_progress: determine whether there is writeback in progress + * writeback_in_progress - determine whether there is writeback in progress * @bdi: the device's backing_dev_info structure. * * Determine whether there is writeback in progress against a backing device. @@ -779,7 +779,7 @@ int writeback_in_progress(struct backing_dev_info *bdi) } /** - * writeback_release: relinquish exclusive writeback access against a device. + * writeback_release - relinquish exclusive writeback access against a device. * @bdi: the device's backing_dev_info structure */ void writeback_release(struct backing_dev_info *bdi) diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 4c895044c7d6..2c9e8f5d13aa 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1904,13 +1904,12 @@ zap_buffer_unlocked: } /** - * void journal_invalidatepage() - * @journal: journal to use for flush... + * void journal_invalidatepage() - invalidate a journal page + * @journal: journal to use for flush * @page: page to flush * @offset: length of page to invalidate. * * Reap page buffers containing data after offset in page. - * */ void journal_invalidatepage(journal_t *journal, struct page *page, diff --git a/fs/locks.c b/fs/locks.c index f36f0e61558d..d83fab1b77b5 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1275,13 +1275,13 @@ out: EXPORT_SYMBOL(__break_lease); /** - * lease_get_mtime + * lease_get_mtime - get the last modified time of an inode * @inode: the inode * @time: pointer to a timespec which will contain the last modified time * * This is to force NFS clients to flush their caches for files with * exclusive leases. The justification is that if someone has an - * exclusive lease, then they could be modifiying it. + * exclusive lease, then they could be modifying it. */ void lease_get_mtime(struct inode *inode, struct timespec *time) { diff --git a/fs/namei.c b/fs/namei.c index 941c8e8228c0..6b7a0eef4090 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1364,13 +1364,13 @@ static int __lookup_one_len(const char *name, struct qstr *this, } /** - * lookup_one_len: filesystem helper to lookup single pathname component + * lookup_one_len - filesystem helper to lookup single pathname component * @name: pathname component to lookup * @base: base directory to lookup from * @len: maximum length @len should be interpreted to * - * Note that this routine is purely a helper for filesystem useage and should - * not be called by generic code. Also note that by using this function to + * Note that this routine is purely a helper for filesystem usage and should + * not be called by generic code. Also note that by using this function the * nameidata argument is passed to the filesystem methods and a filesystem * using this helper needs to be prepared for that. */ diff --git a/fs/super.c b/fs/super.c index 010446d8c40a..d0a941a4e620 100644 --- a/fs/super.c +++ b/fs/super.c @@ -556,11 +556,11 @@ out: } /** - * mark_files_ro + * mark_files_ro - mark all files read-only * @sb: superblock in question * - * All files are marked read/only. We don't care about pending - * delete files so this should be used in 'force' mode only + * All files are marked read-only. We don't care about pending + * delete files so this should be used in 'force' mode only. */ static void mark_files_ro(struct super_block *sb) diff --git a/include/linux/jbd.h b/include/linux/jbd.h index b18fd3b9b835..423f58272188 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -348,8 +348,7 @@ static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh) struct jbd_revoke_table_s; /** - * struct handle_s - The handle_s type is the concrete type associated with - * handle_t. + * struct handle_s - this is the concrete type associated with handle_t. * @h_transaction: Which compound transaction is this update a part of? * @h_buffer_credits: Number of remaining buffers we are allowed to dirty. * @h_ref: Reference count on this handle @@ -358,12 +357,7 @@ struct jbd_revoke_table_s; * @h_jdata: flag to force data journaling * @h_aborted: flag indicating fatal error on handle * @h_lockdep_map: lockdep info for debugging lock problems - **/ - -/* Docbook can't yet cope with the bit fields, but will leave the documentation - * in so it can be fixed later. */ - struct handle_s { /* Which compound transaction is this update a part of? */ @@ -558,8 +552,7 @@ struct transaction_s }; /** - * struct journal_s - The journal_s type is the concrete type associated with - * journal_t. + * struct journal_s - this is the concrete type associated with journal_t. * @j_flags: General journaling state flags * @j_errno: Is there an outstanding uncleared error on the journal (from a * prior abort)? -- cgit v1.2.3 From ead70773608a5d97f81cb492f117d20b5e9f323e Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Wed, 19 Mar 2008 17:01:06 -0700 Subject: memstick: automatically retrieve "INT" value from command response MemoryStick storage cards, when in parallel mode, send several meaningful bits of their "INT" register as part of command response. This data is stored by host and can be used to spare invocation of "GET_INT" TPC on each data page transferred between host and card. Signed-off-by: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/core/memstick.c | 9 +++---- drivers/memstick/core/mspro_block.c | 15 +++++++----- drivers/memstick/host/jmb38x_ms.c | 48 +++++++++++++++++++++---------------- drivers/memstick/host/tifm_ms.c | 17 +++++++------ include/linux/memstick.h | 1 - 5 files changed, 49 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index de80dba12f9b..946e3d3506ac 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -276,8 +276,6 @@ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, mrq->need_card_int = 1; else mrq->need_card_int = 0; - - mrq->get_int_reg = 0; } EXPORT_SYMBOL(memstick_init_req_sg); @@ -311,8 +309,6 @@ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, mrq->need_card_int = 1; else mrq->need_card_int = 0; - - mrq->get_int_reg = 0; } EXPORT_SYMBOL(memstick_init_req); @@ -342,6 +338,7 @@ static int h_memstick_read_dev_id(struct memstick_dev *card, card->id.class = id_reg.class; } complete(&card->mrq_complete); + dev_dbg(&card->dev, "if_mode = %02x\n", id_reg.if_mode); return -EAGAIN; } } @@ -422,7 +419,6 @@ static void memstick_power_on(struct memstick_host *host) { host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); - msleep(1); } static void memstick_check(struct work_struct *work) @@ -579,7 +575,8 @@ EXPORT_SYMBOL(memstick_suspend_host); void memstick_resume_host(struct memstick_host *host) { mutex_lock(&host->lock); - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); + if (host->card) + memstick_power_on(host); mutex_unlock(&host->lock); memstick_detect_change(host); } diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 1d637e4561d3..e5356f97d076 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -133,6 +133,7 @@ struct mspro_devinfo { struct mspro_block_data { struct memstick_dev *card; unsigned int usage_count; + unsigned int caps; struct gendisk *disk; struct request_queue *queue; spinlock_t q_lock; @@ -577,7 +578,6 @@ static int h_mspro_block_wait_for_ced(struct memstick_dev *card, static int h_mspro_block_transfer_data(struct memstick_dev *card, struct memstick_request **mrq) { - struct memstick_host *host = card->host; struct mspro_block_data *msb = memstick_get_drvdata(card); unsigned char t_val = 0; struct scatterlist t_sg = { 0 }; @@ -591,12 +591,12 @@ static int h_mspro_block_transfer_data(struct memstick_dev *card, switch ((*mrq)->tpc) { case MS_TPC_WRITE_REG: memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1); - (*mrq)->get_int_reg = 1; + (*mrq)->need_card_int = 1; return 0; case MS_TPC_SET_CMD: t_val = (*mrq)->int_reg; memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); - if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) + if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) goto has_int_reg; return 0; case MS_TPC_GET_INT: @@ -646,12 +646,12 @@ has_int_reg: ? MS_TPC_READ_LONG_DATA : MS_TPC_WRITE_LONG_DATA, &t_sg); - (*mrq)->get_int_reg = 1; + (*mrq)->need_card_int = 1; return 0; case MS_TPC_READ_LONG_DATA: case MS_TPC_WRITE_LONG_DATA: msb->current_page++; - if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) { + if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) { t_val = (*mrq)->int_reg; goto has_int_reg; } else { @@ -1052,7 +1052,8 @@ static int mspro_block_init_card(struct memstick_dev *card) if (memstick_set_rw_addr(card)) return -EIO; - if (host->caps & MEMSTICK_CAP_PAR4) { + msb->caps = host->caps; + if (msb->caps & MEMSTICK_CAP_PAR4) { if (mspro_block_switch_to_parallel(card)) printk(KERN_WARNING "%s: could not switch to " "parallel interface\n", card->dev.bus_id); @@ -1062,6 +1063,8 @@ static int mspro_block_init_card(struct memstick_dev *card) if (rc) return rc; dev_dbg(&card->dev, "card activated\n"); + if (msb->system != MEMSTICK_SYS_SERIAL) + msb->caps |= MEMSTICK_CAP_AUTO_GET_INT; card->next_request = h_mspro_block_req_init; msb->mrq_handler = h_mspro_block_get_ro; diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 9a57504183c7..f91037d50422 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -57,8 +57,6 @@ struct jmb38x_ms_host { unsigned long timeout_jiffies; struct timer_list timer; struct memstick_request *req; - unsigned char eject:1, - use_dma:1; unsigned char cmd_flags; unsigned char io_pos; unsigned int io_word[2]; @@ -95,9 +93,22 @@ struct jmb38x_ms { #define HOST_CONTROL_IF_PAR4 0x1 #define HOST_CONTROL_IF_PAR8 0x3 +#define STATUS_BUSY 0x00080000 +#define STATUS_MS_DAT7 0x00040000 +#define STATUS_MS_DAT6 0x00020000 +#define STATUS_MS_DAT5 0x00010000 +#define STATUS_MS_DAT4 0x00008000 +#define STATUS_MS_DAT3 0x00004000 +#define STATUS_MS_DAT2 0x00002000 +#define STATUS_MS_DAT1 0x00001000 +#define STATUS_MS_DAT0 0x00000800 #define STATUS_HAS_MEDIA 0x00000400 #define STATUS_FIFO_EMPTY 0x00000200 #define STATUS_FIFO_FULL 0x00000100 +#define STATUS_MS_CED 0x00000080 +#define STATUS_MS_ERR 0x00000040 +#define STATUS_MS_BRQ 0x00000020 +#define STATUS_MS_CNK 0x00000001 #define INT_STATUS_TPC_ERR 0x00080000 #define INT_STATUS_CRC_ERR 0x00040000 @@ -124,7 +135,7 @@ enum { CMD_READY = 0x01, FIFO_READY = 0x02, REG_DATA = 0x04, - AUTO_GET_INT = 0x08 + DMA_DATA = 0x08 }; static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, @@ -367,28 +378,27 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh) cmd |= TPC_DIR; if (host->req->need_card_int) cmd |= TPC_WAIT_INT; - if (host->req->get_int_reg) - cmd |= TPC_GET_INT; data = host->req->data; - host->use_dma = !no_dma; + if (!no_dma) + host->cmd_flags |= DMA_DATA; if (host->req->long_data) { data_len = host->req->sg.length; } else { data_len = host->req->data_len; - host->use_dma = 0; + host->cmd_flags &= ~DMA_DATA; } if (data_len <= 8) { cmd &= ~(TPC_DATA_SEL | 0xf); host->cmd_flags |= REG_DATA; cmd |= data_len & 0xf; - host->use_dma = 0; + host->cmd_flags &= ~DMA_DATA; } - if (host->use_dma) { + if (host->cmd_flags & DMA_DATA) { if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE @@ -451,13 +461,12 @@ static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last) readl(host->addr + INT_STATUS)); dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS)); - if (host->req->get_int_reg) { - t_val = readl(host->addr + TPC_P0); - host->req->int_reg = (t_val & 0xff); - } + host->req->int_reg = readl(host->addr + STATUS) & 0xff; + + writel(0, host->addr + BLOCK); + writel(0, host->addr + DMA_CONTROL); - if (host->use_dma) { - writel(0, host->addr + DMA_CONTROL); + if (host->cmd_flags & DMA_DATA) { pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); @@ -509,7 +518,7 @@ static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) else host->req->error = -ETIME; } else { - if (host->use_dma) { + if (host->cmd_flags & DMA_DATA) { if (irq_status & INT_STATUS_EOTRAN) host->cmd_flags |= FIFO_READY; } else { @@ -775,13 +784,10 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", host->id); host->irq = jm->pdev->irq; - host->timeout_jiffies = msecs_to_jiffies(4000); + host->timeout_jiffies = msecs_to_jiffies(1000); msh->request = jmb38x_ms_request; msh->set_param = jmb38x_ms_set_param; - /* - msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4 - | MEMSTICK_CAP_PAR8; - */ + msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh); diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 2b5bf52a8302..eb150dfb637f 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -340,11 +340,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) del_timer(&host->timer); - if (host->use_dma) + host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff; + host->req->int_reg = (host->req->int_reg & 1) + | ((host->req->int_reg << 4) & 0xe0); + + writel(TIFM_FIFO_INT_SETALL, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); + writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); + + if (host->use_dma) { tifm_unmap_sg(sock, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + } writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); @@ -424,12 +433,6 @@ static void tifm_ms_card_event(struct tifm_dev *sock) else if (host_status & TIFM_MS_STAT_CRC) host->req->error = -EILSEQ; - if (host->req->error) { - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); - } - if (host_status & TIFM_MS_STAT_RDY) host->cmd_flags |= CMD_READY; diff --git a/include/linux/memstick.h b/include/linux/memstick.h index b7ee25888836..3e686ec6a967 100644 --- a/include/linux/memstick.h +++ b/include/linux/memstick.h @@ -239,7 +239,6 @@ struct memstick_request { unsigned char tpc; unsigned char data_dir:1, need_card_int:1, - get_int_reg:1, long_data:1; unsigned char int_reg; int error; -- cgit v1.2.3 From 7d7971db29c078a7946efbe479de5e567a20ba9a Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 12 Mar 2008 22:33:57 +0100 Subject: [ARM] 4863/1: AT91: CAP9 USART definitions for early debug Define AT91_USART0, 1, 2 so the selection of the UART for early kernel messages works. (See commit fa3218d8594869b38b1a170ea36d176ac455b897). Replace AT91_SHDC with AT91_SHDWC to be consistent with other AT91 platforms. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- include/asm-arm/arch-at91/at91cap9.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/arch-at91/at91cap9.h b/include/asm-arm/arch-at91/at91cap9.h index 73e1fcf4a0aa..bac83adb5050 100644 --- a/include/asm-arm/arch-at91/at91cap9.h +++ b/include/asm-arm/arch-at91/at91cap9.h @@ -97,12 +97,17 @@ #define AT91_PIOD (0xfffff800 - AT91_BASE_SYS) #define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) #define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) -#define AT91_SHDC (0xfffffd10 - AT91_BASE_SYS) +#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS) #define AT91_RTT (0xfffffd20 - AT91_BASE_SYS) #define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) #define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) +#define AT91_USART0 AT91CAP9_BASE_US0 +#define AT91_USART1 AT91CAP9_BASE_US1 +#define AT91_USART2 AT91CAP9_BASE_US2 + + /* * Internal Memory. */ -- cgit v1.2.3 From eec2beac278fe5dbf342e0e3f9e56fb64a429d46 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 17 Mar 2008 13:01:07 +0100 Subject: [ARM] 4869/1: ARM: OMAP: Fix compile for mcbsp Until DSP MMU code is merged, dsp_request_mem() does not exist. Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- include/asm-arm/arch-omap/dsp_common.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h index c61f868f24ee..da97736f3efa 100644 --- a/include/asm-arm/arch-omap/dsp_common.h +++ b/include/asm-arm/arch-omap/dsp_common.h @@ -24,11 +24,17 @@ #ifndef ASM_ARCH_DSP_COMMON_H #define ASM_ARCH_DSP_COMMON_H -#ifdef CONFIG_ARCH_OMAP1 +#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_OMAP_MMU_FWK) extern void omap_dsp_request_mpui(void); extern void omap_dsp_release_mpui(void); extern int omap_dsp_request_mem(void); extern int omap_dsp_release_mem(void); +#else +static inline int omap_dsp_request_mem(void) +{ + return 0; +} +#define omap_dsp_release_mem() do {} while (0) #endif #endif /* ASM_ARCH_DSP_COMMON_H */ -- cgit v1.2.3 From a0d1d04ea810481dd0b8790712086a77bc665b8a Mon Sep 17 00:00:00 2001 From: Davide Rizzo Date: Wed, 19 Mar 2008 13:51:48 +0100 Subject: [ARM] 4872/1: Replaces buggy macro in S3C2410 irq include This is a bug correction for a macro that generated wrong results. Nobody used it in official kernel tree, my driver did. Signed-off-by: Davide Rizzo Acked-by: Ben Dooks Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/irqs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h index d858b3eb5547..f5435d8c3769 100644 --- a/include/asm-arm/arch-s3c2410/irqs.h +++ b/include/asm-arm/arch-s3c2410/irqs.h @@ -85,7 +85,7 @@ #define IRQ_EINT23 S3C2410_IRQ(51) -#define IRQ_EINT(x) S3C2410_IRQ((x >= 4) ? (IRQ_EINT4 + (x) - 4) : (S3C2410_IRQ(0) + (x))) +#define IRQ_EINT(x) (((x) >= 4) ? (IRQ_EINT4 + (x) - 4) : (IRQ_EINT0 + (x))) #define IRQ_LCD_FIFO S3C2410_IRQ(52) #define IRQ_LCD_FRAME S3C2410_IRQ(53) -- cgit v1.2.3 From aedb60a67c10a0861af179725d060765262ba0fb Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Fri, 29 Feb 2008 15:14:57 +0000 Subject: file capabilities: remove cap_task_kill() The original justification for cap_task_kill() was as follows: check_kill_permission() does appropriate uid equivalence checks. However with file capabilities it becomes possible for an unprivileged user to execute a file with file capabilities resulting in a more privileged task with the same uid. However now that cap_task_kill() always returns 0 (permission granted) when p->uid==current->uid, the whole hook is worthless, and only likely to create more subtle problems in the corner cases where it might still be called but return -EPERM. Those cases are basically when uids are different but euid/suid is equivalent as per the check in check_kill_permission(). One example of a still-broken application is 'at' for non-root users. This patch removes cap_task_kill(). Signed-off-by: Serge Hallyn Acked-by: Andrew G. Morgan Earlier-version-tested-by: Luiz Fernando N. Capitulino Acked-by: Casey Schaufler Signed-off-by: Linus Torvalds --- include/linux/security.h | 3 +-- security/capability.c | 1 - security/commoncap.c | 40 ---------------------------------------- security/smack/smack_lsm.c | 5 ----- 4 files changed, 1 insertion(+), 48 deletions(-) (limited to 'include') diff --git a/include/linux/security.h b/include/linux/security.h index b07357ca2137..c673dfd4dffc 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -57,7 +57,6 @@ extern int cap_inode_need_killpriv(struct dentry *dentry); extern int cap_inode_killpriv(struct dentry *dentry); extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags); extern void cap_task_reparent_to_init (struct task_struct *p); -extern int cap_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid); extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp); extern int cap_task_setioprio (struct task_struct *p, int ioprio); extern int cap_task_setnice (struct task_struct *p, int nice); @@ -2187,7 +2186,7 @@ static inline int security_task_kill (struct task_struct *p, struct siginfo *info, int sig, u32 secid) { - return cap_task_kill(p, info, sig, secid); + return 0; } static inline int security_task_wait (struct task_struct *p) diff --git a/security/capability.c b/security/capability.c index 9e99f36a8b5c..2c6e06d18fab 100644 --- a/security/capability.c +++ b/security/capability.c @@ -40,7 +40,6 @@ static struct security_operations capability_ops = { .inode_need_killpriv = cap_inode_need_killpriv, .inode_killpriv = cap_inode_killpriv, - .task_kill = cap_task_kill, .task_setscheduler = cap_task_setscheduler, .task_setioprio = cap_task_setioprio, .task_setnice = cap_task_setnice, diff --git a/security/commoncap.c b/security/commoncap.c index bb0c095f5761..06d5c9469ba3 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -540,41 +540,6 @@ int cap_task_setnice (struct task_struct *p, int nice) return cap_safe_nice(p); } -int cap_task_kill(struct task_struct *p, struct siginfo *info, - int sig, u32 secid) -{ - if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))) - return 0; - - /* - * Running a setuid root program raises your capabilities. - * Killing your own setuid root processes was previously - * allowed. - * We must preserve legacy signal behavior in this case. - */ - if (p->uid == current->uid) - return 0; - - /* sigcont is permitted within same session */ - if (sig == SIGCONT && (task_session_nr(current) == task_session_nr(p))) - return 0; - - if (secid) - /* - * Signal sent as a particular user. - * Capabilities are ignored. May be wrong, but it's the - * only thing we can do at the moment. - * Used only by usb drivers? - */ - return 0; - if (cap_issubset(p->cap_permitted, current->cap_permitted)) - return 0; - if (capable(CAP_KILL)) - return 0; - - return -EPERM; -} - /* * called from kernel/sys.c for prctl(PR_CABSET_DROP) * done without task_capability_lock() because it introduces @@ -605,11 +570,6 @@ int cap_task_setnice (struct task_struct *p, int nice) { return 0; } -int cap_task_kill(struct task_struct *p, struct siginfo *info, - int sig, u32 secid) -{ - return 0; -} #endif void cap_task_reparent_to_init (struct task_struct *p) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 38d707593b31..732ba27923c4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1117,11 +1117,6 @@ static int smack_task_movememory(struct task_struct *p) static int smack_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid) { - int rc; - - rc = cap_task_kill(p, info, sig, secid); - if (rc != 0) - return rc; /* * Special cases where signals really ought to go through * in spite of policy. Stephen Smalley suggests it may -- cgit v1.2.3 From 9aefd0abd8610e8f3bb097debf3afb73f8b7b210 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 12 Mar 2008 18:31:58 +0100 Subject: sched: add exported arch_reinit_sched_domains() to header file. Needed so it can be called from outside of sched.c. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Ingo Molnar --- include/linux/sched.h | 1 + kernel/sched.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index 3625fcaf5d0f..fed07d03364e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -790,6 +790,7 @@ struct sched_domain { }; extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new); +extern int arch_reinit_sched_domains(void); #endif /* CONFIG_SMP */ diff --git a/kernel/sched.c b/kernel/sched.c index 573179eb553e..78482e51b583 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6920,7 +6920,7 @@ match2: } #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) -static int arch_reinit_sched_domains(void) +int arch_reinit_sched_domains(void) { int err; -- cgit v1.2.3 From 22e52b072dd87faa9b2559fe89d4e8f2370f81ca Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 12 Mar 2008 18:31:59 +0100 Subject: sched: add arch_update_cpu_topology hook. Will be called each time the scheduling domains are rebuild. Needed for architectures that don't have a static cpu topology. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Ingo Molnar --- include/linux/topology.h | 2 ++ kernel/sched.c | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/include/linux/topology.h b/include/linux/topology.h index 2d8dac8799cf..bd14f8b30f09 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -50,6 +50,8 @@ for_each_online_node(node) \ if (nr_cpus_node(node)) +void arch_update_cpu_topology(void); + /* Conform to ACPI 2.0 SLIT distance definitions */ #define LOCAL_DISTANCE 10 #define REMOTE_DISTANCE 20 diff --git a/kernel/sched.c b/kernel/sched.c index 78482e51b583..28c73f07efb2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6807,6 +6807,10 @@ static int ndoms_cur; /* number of sched domains in 'doms_cur' */ */ static cpumask_t fallback_doms; +void __attribute__((weak)) arch_update_cpu_topology(void) +{ +} + /* * Set up scheduler domains and groups. Callers must hold the hotplug lock. * For now this just excludes isolated cpus, but could be used to @@ -6816,6 +6820,7 @@ static int arch_init_sched_domains(const cpumask_t *cpu_map) { int err; + arch_update_cpu_topology(); ndoms_cur = 1; doms_cur = kmalloc(sizeof(cpumask_t), GFP_KERNEL); if (!doms_cur) -- cgit v1.2.3 From 3078b79d257054c3697c85936afce38595e7b67b Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 6 Mar 2008 13:45:46 +0100 Subject: x86: cast cmpxchg and cmpxchg_local result for 386 and 486 mm/slub.c: In function 'slab_alloc': mm/slub.c:1637: warning: assignment makes pointer from integer without a cast mm/slub.c:1637: warning: assignment makes pointer from integer without a cast mm/slub.c: In function 'slab_free': mm/slub.c:1796: warning: assignment makes pointer from integer without a cast mm/slub.c:1796: warning: assignment makes pointer from integer without a cast A cast is needed in the 386 and 486 code because the type is a pointer. In every other integer case the original cmpxchg code (and the cmpxchg_local which has been copied from it) worked fine, but since we touch a pointer, the type needs to be casted in the cmpxchg_local and cmpxchg macros. The more recent code (586+) does not have this problem (the cast is already there). Signed-off-by: Mathieu Desnoyers Signed-off-by: Thomas Gleixner Reviewed-by: Christoph Lameter Cc: Vegard Nossum Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/cmpxchg_32.h | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/asm-x86/cmpxchg_32.h b/include/asm-x86/cmpxchg_32.h index cea1dae288a7..959fad00dff5 100644 --- a/include/asm-x86/cmpxchg_32.h +++ b/include/asm-x86/cmpxchg_32.h @@ -269,22 +269,26 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old, ({ \ __typeof__(*(ptr)) __ret; \ if (likely(boot_cpu_data.x86 > 3)) \ - __ret = __cmpxchg((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr))); \ + __ret = (__typeof__(*(ptr)))__cmpxchg((ptr), \ + (unsigned long)(o), (unsigned long)(n), \ + sizeof(*(ptr))); \ else \ - __ret = cmpxchg_386((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr))); \ + __ret = (__typeof__(*(ptr)))cmpxchg_386((ptr), \ + (unsigned long)(o), (unsigned long)(n), \ + sizeof(*(ptr))); \ __ret; \ }) #define cmpxchg_local(ptr, o, n) \ ({ \ __typeof__(*(ptr)) __ret; \ if (likely(boot_cpu_data.x86 > 3)) \ - __ret = __cmpxchg_local((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr))); \ + __ret = (__typeof__(*(ptr)))__cmpxchg_local((ptr), \ + (unsigned long)(o), (unsigned long)(n), \ + sizeof(*(ptr))); \ else \ - __ret = cmpxchg_386((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr))); \ + __ret = (__typeof__(*(ptr)))cmpxchg_386((ptr), \ + (unsigned long)(o), (unsigned long)(n), \ + sizeof(*(ptr))); \ __ret; \ }) #endif @@ -301,10 +305,12 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64); ({ \ __typeof__(*(ptr)) __ret; \ if (likely(boot_cpu_data.x86 > 4)) \ - __ret = __cmpxchg64((ptr), (unsigned long long)(o), \ + __ret = (__typeof__(*(ptr)))__cmpxchg64((ptr), \ + (unsigned long long)(o), \ (unsigned long long)(n)); \ else \ - __ret = cmpxchg_486_u64((ptr), (unsigned long long)(o), \ + __ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr), \ + (unsigned long long)(o), \ (unsigned long long)(n)); \ __ret; \ }) @@ -312,10 +318,12 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64); ({ \ __typeof__(*(ptr)) __ret; \ if (likely(boot_cpu_data.x86 > 4)) \ - __ret = __cmpxchg64_local((ptr), (unsigned long long)(o), \ + __ret = (__typeof__(*(ptr)))__cmpxchg64_local((ptr), \ + (unsigned long long)(o), \ (unsigned long long)(n)); \ else \ - __ret = cmpxchg_486_u64((ptr), (unsigned long long)(o), \ + __ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr), \ + (unsigned long long)(o), \ (unsigned long long)(n)); \ __ret; \ }) -- cgit v1.2.3 From f2f7abcb96f03a7a42c13063ad556fc80e345c71 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 4 Mar 2008 14:55:45 -0800 Subject: x86: fix {clear,copy}_user_page() declarations in page.h Clean up: eliminate some compiler noise on x86 when building with strict warnings enabled, introduced by commit 345b904c. In file included from include2/asm/thread_info_64.h:12, from include2/asm/thread_info.h:4, from /home/cel/src/linux/nfs-2.6/include/linux/thread_info.h:35, from /home/cel/src/linux/nfs-2.6/include/linux/preempt.h:9, from /home/cel/src/linux/nfs-2.6/include/linux/spinlock.h:49, from /home/cel/src/linux/nfs-2.6/include/linux/mmzone.h:7, from /home/cel/src/linux/nfs-2.6/include/linux/gfp.h:4, from /home/cel/src/linux/nfs-2.6/include/linux/slab.h:14, from /home/cel/src/linux/nfs-2.6/fs/nfsd/nfs4acl.c:40: include2/asm/page.h:55: warning: `inline' is not at beginning of declaration include2/asm/page.h:61: warning: `inline' is not at beginning of declaration Signed-off-by: Chuck Lever Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/page.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h index 1cb7c51bc296..a05b2896492f 100644 --- a/include/asm-x86/page.h +++ b/include/asm-x86/page.h @@ -52,13 +52,13 @@ extern int page_is_ram(unsigned long pagenr); struct page; -static void inline clear_user_page(void *page, unsigned long vaddr, +static inline void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); } -static void inline copy_user_page(void *to, void *from, unsigned long vaddr, +static inline void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *topage) { copy_page(to, from); -- cgit v1.2.3 From f62f1fc9ef94f74fda2b456d935ba2da69fa0a40 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 7 Mar 2008 15:02:50 -0800 Subject: x86: reserve dma32 early for gart a system with 256 GB of RAM, when NUMA is disabled crashes the following way: Your BIOS doesn't leave a aperture memory hole Please enable the IOMMU option in the BIOS setup This costs you 64 MB of RAM Cannot allocate aperture memory hole (ffff8101c0000000,65536K) Kernel panic - not syncing: Not enough memory for aperture Pid: 0, comm: swapper Not tainted 2.6.25-rc4-x86-latest.git #33 Call Trace: [] panic+0xb2/0x190 [] ? release_console_sem+0x7c/0x250 [] ? __alloc_bootmem_nopanic+0x48/0x90 [] ? free_bootmem+0x29/0x50 [] gart_iommu_hole_init+0x5e7/0x680 [] ? alloc_large_system_hash+0x16b/0x310 [] ? _etext+0x0/0x1 [] pci_iommu_alloc+0x1c/0x40 [] mem_init+0x45/0x1a0 [] start_kernel+0x295/0x380 [] _sinittext+0x1c2/0x230 the root cause is : memmap PMD is too big, [ffffe200e0600000-ffffe200e07fffff] PMD ->ffff81383c000000 on node 0 almost near 4G..., and vmemmap_alloc_block will use up the ram under 4G. solution will be: 1. make memmap allocation get memory above 4G... 2. reserve some dma32 range early before we try to set up memmap for all. and release that before pci_iommu_alloc, so gart or swiotlb could get some range under 4g limit for sure. the patch is using method 2. because method1 may need more code to handle SPARSEMEM and SPASEMEM_VMEMMAP will get Your BIOS doesn't leave a aperture memory hole Please enable the IOMMU option in the BIOS setup This costs you 64 MB of RAM Mapping aperture over 65536 KB of RAM @ 4000000 Memory: 264245736k/268959744k available (8484k kernel code, 4187464k reserved, 4004k data, 724k init) Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/pci-dma_64.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup_64.c | 2 ++ include/asm-x86/pci_64.h | 1 + 3 files changed, 52 insertions(+) (limited to 'include') diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index 375cb2bc45be..8bc1e185e557 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -286,8 +288,55 @@ static __init int iommu_setup(char *p) } early_param("iommu", iommu_setup); +static __initdata void *dma32_bootmem_ptr; +static unsigned long dma32_bootmem_size __initdata = (128ULL<<20); + +static int __init parse_dma32_size_opt(char *p) +{ + if (!p) + return -EINVAL; + dma32_bootmem_size = memparse(p, &p); + return 0; +} +early_param("dma32_size", parse_dma32_size_opt); + +void __init dma32_reserve_bootmem(void) +{ + unsigned long size, align; + if (end_pfn <= MAX_DMA32_PFN) + return; + + align = 64ULL<<20; + size = round_up(dma32_bootmem_size, align); + dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align, + __pa(MAX_DMA_ADDRESS)); + if (dma32_bootmem_ptr) + dma32_bootmem_size = size; + else + dma32_bootmem_size = 0; +} +static void __init dma32_free_bootmem(void) +{ + int node; + + if (end_pfn <= MAX_DMA32_PFN) + return; + + if (!dma32_bootmem_ptr) + return; + + for_each_online_node(node) + free_bootmem_node(NODE_DATA(node), __pa(dma32_bootmem_ptr), + dma32_bootmem_size); + + dma32_bootmem_ptr = NULL; + dma32_bootmem_size = 0; +} + void __init pci_iommu_alloc(void) { + /* free the range so iommu could get some range less than 4G */ + dma32_free_bootmem(); /* * The order of these functions is important for * fall-back/fail-over reasons diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 7637dc91c79b..a775fe3de955 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -389,6 +389,8 @@ void __init setup_arch(char **cmdline_p) early_res_to_bootmem(); + dma32_reserve_bootmem(); + #ifdef CONFIG_ACPI_SLEEP /* * Reserve low memory region for sleep support. diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h index 374690314539..da8266a08005 100644 --- a/include/asm-x86/pci_64.h +++ b/include/asm-x86/pci_64.h @@ -25,6 +25,7 @@ extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int l +extern void dma32_reserve_bootmem(void); extern void pci_iommu_alloc(void); /* The PCI address space does equal the physical memory -- cgit v1.2.3 From 5dca6a1bb014875a17289fdaae8c31e0a3641c99 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 18 Mar 2008 16:44:19 -0700 Subject: x86: trim mtrr don't close gap for resource allocation. fix the bug reported here: http://bugzilla.kernel.org/show_bug.cgi?id=10232 use update_memory_range() instead of add_memory_range() directly to avoid closing the gap. ( the new code only affects and runs on systems where the MTRR workaround triggers. ) Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/mtrr/main.c | 3 ++- arch/x86/kernel/e820_32.c | 26 ++++++++++++++++++++++++++ arch/x86/kernel/e820_64.c | 27 +++++++++++++++++++++++++++ include/asm-x86/e820_32.h | 2 ++ include/asm-x86/e820_64.h | 2 ++ 5 files changed, 59 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index be83336fddba..a6450b3ae759 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -711,7 +711,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) trim_size = end_pfn; trim_size <<= PAGE_SHIFT; trim_size -= trim_start; - add_memory_region(trim_start, trim_size, E820_RESERVED); + update_memory_range(trim_start, trim_size, E820_RAM, + E820_RESERVED); update_e820(); return 1; } diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c index 4e16ef4a2659..80444c5c9b14 100644 --- a/arch/x86/kernel/e820_32.c +++ b/arch/x86/kernel/e820_32.c @@ -749,6 +749,32 @@ static int __init parse_memmap(char *arg) return 0; } early_param("memmap", parse_memmap); +void __init update_memory_range(u64 start, u64 size, unsigned old_type, + unsigned new_type) +{ + int i; + + BUG_ON(old_type == new_type); + + for (i = 0; i < e820.nr_map; i++) { + struct e820entry *ei = &e820.map[i]; + u64 final_start, final_end; + if (ei->type != old_type) + continue; + /* totally covered? */ + if (ei->addr >= start && ei->size <= size) { + ei->type = new_type; + continue; + } + /* partially covered */ + final_start = max(start, ei->addr); + final_end = min(start + size, ei->addr + ei->size); + if (final_start >= final_end) + continue; + add_memory_region(final_start, final_end - final_start, + new_type); + } +} void __init update_e820(void) { u8 nr_map; diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 9f65b4cc323c..9be697126013 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c @@ -744,6 +744,33 @@ void __init finish_e820_parsing(void) } } +void __init update_memory_range(u64 start, u64 size, unsigned old_type, + unsigned new_type) +{ + int i; + + BUG_ON(old_type == new_type); + + for (i = 0; i < e820.nr_map; i++) { + struct e820entry *ei = &e820.map[i]; + u64 final_start, final_end; + if (ei->type != old_type) + continue; + /* totally covered? */ + if (ei->addr >= start && ei->size <= size) { + ei->type = new_type; + continue; + } + /* partially covered */ + final_start = max(start, ei->addr); + final_end = min(start + size, ei->addr + ei->size); + if (final_start >= final_end) + continue; + add_memory_region(final_start, final_end - final_start, + new_type); + } +} + void __init update_e820(void) { u8 nr_map; diff --git a/include/asm-x86/e820_32.h b/include/asm-x86/e820_32.h index f1da7ebd1905..e7207a6de3e0 100644 --- a/include/asm-x86/e820_32.h +++ b/include/asm-x86/e820_32.h @@ -28,6 +28,8 @@ extern void find_max_pfn(void); extern void register_bootmem_low_pages(unsigned long max_low_pfn); extern void add_memory_region(unsigned long long start, unsigned long long size, int type); +extern void update_memory_range(u64 start, u64 size, unsigned old_type, + unsigned new_type); extern void e820_register_memory(void); extern void limit_regions(unsigned long long size); extern void print_memory_map(char *who); diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h index a560c4f5d500..22ede73ae724 100644 --- a/include/asm-x86/e820_64.h +++ b/include/asm-x86/e820_64.h @@ -18,6 +18,8 @@ extern unsigned long find_e820_area(unsigned long start, unsigned long end, unsigned size, unsigned long align); extern void add_memory_region(unsigned long start, unsigned long size, int type); +extern void update_memory_range(u64 start, u64 size, unsigned old_type, + unsigned new_type); extern void setup_memory_region(void); extern void contig_e820_setup(void); extern unsigned long e820_end_of_ram(void); -- cgit v1.2.3 From 7800c0c3b146013e1e8439e91dc1236a55871d21 Mon Sep 17 00:00:00 2001 From: Matti Linnanvuori Date: Sun, 16 Mar 2008 02:47:35 -0700 Subject: sync_bitops: fix wrong comments [Bug 10247] Fix wrong function name and references to non-x86 architectures. Signed-off-by: Matti Linnanvuori mattilinnanvuori@yahoo.com Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/sync_bitops.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'include') diff --git a/include/asm-x86/sync_bitops.h b/include/asm-x86/sync_bitops.h index cbce08a2d135..6b775c905666 100644 --- a/include/asm-x86/sync_bitops.h +++ b/include/asm-x86/sync_bitops.h @@ -23,10 +23,6 @@ * This function is atomic and may not be reordered. See __set_bit() * if you do not require the atomic guarantees. * - * Note: there are no guarantees that this function will not be reordered - * on non-x86 architectures, so if you are writing portable code, - * make sure not to rely on its reordering guarantees. - * * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ @@ -61,8 +57,7 @@ static inline void sync_clear_bit(int nr, volatile unsigned long * addr) * @nr: Bit to change * @addr: Address to start counting from * - * change_bit() is atomic and may not be reordered. It may be - * reordered on other architectures than x86. + * sync_change_bit() is atomic and may not be reordered. * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ @@ -80,7 +75,6 @@ static inline void sync_change_bit(int nr, volatile unsigned long * addr) * @addr: Address to count from * * This operation is atomic and cannot be reordered. - * It may be reordered on other architectures than x86. * It also implies a memory barrier. */ static inline int sync_test_and_set_bit(int nr, volatile unsigned long * addr) @@ -99,7 +93,6 @@ static inline int sync_test_and_set_bit(int nr, volatile unsigned long * addr) * @addr: Address to count from * * This operation is atomic and cannot be reordered. - * It can be reorderdered on other architectures other than x86. * It also implies a memory barrier. */ static inline int sync_test_and_clear_bit(int nr, volatile unsigned long * addr) -- cgit v1.2.3 From 64658743fdd40021e3ac91e8ff260ad06578dd23 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 21 Mar 2008 17:01:38 -0700 Subject: [SPARC64]: Remove most limitations to kernel image size. Currently kernel images are limited to 8MB in size, and this causes problems especially when enabling features that take up a lot of kernel image space such as lockdep. The code now will align the kernel image size up to 4MB and map that many locked TLB entries. So, the only practical limitation is the number of available locked TLB entries which is 16 on Cheetah and 64 on pre-Cheetah sparc64 cpus. Niagara cpus don't actually have hw locked TLB entry support. Rather, the hypervisor transparently provides support for "locked" TLB entries since it runs with physical addressing and does the initial TLB miss processing. Fully utilizing this change requires some help from SILO, a patch for which will be submitted to the maintainer. Essentially, SILO will only currently map up to 8MB for the kernel image and that needs to be increased. Note that neither this patch nor the SILO bits will help with network booting. The openfirmware code will only map up to a certain amount of kernel image during a network boot and there isn't much we can to about that other than to implemented a layered network booting facility. Solaris has this, and calls it "wanboot" and we may implement something similar at some point. Signed-off-by: David S. Miller --- arch/sparc64/kernel/head.S | 8 +- arch/sparc64/kernel/smp.c | 17 ++-- arch/sparc64/kernel/trampoline.S | 188 +++++++++++++-------------------------- arch/sparc64/mm/init.c | 38 +++----- include/asm-sparc64/hvtramp.h | 2 +- include/asm-sparc64/spitfire.h | 2 + 6 files changed, 96 insertions(+), 159 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 44b105c04dd3..34f8ff57c56b 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -288,8 +288,12 @@ sun4v_chip_type: /* Leave arg2 as-is, prom_mmu_ihandle_cache */ mov -1, %l3 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: mode (-1 default) - sethi %hi(8 * 1024 * 1024), %l3 - stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: size (8MB) + /* 4MB align the kernel image size. */ + set (_end - KERNBASE), %l3 + set ((4 * 1024 * 1024) - 1), %l4 + add %l3, %l4, %l3 + andn %l3, %l4, %l3 + stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: roundup(ksize, 4MB) sethi %hi(KERNBASE), %l3 stx %l3, [%sp + 2047 + 128 + 0x38] ! arg5: vaddr (KERNBASE) stx %g0, [%sp + 2047 + 128 + 0x40] ! arg6: empty diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index cc454731d879..5a1126b363a4 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -284,14 +284,17 @@ static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg) { extern unsigned long sparc64_ttable_tl0; extern unsigned long kern_locked_tte_data; - extern int bigkernel; struct hvtramp_descr *hdesc; unsigned long trampoline_ra; struct trap_per_cpu *tb; u64 tte_vaddr, tte_data; unsigned long hv_err; + int i; - hdesc = kzalloc(sizeof(*hdesc), GFP_KERNEL); + hdesc = kzalloc(sizeof(*hdesc) + + (sizeof(struct hvtramp_mapping) * + num_kernel_image_mappings - 1), + GFP_KERNEL); if (!hdesc) { printk(KERN_ERR "ldom_startcpu_cpuid: Cannot allocate " "hvtramp_descr.\n"); @@ -299,7 +302,7 @@ static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg) } hdesc->cpu = cpu; - hdesc->num_mappings = (bigkernel ? 2 : 1); + hdesc->num_mappings = num_kernel_image_mappings; tb = &trap_block[cpu]; tb->hdesc = hdesc; @@ -312,13 +315,11 @@ static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg) tte_vaddr = (unsigned long) KERNBASE; tte_data = kern_locked_tte_data; - hdesc->maps[0].vaddr = tte_vaddr; - hdesc->maps[0].tte = tte_data; - if (bigkernel) { + for (i = 0; i < hdesc->num_mappings; i++) { + hdesc->maps[i].vaddr = tte_vaddr; + hdesc->maps[i].tte = tte_data; tte_vaddr += 0x400000; tte_data += 0x400000; - hdesc->maps[1].vaddr = tte_vaddr; - hdesc->maps[1].tte = tte_data; } trampoline_ra = kimage_addr_to_ra(hv_cpu_startup); diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 4ae2e525d68b..56ff55211341 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S @@ -105,7 +105,7 @@ startup_continue: wr %g2, 0, %tick_cmpr /* Call OBP by hand to lock KERNBASE into i/d tlbs. - * We lock 2 consequetive entries if we are 'bigkernel'. + * We lock 'num_kernel_image_mappings' consequetive entries. */ sethi %hi(prom_entry_lock), %g2 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 @@ -119,6 +119,29 @@ startup_continue: add %l2, -(192 + 128), %sp flushw + /* Setup the loop variables: + * %l3: VADDR base + * %l4: TTE base + * %l5: Loop iterator, iterates from 0 to 'num_kernel_image_mappings' + * %l6: Number of TTE entries to map + * %l7: Highest TTE entry number, we count down + */ + sethi %hi(KERNBASE), %l3 + sethi %hi(kern_locked_tte_data), %l4 + ldx [%l4 + %lo(kern_locked_tte_data)], %l4 + clr %l5 + sethi %hi(num_kernel_image_mappings), %l6 + lduw [%l6 + %lo(num_kernel_image_mappings)], %l6 + add %l6, 1, %l6 + + mov 15, %l7 + BRANCH_IF_ANY_CHEETAH(g1,g5,2f) + + mov 63, %l7 +2: + +3: + /* Lock into I-MMU */ sethi %hi(call_method), %g2 or %g2, %lo(call_method), %g2 stx %g2, [%sp + 2047 + 128 + 0x00] @@ -132,63 +155,26 @@ startup_continue: sethi %hi(prom_mmu_ihandle_cache), %g2 lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - - mov 15, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) - mov 63, %g2 -1: - stx %g2, [%sp + 2047 + 128 + 0x38] - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x08], %o1 - call %o1 - add %sp, (2047 + 128), %o0 + /* Each TTE maps 4MB, convert index to offset. */ + sllx %l5, 22, %g1 - sethi %hi(bigkernel), %g2 - lduw [%g2 + %lo(bigkernel)], %g2 - brz,pt %g2, do_dtlb - nop + add %l3, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] ! VADDR + add %l4, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] ! TTE - sethi %hi(call_method), %g2 - or %g2, %lo(call_method), %g2 - stx %g2, [%sp + 2047 + 128 + 0x00] - mov 5, %g2 - stx %g2, [%sp + 2047 + 128 + 0x08] - mov 1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x10] - sethi %hi(itlb_load), %g2 - or %g2, %lo(itlb_load), %g2 - stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(prom_mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE + 0x400000), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - sethi %hi(0x400000), %g1 - add %g2, %g1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - - mov 14, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) - - mov 62, %g2 -1: + /* TTE index is highest minus loop index. */ + sub %l7, %l5, %g2 stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 or %g2, %lo(p1275buf), %g2 ldx [%g2 + 0x08], %o1 call %o1 add %sp, (2047 + 128), %o0 -do_dtlb: + /* Lock into D-MMU */ sethi %hi(call_method), %g2 or %g2, %lo(call_method), %g2 stx %g2, [%sp + 2047 + 128 + 0x00] @@ -202,65 +188,30 @@ do_dtlb: sethi %hi(prom_mmu_ihandle_cache), %g2 lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - mov 15, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) + /* Each TTE maps 4MB, convert index to offset. */ + sllx %l5, 22, %g1 - mov 63, %g2 -1: + add %l3, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] ! VADDR + add %l4, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] ! TTE + /* TTE index is highest minus loop index. */ + sub %l7, %l5, %g2 stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 or %g2, %lo(p1275buf), %g2 ldx [%g2 + 0x08], %o1 call %o1 add %sp, (2047 + 128), %o0 - sethi %hi(bigkernel), %g2 - lduw [%g2 + %lo(bigkernel)], %g2 - brz,pt %g2, do_unlock + add %l5, 1, %l5 + cmp %l5, %l6 + bne,pt %xcc, 3b nop - sethi %hi(call_method), %g2 - or %g2, %lo(call_method), %g2 - stx %g2, [%sp + 2047 + 128 + 0x00] - mov 5, %g2 - stx %g2, [%sp + 2047 + 128 + 0x08] - mov 1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x10] - sethi %hi(dtlb_load), %g2 - or %g2, %lo(dtlb_load), %g2 - stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(prom_mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 - stx %g2, [%sp + 2047 + 128 + 0x20] - sethi %hi(KERNBASE + 0x400000), %g2 - stx %g2, [%sp + 2047 + 128 + 0x28] - sethi %hi(kern_locked_tte_data), %g2 - ldx [%g2 + %lo(kern_locked_tte_data)], %g2 - sethi %hi(0x400000), %g1 - add %g2, %g1, %g2 - stx %g2, [%sp + 2047 + 128 + 0x30] - - mov 14, %g2 - BRANCH_IF_ANY_CHEETAH(g1,g5,1f) - - mov 62, %g2 -1: - - stx %g2, [%sp + 2047 + 128 + 0x38] - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x08], %o1 - call %o1 - add %sp, (2047 + 128), %o0 - -do_unlock: sethi %hi(prom_entry_lock), %g2 stb %g0, [%g2 + %lo(prom_entry_lock)] membar #StoreStore | #StoreLoad @@ -269,47 +220,36 @@ do_unlock: nop niagara_lock_tlb: + sethi %hi(KERNBASE), %l3 + sethi %hi(kern_locked_tte_data), %l4 + ldx [%l4 + %lo(kern_locked_tte_data)], %l4 + clr %l5 + sethi %hi(num_kernel_image_mappings), %l6 + lduw [%l6 + %lo(num_kernel_image_mappings)], %l6 + add %l6, 1, %l6 + +1: mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 - sethi %hi(KERNBASE), %o0 + sllx %l5, 22, %g2 + add %l3, %g2, %o0 clr %o1 - sethi %hi(kern_locked_tte_data), %o2 - ldx [%o2 + %lo(kern_locked_tte_data)], %o2 + add %l4, %g2, %o2 mov HV_MMU_IMMU, %o3 ta HV_FAST_TRAP mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 - sethi %hi(KERNBASE), %o0 + sllx %l5, 22, %g2 + add %l3, %g2, %o0 clr %o1 - sethi %hi(kern_locked_tte_data), %o2 - ldx [%o2 + %lo(kern_locked_tte_data)], %o2 + add %l4, %g2, %o2 mov HV_MMU_DMMU, %o3 ta HV_FAST_TRAP - sethi %hi(bigkernel), %g2 - lduw [%g2 + %lo(bigkernel)], %g2 - brz,pt %g2, after_lock_tlb + add %l5, 1, %l5 + cmp %l5, %l6 + bne,pt %xcc, 1b nop - mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 - sethi %hi(KERNBASE + 0x400000), %o0 - clr %o1 - sethi %hi(kern_locked_tte_data), %o2 - ldx [%o2 + %lo(kern_locked_tte_data)], %o2 - sethi %hi(0x400000), %o3 - add %o2, %o3, %o2 - mov HV_MMU_IMMU, %o3 - ta HV_FAST_TRAP - - mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 - sethi %hi(KERNBASE + 0x400000), %o0 - clr %o1 - sethi %hi(kern_locked_tte_data), %o2 - ldx [%o2 + %lo(kern_locked_tte_data)], %o2 - sethi %hi(0x400000), %o3 - add %o2, %o3, %o2 - mov HV_MMU_DMMU, %o3 - ta HV_FAST_TRAP - after_lock_tlb: wrpr %g0, (PSTATE_PRIV | PSTATE_PEF), %pstate wr %g0, 0, %fprs diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index b5c30416fdac..466fd6cffac9 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -166,7 +166,7 @@ unsigned long sparc64_kern_pri_context __read_mostly; unsigned long sparc64_kern_pri_nuc_bits __read_mostly; unsigned long sparc64_kern_sec_context __read_mostly; -int bigkernel = 0; +int num_kernel_image_mappings; #ifdef CONFIG_DEBUG_DCFLUSH atomic_t dcpage_flushes = ATOMIC_INIT(0); @@ -572,7 +572,7 @@ static unsigned long kern_large_tte(unsigned long paddr); static void __init remap_kernel(void) { unsigned long phys_page, tte_vaddr, tte_data; - int tlb_ent = sparc64_highest_locked_tlbent(); + int i, tlb_ent = sparc64_highest_locked_tlbent(); tte_vaddr = (unsigned long) KERNBASE; phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL; @@ -582,27 +582,20 @@ static void __init remap_kernel(void) /* Now lock us into the TLBs via Hypervisor or OBP. */ if (tlb_type == hypervisor) { - hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_DMMU); - hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_IMMU); - if (bigkernel) { - tte_vaddr += 0x400000; - tte_data += 0x400000; + for (i = 0; i < num_kernel_image_mappings; i++) { hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_DMMU); hypervisor_tlb_lock(tte_vaddr, tte_data, HV_MMU_IMMU); + tte_vaddr += 0x400000; + tte_data += 0x400000; } } else { - prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); - prom_itlb_load(tlb_ent, tte_data, tte_vaddr); - if (bigkernel) { - tlb_ent -= 1; - prom_dtlb_load(tlb_ent, - tte_data + 0x400000, - tte_vaddr + 0x400000); - prom_itlb_load(tlb_ent, - tte_data + 0x400000, - tte_vaddr + 0x400000); + for (i = 0; i < num_kernel_image_mappings; i++) { + prom_dtlb_load(tlb_ent - i, tte_data, tte_vaddr); + prom_itlb_load(tlb_ent - i, tte_data, tte_vaddr); + tte_vaddr += 0x400000; + tte_data += 0x400000; } - sparc64_highest_unlocked_tlb_ent = tlb_ent - 1; + sparc64_highest_unlocked_tlb_ent = tlb_ent - i; } if (tlb_type == cheetah_plus) { sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 | @@ -1352,12 +1345,9 @@ void __init paging_init(void) shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE); real_end = (unsigned long)_end; - if ((real_end > ((unsigned long)KERNBASE + 0x400000))) - bigkernel = 1; - if ((real_end > ((unsigned long)KERNBASE + 0x800000))) { - prom_printf("paging_init: Kernel > 8MB, too large.\n"); - prom_halt(); - } + num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << 22); + printk("Kernel: Using %d locked TLB entries for main kernel image.\n", + num_kernel_image_mappings); /* Set kernel pgd to upper alias so physical page computations * work. diff --git a/include/asm-sparc64/hvtramp.h b/include/asm-sparc64/hvtramp.h index c7dd6ad056df..b2b9b947b3a4 100644 --- a/include/asm-sparc64/hvtramp.h +++ b/include/asm-sparc64/hvtramp.h @@ -16,7 +16,7 @@ struct hvtramp_descr { __u64 fault_info_va; __u64 fault_info_pa; __u64 thread_reg; - struct hvtramp_mapping maps[2]; + struct hvtramp_mapping maps[1]; }; extern void hv_cpu_startup(unsigned long hvdescr_pa); diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h index 63b7040e8134..985ea7e31992 100644 --- a/include/asm-sparc64/spitfire.h +++ b/include/asm-sparc64/spitfire.h @@ -63,6 +63,8 @@ extern void cheetah_enable_pcache(void); SPITFIRE_HIGHEST_LOCKED_TLBENT : \ CHEETAH_HIGHEST_LOCKED_TLBENT) +extern int num_kernel_image_mappings; + /* The data cache is write through, so this just invalidates the * specified line. */ -- cgit v1.2.3 From 9e9630481ee8ef33f1cce71ce3636169fa37cd49 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 22 Mar 2008 14:13:06 +0100 Subject: x86: revert: reserve dma32 early for gart Revert commit f62f1fc9ef94f74fda2b456d935ba2da69fa0a40 Author: Yinghai Lu Date: Fri Mar 7 15:02:50 2008 -0800 x86: reserve dma32 early for gart The patch has a dependency on bootmem modifications which are not .25 material that late in the -rc cycle. The problem which is addressed by the patch is limited to machines with 256G and more memory booted with NUMA disabled. This is not a .25 regression and the audience which is affected by this problem is very limited, so it's safer to do the revert than pulling in intrusive bootmem changes right now. Signed-off-by: Thomas Gleixner --- arch/x86/kernel/pci-dma_64.c | 49 -------------------------------------------- arch/x86/kernel/setup_64.c | 2 -- include/asm-x86/pci_64.h | 1 - 3 files changed, 52 deletions(-) (limited to 'include') diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index 8bc1e185e557..375cb2bc45be 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -8,8 +8,6 @@ #include #include #include -#include -#include #include #include #include @@ -288,55 +286,8 @@ static __init int iommu_setup(char *p) } early_param("iommu", iommu_setup); -static __initdata void *dma32_bootmem_ptr; -static unsigned long dma32_bootmem_size __initdata = (128ULL<<20); - -static int __init parse_dma32_size_opt(char *p) -{ - if (!p) - return -EINVAL; - dma32_bootmem_size = memparse(p, &p); - return 0; -} -early_param("dma32_size", parse_dma32_size_opt); - -void __init dma32_reserve_bootmem(void) -{ - unsigned long size, align; - if (end_pfn <= MAX_DMA32_PFN) - return; - - align = 64ULL<<20; - size = round_up(dma32_bootmem_size, align); - dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align, - __pa(MAX_DMA_ADDRESS)); - if (dma32_bootmem_ptr) - dma32_bootmem_size = size; - else - dma32_bootmem_size = 0; -} -static void __init dma32_free_bootmem(void) -{ - int node; - - if (end_pfn <= MAX_DMA32_PFN) - return; - - if (!dma32_bootmem_ptr) - return; - - for_each_online_node(node) - free_bootmem_node(NODE_DATA(node), __pa(dma32_bootmem_ptr), - dma32_bootmem_size); - - dma32_bootmem_ptr = NULL; - dma32_bootmem_size = 0; -} - void __init pci_iommu_alloc(void) { - /* free the range so iommu could get some range less than 4G */ - dma32_free_bootmem(); /* * The order of these functions is important for * fall-back/fail-over reasons diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index a775fe3de955..7637dc91c79b 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -389,8 +389,6 @@ void __init setup_arch(char **cmdline_p) early_res_to_bootmem(); - dma32_reserve_bootmem(); - #ifdef CONFIG_ACPI_SLEEP /* * Reserve low memory region for sleep support. diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h index da8266a08005..374690314539 100644 --- a/include/asm-x86/pci_64.h +++ b/include/asm-x86/pci_64.h @@ -25,7 +25,6 @@ extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int l -extern void dma32_reserve_bootmem(void); extern void pci_iommu_alloc(void); /* The PCI address space does equal the physical memory -- cgit v1.2.3 From 03c086a747d0b242878eb881971ec61c1555869d Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 13 Mar 2008 15:35:49 +0000 Subject: PNP: increase the number of PnP memory resources from 12 to 24 Increase the number of PnP memory resources from 12 to 24. This removes an "exceeded the max num of mem resources" warning on boot. I also noticed the reservation of two more iomem ranges on the computer on which this was tested. Signed-off-by: Darren Salt Signed-off-by: Ingo Molnar Acked-by: Bjorn Helgaas Signed-off-by: Linus Torvalds --- include/linux/pnp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/pnp.h b/include/linux/pnp.h index cd6332b88829..29dd55838e84 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -14,7 +14,7 @@ #include #define PNP_MAX_PORT 40 -#define PNP_MAX_MEM 12 +#define PNP_MAX_MEM 24 #define PNP_MAX_IRQ 2 #define PNP_MAX_DMA 2 #define PNP_NAME_LEN 50 -- cgit v1.2.3 From b9e76a00749521f2b080fa8a4fb15f66538ab756 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 24 Mar 2008 11:22:39 -0700 Subject: x86-32: Pass the full resource data to ioremap() It appears that 64-bit PCI resources cannot possibly ever have worked on x86-32 even when the RESOURCES_64BIT config option was set, because any driver that tried to [pci_]ioremap() the resource would have been unable to do so because the high 32 bits would have been silently dropped on the floor by the ioremap() routines that only used "unsigned long". Change them to use "resource_size_t" instead, which properly encodes the whole 64-bit resource data if RESOURCES_64BIT is enabled. Acked-by: H. Peter Anvin Acked-by: Stefan Richter Cc: Ivan Kokshaysky Signed-off-by: Linus Torvalds --- arch/x86/mm/ioremap.c | 6 +++--- include/asm-x86/io_32.h | 6 +++--- include/asm-x86/io_64.h | 6 +++--- lib/iomap.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 8fe576baa148..4afaba0ed722 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -106,7 +106,7 @@ static int ioremap_change_attr(unsigned long vaddr, unsigned long size, * have to convert them into an offset in a page-aligned mapping, but the * caller shouldn't need to know that small detail. */ -static void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, +static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size, enum ioremap_mode mode) { unsigned long pfn, offset, last_addr, vaddr; @@ -193,13 +193,13 @@ static void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, * * Must be freed with iounmap. */ -void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size) +void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size) { return __ioremap(phys_addr, size, IOR_MODE_UNCACHED); } EXPORT_SYMBOL(ioremap_nocache); -void __iomem *ioremap_cache(unsigned long phys_addr, unsigned long size) +void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size) { return __ioremap(phys_addr, size, IOR_MODE_CACHED); } diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h index 58d2c45cd0b1..d4d8fbd9378c 100644 --- a/include/asm-x86/io_32.h +++ b/include/asm-x86/io_32.h @@ -114,13 +114,13 @@ static inline void * phys_to_virt(unsigned long address) * If the area you are trying to map is a PCI BAR you should have a * look at pci_iomap(). */ -extern void __iomem *ioremap_nocache(unsigned long offset, unsigned long size); -extern void __iomem *ioremap_cache(unsigned long offset, unsigned long size); +extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size); +extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size); /* * The default ioremap() behavior is non-cached: */ -static inline void __iomem *ioremap(unsigned long offset, unsigned long size) +static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) { return ioremap_nocache(offset, size); } diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h index f64a59cc396d..db0be2011a3c 100644 --- a/include/asm-x86/io_64.h +++ b/include/asm-x86/io_64.h @@ -158,13 +158,13 @@ extern void early_iounmap(void *addr, unsigned long size); * it's useful if some control registers are in such an area and write combining * or read caching is not desirable: */ -extern void __iomem *ioremap_nocache(unsigned long offset, unsigned long size); -extern void __iomem *ioremap_cache(unsigned long offset, unsigned long size); +extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size); +extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size); /* * The default ioremap() behavior is non-cached: */ -static inline void __iomem *ioremap(unsigned long offset, unsigned long size) +static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) { return ioremap_nocache(offset, size); } diff --git a/lib/iomap.c b/lib/iomap.c index db004a9ff509..dd6ca48fe6b0 100644 --- a/lib/iomap.c +++ b/lib/iomap.c @@ -256,7 +256,7 @@ EXPORT_SYMBOL(ioport_unmap); * */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); unsigned long len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); -- cgit v1.2.3 From aacda37538e7f9cf2148eedf3766239829e51ba4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 18 Mar 2008 17:47:43 +0900 Subject: libata: implement ata_qc_raw_nbytes() Implement ata_qc_raw_nbytes() which determines the raw user-requested size of a PC command. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 14 +++++++++++--- include/linux/libata.h | 8 +++++++- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8f0e8f2bc628..15795394b0a8 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -527,6 +527,14 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, return qc; } +static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + + qc->extrabytes = scmd->request->extra_len; + qc->nbytes = scsi_bufflen(scmd) + qc->extrabytes; +} + /** * ata_dump_status - user friendly display of error info * @id: id of the port in question @@ -2539,7 +2547,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) } qc->tf.command = ATA_CMD_PACKET; - qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len; + ata_qc_set_pc_nbytes(qc); /* check whether ATAPI DMA is safe */ if (!using_pio && ata_check_atapi_dma(qc)) @@ -2550,7 +2558,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) * want to set it properly, and for DMA where it is * effectively meaningless. */ - nbytes = min(scmd->request->data_len, (unsigned int)63 * 1024); + nbytes = min(ata_qc_raw_nbytes(qc), (unsigned int)63 * 1024); /* Most ATAPI devices which honor transfer chunk size don't * behave according to the spec when odd chunk size which @@ -2876,7 +2884,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * TODO: find out if we need to do more here to * cover scatter/gather case. */ - qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len; + ata_qc_set_pc_nbytes(qc); /* request result TF and be quiet about device error */ qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET; diff --git a/include/linux/libata.h b/include/linux/libata.h index a05f60013642..269cdba09578 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -463,6 +463,7 @@ struct ata_queued_cmd { unsigned int sect_size; unsigned int nbytes; + unsigned int extrabytes; unsigned int curbytes; struct scatterlist *cursg; @@ -1336,6 +1337,11 @@ static inline struct ata_queued_cmd *ata_qc_from_tag(struct ata_port *ap, return NULL; } +static inline unsigned int ata_qc_raw_nbytes(struct ata_queued_cmd *qc) +{ + return qc->nbytes - min(qc->extrabytes, qc->nbytes); +} + static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf) { memset(tf, 0, sizeof(*tf)); @@ -1354,7 +1360,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->flags = 0; qc->cursg = NULL; qc->cursg_ofs = 0; - qc->nbytes = qc->curbytes = 0; + qc->nbytes = qc->extrabytes = qc->curbytes = 0; qc->n_elem = 0; qc->err_mask = 0; qc->sect_size = ATA_SECT_SIZE; -- cgit v1.2.3 From 85a793533524f333e8d630dc22450e574b7e08d2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 24 Mar 2008 20:06:24 -0700 Subject: [SPARC64]: Make save_stack_trace() more efficient. Doing a 'flushw' every stack trace capture creates so much overhead that it makes lockdep next to unusable. We only care about the frame pointer chain and the function caller program counters, so flush those by hand to the stack frame. This is significantly more efficient than a 'flushw' because: 1) We only save 16 bytes per active register window to the stack. 2) This doesn't push the entire register window context of the current call chain out of the cpu, forcing register window fill traps as we return back down. Note that we can't use 'restore' and 'save' instructions to move around the register windows because that wouldn't work on Niagara processors. They optimize 'save' into a new register window by simply clearing out the registers instead of pulling them in from the on-chip register window backing store. Based upon a report by Tom Callaway. Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.S | 30 ++++++++++++++++++++++++++++++ arch/sparc64/kernel/stacktrace.c | 4 +++- include/asm-sparc64/stacktrace.h | 6 ++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 include/asm-sparc64/stacktrace.h (limited to 'include') diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 6be4d2d2904e..49eca4b1cf25 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1705,6 +1705,36 @@ __flushw_user: 2: retl nop + /* Flush %fp and %i7 to the stack for all register + * windows active inside of the cpu. This allows + * show_stack_trace() to avoid using an expensive + * 'flushw'. + */ + .globl stack_trace_flush + .type stack_trace_flush,#function +stack_trace_flush: + rdpr %pstate, %o0 + wrpr %o0, PSTATE_IE, %pstate + + rdpr %cwp, %g1 + rdpr %canrestore, %g2 + sub %g1, 1, %g3 + +1: brz,pn %g2, 2f + sub %g2, 1, %g2 + wrpr %g3, %cwp + stx %fp, [%sp + STACK_BIAS + RW_V9_I6] + stx %i7, [%sp + STACK_BIAS + RW_V9_I7] + ba,pt %xcc, 1b + sub %g3, 1, %g3 + +2: wrpr %g1, %cwp + wrpr %o0, %pstate + + retl + nop + .size stack_trace_flush,.-stack_trace_flush + #ifdef CONFIG_SMP .globl hard_smp_processor_id hard_smp_processor_id: diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c index 47f92a59be18..84d39e873e88 100644 --- a/arch/sparc64/kernel/stacktrace.c +++ b/arch/sparc64/kernel/stacktrace.c @@ -2,13 +2,15 @@ #include #include #include +#include void save_stack_trace(struct stack_trace *trace) { unsigned long ksp, fp, thread_base; struct thread_info *tp = task_thread_info(current); - flushw_all(); + stack_trace_flush(); + __asm__ __volatile__( "mov %%fp, %0" : "=r" (ksp) diff --git a/include/asm-sparc64/stacktrace.h b/include/asm-sparc64/stacktrace.h new file mode 100644 index 000000000000..6cee39adf6d6 --- /dev/null +++ b/include/asm-sparc64/stacktrace.h @@ -0,0 +1,6 @@ +#ifndef _SPARC64_STACKTRACE_H +#define _SPARC64_STACKTRACE_H + +extern void stack_trace_flush(void); + +#endif /* _SPARC64_STACKTRACE_H */ -- cgit v1.2.3 From 392e1d9817d0024c96aae237c3c4349e47c976fd Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 11 Mar 2008 10:20:12 -0400 Subject: USB: new quirk flag to avoid Set-Interface This patch (as1057) fixes a problem with the X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter; the device crashes when it receives a Set-Interface request. A new quirk (USB_QUIRK_NO_SET_INTF) is introduced and a quirks entry is created for this device. Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 5 ++++- drivers/usb/core/quirks.c | 3 +++ include/linux/usb/quirks.h | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fefb92296e8f..c311f67b7f08 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1206,7 +1206,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) return -EINVAL; } - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + if (dev->quirks & USB_QUIRK_NO_SET_INTF) + ret = -EPIPE; + else + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, interface, NULL, 0, 5000); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index d9d1eb19f2a1..dfc5418ea10c 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -50,6 +50,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, + /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */ + { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF }, + /* Action Semiconductor flash disk */ { USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255 }, diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 2692ec9389ca..1f999ec8d08c 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -9,3 +9,6 @@ /* device can't resume correctly so reset it instead */ #define USB_QUIRK_RESET_RESUME 0x00000002 + +/* device can't handle Set-Interface requests */ +#define USB_QUIRK_NO_SET_INTF 0x00000004 -- cgit v1.2.3 From cc36bdd47ae51b66780b317c1fa519221f894405 Mon Sep 17 00:00:00 2001 From: Constantin Baranov Date: Sun, 16 Mar 2008 20:04:23 +0000 Subject: USB: add support for Motorola ROKR Z6 cellphone in mass storage mode Motorola ROKR Z6 cellphone has bugs in its USB, so it is impossible to use it as mass storage. Patch describes new "unusual" USB device for it with FIX_INQUIRY and FIX_CAPACITY flags and new BULK_IGNORE_TAG flag. Last flag relaxes check for equality of bcs->Tag and us->tag in usb_stor_Bulk_transport routine. Signed-off-by: Constantin Baranov Signed-off-by: Matthew Dharm Signed-off-by: Daniel Drake Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/transport.c | 3 ++- drivers/usb/storage/unusual_devs.h | 11 +++++++++++ include/linux/usb_usual.h | 4 +++- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 5780ed15f1ad..bdd4334bed5a 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1009,7 +1009,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status); - if (bcs->Tag != us->tag || bcs->Status > US_BULK_STAT_PHASE) { + if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) || + bcs->Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 99679a8cfa02..e5219a56947c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1589,6 +1589,17 @@ UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* + * Patch by Constantin Baranov + * Report by Andreas Koenecke. + * Motorola ROKR Z6. + */ +UNUSUAL_DEV( 0x22b8, 0x6426, 0x0101, 0x0101, + "Motorola", + "MSnc.", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY | US_FL_BULK_IGNORE_TAG), + /* Reported by Radovan Garabik */ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, "MPIO", diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index cee0623b3c7b..0a40dfa44c9f 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -50,7 +50,9 @@ US_FLAG(CAPACITY_HEURISTICS, 0x00001000) \ /* sometimes sizes is too big */ \ US_FLAG(MAX_SECTORS_MIN,0x00002000) \ - /* Sets max_sectors to arch min */ + /* Sets max_sectors to arch min */ \ + US_FLAG(BULK_IGNORE_TAG,0x00004000) \ + /* Ignore tag mismatch in bulk operations */ #define US_FLAG(name, value) US_FL_##name = value , -- cgit v1.2.3 From 49741c4d01554c2630cea02cfdf236b17062a912 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 17 Mar 2008 14:21:18 -0700 Subject: PCI: revert "pcie: utilize pcie transaction pending bit" Revert as it is reported to cause problems for people. commit 4348a2dc49f9baecd34a9b0904245488c6189398 Author: Shaohua Li Date: Wed Oct 24 10:45:08 2007 +0800 pcie: utilize pcie transaction pending bit PCIE has a mechanism to wait for Non-Posted request to complete. I think pci_disable_device is a good place to do this. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman Due to the regression reported at http://bugzilla.kernel.org/show_bug.cgi?id=10065 Cc: Shaohua Li Cc: Soeren Sonnenburg Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 21 --------------------- include/linux/pci.h | 4 ---- 2 files changed, 25 deletions(-) (limited to 'include') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 183fddaa38b7..a4445b7210bf 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -314,24 +314,6 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap) } EXPORT_SYMBOL_GPL(pci_find_ht_capability); -void pcie_wait_pending_transaction(struct pci_dev *dev) -{ - int pos; - u16 reg16; - - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (!pos) - return; - while (1) { - pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, ®16); - if (!(reg16 & PCI_EXP_DEVSTA_TRPND)) - break; - cpu_relax(); - } - -} -EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction); - /** * pci_find_parent_resource - return resource region of parent bus of given region * @dev: PCI device structure contains resources to be searched @@ -936,9 +918,6 @@ pci_disable_device(struct pci_dev *dev) if (atomic_sub_return(1, &dev->enable_cnt) != 0) return; - /* Wait for all transactions are finished before disabling the device */ - pcie_wait_pending_transaction(dev); - pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; diff --git a/include/linux/pci.h b/include/linux/pci.h index b7e4b633c69b..ea760e519c46 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -513,7 +513,6 @@ int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap); int pci_find_ext_capability(struct pci_dev *dev, int cap); int pci_find_ht_capability(struct pci_dev *dev, int ht_cap); int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap); -void pcie_wait_pending_transaction(struct pci_dev *dev); struct pci_bus *pci_find_next_bus(const struct pci_bus *from); struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, @@ -884,9 +883,6 @@ static inline int pci_find_ext_capability(struct pci_dev *dev, int cap) return 0; } -static inline void pcie_wait_pending_transaction(struct pci_dev *dev) -{ } - /* Power management related routines */ static inline int pci_save_state(struct pci_dev *dev) { -- cgit v1.2.3 From 606d5b19391476f71e10ccce5b376f7071d11aba Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 25 Mar 2008 21:13:22 -0700 Subject: [SPARC64]: Adjust {TLBTEMP,TSBMAP}_BASE. Move them further from the main kernel image area to facilitate larger kernel sizes. Adjust comments to match. Signed-off-by: David S. Miller --- include/asm-sparc64/pgtable.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 3167ccff64f8..95303f5be86b 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -23,9 +23,9 @@ #include #include -/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB). - * The page copy blockops can use 0x2000000 to 0x4000000. - * The TSB is mapped in the 0x4000000 to 0x6000000 range. +/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). + * The page copy blockops can use 0x6000000 to 0x8000000. + * The TSB is mapped in the 0x8000000 to 0xa000000 range. * The PROM resides in an area spanning 0xf0000000 to 0x100000000. * The vmalloc area spans 0x100000000 to 0x200000000. * Since modules need to be in the lowest 32-bits of the address space, @@ -33,8 +33,8 @@ * There is a single static kernel PMD which maps from 0x0 to address * 0x400000000. */ -#define TLBTEMP_BASE _AC(0x0000000002000000,UL) -#define TSBMAP_BASE _AC(0x0000000004000000,UL) +#define TLBTEMP_BASE _AC(0x0000000006000000,UL) +#define TSBMAP_BASE _AC(0x0000000008000000,UL) #define MODULES_VADDR _AC(0x0000000010000000,UL) #define MODULES_LEN _AC(0x00000000e0000000,UL) #define MODULES_END _AC(0x00000000f0000000,UL) -- cgit v1.2.3 From 8b78cf602fd3bd97c0080edd22fe8fd5d0fa7832 Mon Sep 17 00:00:00 2001 From: Yi Yang Date: Mon, 25 Feb 2008 08:46:12 +0800 Subject: cpuidle: fix cpuidle time and usage overflow cpuidle C-state sysfs node time and usage are very easy to overflow because they are all of unsigned int type, time will overflow within about two hours, usage will take longer time to overflow, but they are increasing for ever. This patch will convert them to unsigned long long. Signed-off-by: Yi Yang Acked-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/cpuidle/cpuidle.c | 2 +- drivers/cpuidle/sysfs.c | 10 ++++++++-- include/linux/cpuidle.h | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d73663a52324..d42deb310ac7 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -67,7 +67,7 @@ static void cpuidle_idle_call(void) /* enter the state and update stats */ dev->last_residency = target_state->enter(dev, target_state); dev->last_state = target_state; - target_state->time += dev->last_residency; + target_state->time += (unsigned long long)dev->last_residency; target_state->usage++; /* give the governor an opportunity to reflect on the outcome */ diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 69102ca05685..e949618b9be0 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -218,6 +218,12 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ return sprintf(buf, "%u\n", state->_name);\ } +#define define_show_state_ull_function(_name) \ +static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ +{ \ + return sprintf(buf, "%llu\n", state->_name);\ +} + #define define_show_state_str_function(_name) \ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ { \ @@ -228,8 +234,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ define_show_state_function(exit_latency) define_show_state_function(power_usage) -define_show_state_function(usage) -define_show_state_function(time) +define_show_state_ull_function(usage) +define_show_state_ull_function(time) define_show_state_str_function(name) define_show_state_str_function(desc) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6b72a4584086..51e6b1e520e6 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -38,8 +38,8 @@ struct cpuidle_state { unsigned int power_usage; /* in mW */ unsigned int target_residency; /* in US */ - unsigned int usage; - unsigned int time; /* in US */ + unsigned long long usage; + unsigned long long time; /* in US */ int (*enter) (struct cpuidle_device *dev, struct cpuidle_state *state); -- cgit v1.2.3 From 3d5ae6b69eacfac025021998d2ce159768edcfe1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 25 Mar 2008 21:51:40 -0700 Subject: [SPARC64]: Fix sparse warnings in arch/sparc64/kernel/{cpu,setup}.c We create a local header file entry.h, under arch/sparc64/kernel/, that we can use to declare routines either defined in assembler or only invoked from assembler. As well as other data objects which are private to the inner sparc64 kernel arch code. Signed-off-by: David S. Miller --- arch/sparc64/kernel/cpu.c | 10 ++++++---- arch/sparc64/kernel/entry.h | 15 +++++++++++++++ arch/sparc64/kernel/setup.c | 5 ++--- arch/sparc64/mm/init.c | 1 + include/asm-sparc64/cpudata.h | 2 ++ 5 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 arch/sparc64/kernel/entry.h (limited to 'include') diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index dd5d28e3d798..0097c08dc600 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c @@ -15,6 +15,8 @@ #include #include +#include "entry.h" + DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; struct cpu_iu_info { @@ -65,8 +67,6 @@ static struct cpu_iu_info linux_sparc_chips[] = { char *sparc_cpu_type; char *sparc_fpu_type; -unsigned int fsr_storage; - static void __init sun4v_cpu_probe(void) { switch (sun4v_chip_type) { @@ -94,8 +94,10 @@ void __init cpu_probe(void) unsigned long ver, fpu_vers, manuf, impl, fprs; int i; - if (tlb_type == hypervisor) - return sun4v_cpu_probe(); + if (tlb_type == hypervisor) { + sun4v_cpu_probe(); + return; + } fprs = fprs_read(); fprs_write(FPRS_FEF); diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h new file mode 100644 index 000000000000..bfcd1b8d23dc --- /dev/null +++ b/arch/sparc64/kernel/entry.h @@ -0,0 +1,15 @@ +#ifndef _ENTRY_H +#define _ENTRY_H + +#include + +extern char *sparc_cpu_type; +extern char *sparc_fpu_type; + +extern void __init per_cpu_patch(void); +extern void __init sun4v_patch(void); +extern void __init boot_cpu_id_too_large(int cpu); +extern unsigned int dcache_parity_tl1_occurred; +extern unsigned int icache_parity_tl1_occurred; + +#endif /* _ENTRY_H */ diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index d036dbe72864..6acb4c51cfe4 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -51,6 +51,8 @@ #include #endif +#include "entry.h" + /* Used to synchronize accesses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h */ @@ -335,9 +337,6 @@ void __init setup_arch(char **cmdline_p) /* BUFFER is PAGE_SIZE bytes long. */ -extern char *sparc_cpu_type; -extern char *sparc_fpu_type; - extern void smp_info(struct seq_file *); extern void smp_bogo(struct seq_file *); extern void mmu_info(struct seq_file *); diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 466fd6cffac9..fced6dfe77a8 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -46,6 +46,7 @@ #include #include #include +#include #define MAX_PHYS_ADDRESS (1UL << 42UL) #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h index 542421460a12..532975ecfe10 100644 --- a/include/asm-sparc64/cpudata.h +++ b/include/asm-sparc64/cpudata.h @@ -86,6 +86,8 @@ extern struct trap_per_cpu trap_block[NR_CPUS]; extern void init_cur_cpu_trap(struct thread_info *); extern void setup_tba(void); extern int ncpus_probed; +extern void __init cpu_probe(void); +extern const struct seq_operations cpuinfo_op; extern unsigned long real_hard_smp_processor_id(void); -- cgit v1.2.3 From 99cd220133cdf2a559529d522a78b2ebc1bef2d8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 26 Mar 2008 00:19:43 -0700 Subject: [SPARC64]: Fix sparse errors in arch/sparc64/kernel/traps.c Add 'UL' markers to DCU_* macros. Declare C functions called from assembler in entry.h Declare C functions called from within the sparc64 arch code in include/asm-sparc64/*.h headers as appropriate. Remove unused routines in traps.c Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.h | 141 ++++++++++++++++++++++++++++++++++++++++++ arch/sparc64/kernel/traps.c | 49 +-------------- arch/sparc64/mm/init.c | 4 -- include/asm-sparc64/dcu.h | 41 ++++++------ include/asm-sparc64/pgtable.h | 2 + 5 files changed, 167 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index bfcd1b8d23dc..a5084d6821ba 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -2,6 +2,7 @@ #define _ENTRY_H #include +#include extern char *sparc_cpu_type; extern char *sparc_fpu_type; @@ -12,4 +13,144 @@ extern void __init boot_cpu_id_too_large(int cpu); extern unsigned int dcache_parity_tl1_occurred; extern unsigned int icache_parity_tl1_occurred; +extern void bad_trap_tl1(struct pt_regs *regs, long lvl); + +extern void do_fpe_common(struct pt_regs *regs); +extern void do_fpieee(struct pt_regs *regs); +extern void do_fpother(struct pt_regs *regs); +extern void do_tof(struct pt_regs *regs); +extern void do_div0(struct pt_regs *regs); +extern void do_illegal_instruction(struct pt_regs *regs); +extern void mem_address_unaligned(struct pt_regs *regs, + unsigned long sfar, + unsigned long sfsr); +extern void sun4v_do_mna(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void do_privop(struct pt_regs *regs); +extern void do_privact(struct pt_regs *regs); +extern void do_cee(struct pt_regs *regs); +extern void do_cee_tl1(struct pt_regs *regs); +extern void do_dae_tl1(struct pt_regs *regs); +extern void do_iae_tl1(struct pt_regs *regs); +extern void do_div0_tl1(struct pt_regs *regs); +extern void do_fpdis_tl1(struct pt_regs *regs); +extern void do_fpieee_tl1(struct pt_regs *regs); +extern void do_fpother_tl1(struct pt_regs *regs); +extern void do_ill_tl1(struct pt_regs *regs); +extern void do_irq_tl1(struct pt_regs *regs); +extern void do_lddfmna_tl1(struct pt_regs *regs); +extern void do_stdfmna_tl1(struct pt_regs *regs); +extern void do_paw(struct pt_regs *regs); +extern void do_paw_tl1(struct pt_regs *regs); +extern void do_vaw(struct pt_regs *regs); +extern void do_vaw_tl1(struct pt_regs *regs); +extern void do_tof_tl1(struct pt_regs *regs); +extern void do_getpsr(struct pt_regs *regs); + +extern void spitfire_insn_access_exception(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_insn_access_exception_tl1(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_data_access_exception(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_data_access_exception_tl1(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_access_error(struct pt_regs *regs, + unsigned long status_encoded, + unsigned long afar); + +extern void cheetah_fecc_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_cee_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_deferred_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_plus_parity_error(int type, struct pt_regs *regs); + +extern void sun4v_insn_access_exception(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_insn_access_exception_tl1(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_data_access_exception(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_data_access_exception_tl1(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_resum_error(struct pt_regs *regs, + unsigned long offset); +extern void sun4v_resum_overflow(struct pt_regs *regs); +extern void sun4v_nonresum_error(struct pt_regs *regs, + unsigned long offset); +extern void sun4v_nonresum_overflow(struct pt_regs *regs); + +extern unsigned long sun4v_err_itlb_vaddr; +extern unsigned long sun4v_err_itlb_ctx; +extern unsigned long sun4v_err_itlb_pte; +extern unsigned long sun4v_err_itlb_error; + +extern void sun4v_itlb_error_report(struct pt_regs *regs, int tl); + +extern unsigned long sun4v_err_dtlb_vaddr; +extern unsigned long sun4v_err_dtlb_ctx; +extern unsigned long sun4v_err_dtlb_pte; +extern unsigned long sun4v_err_dtlb_error; + +extern void sun4v_dtlb_error_report(struct pt_regs *regs, int tl); +extern void hypervisor_tlbop_error(unsigned long err, + unsigned long op); +extern void hypervisor_tlbop_error_xcall(unsigned long err, + unsigned long op); + +/* WARNING: The error trap handlers in assembly know the precise + * layout of the following structure. + * + * C-level handlers in traps.c use this information to log the + * error and then determine how to recover (if possible). + */ +struct cheetah_err_info { +/*0x00*/u64 afsr; +/*0x08*/u64 afar; + + /* D-cache state */ +/*0x10*/u64 dcache_data[4]; /* The actual data */ +/*0x30*/u64 dcache_index; /* D-cache index */ +/*0x38*/u64 dcache_tag; /* D-cache tag/valid */ +/*0x40*/u64 dcache_utag; /* D-cache microtag */ +/*0x48*/u64 dcache_stag; /* D-cache snooptag */ + + /* I-cache state */ +/*0x50*/u64 icache_data[8]; /* The actual insns + predecode */ +/*0x90*/u64 icache_index; /* I-cache index */ +/*0x98*/u64 icache_tag; /* I-cache phys tag */ +/*0xa0*/u64 icache_utag; /* I-cache microtag */ +/*0xa8*/u64 icache_stag; /* I-cache snooptag */ +/*0xb0*/u64 icache_upper; /* I-cache upper-tag */ +/*0xb8*/u64 icache_lower; /* I-cache lower-tag */ + + /* E-cache state */ +/*0xc0*/u64 ecache_data[4]; /* 32 bytes from staging registers */ +/*0xe0*/u64 ecache_index; /* E-cache index */ +/*0xe8*/u64 ecache_tag; /* E-cache tag/state */ + +/*0xf0*/u64 __pad[32 - 30]; +}; +#define CHAFSR_INVALID ((u64)-1L) + +/* This is allocated at boot time based upon the largest hardware + * cpu ID in the system. We allocate two entries per cpu, one for + * TL==0 logging and one for TL >= 1 logging. + */ +extern struct cheetah_err_info *cheetah_error_log; + #endif /* _ENTRY_H */ diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 007f5317c0de..96da847023f3 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -42,6 +42,7 @@ #endif #include +#include "entry.h" /* When an irrecoverable trap occurs at tl > 0, the trap entry * code logs the trap state registers at every level in the trap @@ -77,11 +78,6 @@ static void dump_tl1_traplog(struct tl1_traplog *p) } } -void do_call_debug(struct pt_regs *regs) -{ - notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); -} - void bad_trap(struct pt_regs *regs, long lvl) { char buffer[32]; @@ -550,41 +546,6 @@ static unsigned long ecache_flush_physbase; static unsigned long ecache_flush_linesize; static unsigned long ecache_flush_size; -/* WARNING: The error trap handlers in assembly know the precise - * layout of the following structure. - * - * C-level handlers below use this information to log the error - * and then determine how to recover (if possible). - */ -struct cheetah_err_info { -/*0x00*/u64 afsr; -/*0x08*/u64 afar; - - /* D-cache state */ -/*0x10*/u64 dcache_data[4]; /* The actual data */ -/*0x30*/u64 dcache_index; /* D-cache index */ -/*0x38*/u64 dcache_tag; /* D-cache tag/valid */ -/*0x40*/u64 dcache_utag; /* D-cache microtag */ -/*0x48*/u64 dcache_stag; /* D-cache snooptag */ - - /* I-cache state */ -/*0x50*/u64 icache_data[8]; /* The actual insns + predecode */ -/*0x90*/u64 icache_index; /* I-cache index */ -/*0x98*/u64 icache_tag; /* I-cache phys tag */ -/*0xa0*/u64 icache_utag; /* I-cache microtag */ -/*0xa8*/u64 icache_stag; /* I-cache snooptag */ -/*0xb0*/u64 icache_upper; /* I-cache upper-tag */ -/*0xb8*/u64 icache_lower; /* I-cache lower-tag */ - - /* E-cache state */ -/*0xc0*/u64 ecache_data[4]; /* 32 bytes from staging registers */ -/*0xe0*/u64 ecache_index; /* E-cache index */ -/*0xe8*/u64 ecache_tag; /* E-cache tag/state */ - -/*0xf0*/u64 __pad[32 - 30]; -}; -#define CHAFSR_INVALID ((u64)-1L) - /* This table is ordered in priority of errors and matches the * AFAR overwrite policy as well. */ @@ -758,10 +719,6 @@ static struct afsr_error_table __jalapeno_error_table[] = { static struct afsr_error_table *cheetah_error_table; static unsigned long cheetah_afsr_errors; -/* This is allocated at boot time based upon the largest hardware - * cpu ID in the system. We allocate two entries per cpu, one for - * TL==0 logging and one for TL >= 1 logging. - */ struct cheetah_err_info *cheetah_error_log; static inline struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr) @@ -2102,7 +2059,7 @@ void do_div0(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); } -void instruction_dump (unsigned int *pc) +static void instruction_dump(unsigned int *pc) { int i; @@ -2115,7 +2072,7 @@ void instruction_dump (unsigned int *pc) printk("\n"); } -static void user_instruction_dump (unsigned int __user *pc) +static void user_instruction_dump(unsigned int __user *pc) { int i; unsigned int buf[9]; diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index fced6dfe77a8..f37078d96407 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1274,10 +1274,6 @@ void __cpuinit sun4v_ktsb_register(void) /* paging_init() sets up the page tables */ -extern void cheetah_ecache_flush_init(void); -extern void sun4v_patch_tlb_handlers(void); - -extern void cpu_probe(void); extern void central_probe(void); static unsigned long last_valid_pfn; diff --git a/include/asm-sparc64/dcu.h b/include/asm-sparc64/dcu.h index ecbed2ae548f..0f704e106a1b 100644 --- a/include/asm-sparc64/dcu.h +++ b/include/asm-sparc64/dcu.h @@ -1,26 +1,27 @@ -/* $Id: dcu.h,v 1.2 2001/03/01 23:23:33 davem Exp $ */ #ifndef _SPARC64_DCU_H #define _SPARC64_DCU_H +#include + /* UltraSparc-III Data Cache Unit Control Register */ -#define DCU_CP 0x0002000000000000 /* Physical Cache Enable w/o mmu*/ -#define DCU_CV 0x0001000000000000 /* Virtual Cache Enable w/o mmu */ -#define DCU_ME 0x0000800000000000 /* NC-store Merging Enable */ -#define DCU_RE 0x0000400000000000 /* RAW bypass Enable */ -#define DCU_PE 0x0000200000000000 /* PCache Enable */ -#define DCU_HPE 0x0000100000000000 /* HW prefetch Enable */ -#define DCU_SPE 0x0000080000000000 /* SW prefetch Enable */ -#define DCU_SL 0x0000040000000000 /* Secondary load steering Enab */ -#define DCU_WE 0x0000020000000000 /* WCache enable */ -#define DCU_PM 0x000001fe00000000 /* PA Watchpoint Byte Mask */ -#define DCU_VM 0x00000001fe000000 /* VA Watchpoint Byte Mask */ -#define DCU_PR 0x0000000001000000 /* PA Watchpoint Read Enable */ -#define DCU_PW 0x0000000000800000 /* PA Watchpoint Write Enable */ -#define DCU_VR 0x0000000000400000 /* VA Watchpoint Read Enable */ -#define DCU_VW 0x0000000000200000 /* VA Watchpoint Write Enable */ -#define DCU_DM 0x0000000000000008 /* DMMU Enable */ -#define DCU_IM 0x0000000000000004 /* IMMU Enable */ -#define DCU_DC 0x0000000000000002 /* Data Cache Enable */ -#define DCU_IC 0x0000000000000001 /* Instruction Cache Enable */ +#define DCU_CP _AC(0x0002000000000000,UL) /* Phys Cache Enable w/o mmu */ +#define DCU_CV _AC(0x0001000000000000,UL) /* Virt Cache Enable w/o mmu */ +#define DCU_ME _AC(0x0000800000000000,UL) /* NC-store Merging Enable */ +#define DCU_RE _AC(0x0000400000000000,UL) /* RAW bypass Enable */ +#define DCU_PE _AC(0x0000200000000000,UL) /* PCache Enable */ +#define DCU_HPE _AC(0x0000100000000000,UL) /* HW prefetch Enable */ +#define DCU_SPE _AC(0x0000080000000000,UL) /* SW prefetch Enable */ +#define DCU_SL _AC(0x0000040000000000,UL) /* Secondary ld-steering Enab*/ +#define DCU_WE _AC(0x0000020000000000,UL) /* WCache enable */ +#define DCU_PM _AC(0x000001fe00000000,UL) /* PA Watchpoint Byte Mask */ +#define DCU_VM _AC(0x00000001fe000000,UL) /* VA Watchpoint Byte Mask */ +#define DCU_PR _AC(0x0000000001000000,UL) /* PA Watchpoint Read Enable */ +#define DCU_PW _AC(0x0000000000800000,UL) /* PA Watchpoint Write Enable*/ +#define DCU_VR _AC(0x0000000000400000,UL) /* VA Watchpoint Read Enable */ +#define DCU_VW _AC(0x0000000000200000,UL) /* VA Watchpoint Write Enable*/ +#define DCU_DM _AC(0x0000000000000008,UL) /* DMMU Enable */ +#define DCU_IM _AC(0x0000000000000004,UL) /* IMMU Enable */ +#define DCU_DC _AC(0x0000000000000002,UL) /* Data Cache Enable */ +#define DCU_IC _AC(0x0000000000000001,UL) /* Instruction Cache Enable */ #endif /* _SPARC64_DCU_H */ diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 95303f5be86b..549e45266b68 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -761,6 +761,8 @@ extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long, extern void pgtable_cache_init(void); extern void sun4v_register_fault_status(void); extern void sun4v_ktsb_register(void); +extern void __init cheetah_ecache_flush_init(void); +extern void sun4v_patch_tlb_handlers(void); extern unsigned long cmdline_memory_size; -- cgit v1.2.3 From 06d8308c61e54346585b2691c13ee3f90cb6fb2f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 22 Mar 2008 09:20:24 +0100 Subject: NOHZ: reevaluate idle sleep length after add_timer_on() add_timer_on() can add a timer on a CPU which is currently in a long idle sleep, but the timer wheel is not reevaluated by the nohz code on that CPU. So a timer can be delayed for quite a long time. This triggered a false positive in the clocksource watchdog code. To avoid this we need to wake up the idle CPU and enforce the reevaluation of the timer wheel for the next timer event. Add a function, which checks a given CPU for idle state, marks the idle task with NEED_RESCHED and sends a reschedule IPI to notify the other CPU of the change in the timer wheel. Call this function from add_timer_on(). Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra Acked-by: Ingo Molnar Cc: stable@kernel.org -- include/linux/sched.h | 6 ++++++ kernel/sched.c | 43 +++++++++++++++++++++++++++++++++++++++++++ kernel/timer.c | 10 +++++++++- 3 files changed, 58 insertions(+), 1 deletion(-) --- include/linux/sched.h | 6 ++++++ kernel/sched.c | 43 +++++++++++++++++++++++++++++++++++++++++++ kernel/timer.c | 10 +++++++++- 3 files changed, 58 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index fed07d03364e..6a1e7afb099b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1541,6 +1541,12 @@ static inline void idle_task_exit(void) {} extern void sched_idle_next(void); +#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) +extern void wake_up_idle_cpu(int cpu); +#else +static inline void wake_up_idle_cpu(int cpu) { } +#endif + #ifdef CONFIG_SCHED_DEBUG extern unsigned int sysctl_sched_latency; extern unsigned int sysctl_sched_min_granularity; diff --git a/kernel/sched.c b/kernel/sched.c index 28c73f07efb2..8dcdec6fe0fe 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1052,6 +1052,49 @@ static void resched_cpu(int cpu) resched_task(cpu_curr(cpu)); spin_unlock_irqrestore(&rq->lock, flags); } + +#ifdef CONFIG_NO_HZ +/* + * When add_timer_on() enqueues a timer into the timer wheel of an + * idle CPU then this timer might expire before the next timer event + * which is scheduled to wake up that CPU. In case of a completely + * idle system the next event might even be infinite time into the + * future. wake_up_idle_cpu() ensures that the CPU is woken up and + * leaves the inner idle loop so the newly added timer is taken into + * account when the CPU goes back to idle and evaluates the timer + * wheel for the next timer event. + */ +void wake_up_idle_cpu(int cpu) +{ + struct rq *rq = cpu_rq(cpu); + + if (cpu == smp_processor_id()) + return; + + /* + * This is safe, as this function is called with the timer + * wheel base lock of (cpu) held. When the CPU is on the way + * to idle and has not yet set rq->curr to idle then it will + * be serialized on the timer wheel base lock and take the new + * timer into account automatically. + */ + if (rq->curr != rq->idle) + return; + + /* + * We can set TIF_RESCHED on the idle task of the other CPU + * lockless. The worst case is that the other CPU runs the + * idle task through an additional NOOP schedule() + */ + set_tsk_thread_flag(rq->idle, TIF_NEED_RESCHED); + + /* NEED_RESCHED must be visible before we test polling */ + smp_mb(); + if (!tsk_is_polling(rq->idle)) + smp_send_reschedule(cpu); +} +#endif + #else static void __resched_task(struct task_struct *p, int tif_bit) { diff --git a/kernel/timer.c b/kernel/timer.c index 99b00a25f88b..b024106daa70 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -451,10 +451,18 @@ void add_timer_on(struct timer_list *timer, int cpu) spin_lock_irqsave(&base->lock, flags); timer_set_base(timer, base); internal_add_timer(base, timer); + /* + * Check whether the other CPU is idle and needs to be + * triggered to reevaluate the timer wheel when nohz is + * active. We are protected against the other CPU fiddling + * with the timer by holding the timer base lock. This also + * makes sure that a CPU on the way to idle can not evaluate + * the timer wheel. + */ + wake_up_idle_cpu(cpu); spin_unlock_irqrestore(&base->lock, flags); } - /** * mod_timer - modify a timer's timeout * @timer: the timer to be modified -- cgit v1.2.3 From d91aa123b4b96e57680a39fb9dfd9722f8df3c7e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 26 Mar 2008 00:37:51 -0700 Subject: [SPARC64]: Fix sparse warnings in arch/sparc64/kernel/irq.c Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.h | 27 +++++++++++++++++++++++++++ arch/sparc64/kernel/irq.c | 21 ++------------------- include/asm-sparc64/irq.h | 1 + 3 files changed, 30 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index a5084d6821ba..e66d94c7caff 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -153,4 +153,31 @@ struct cheetah_err_info { */ extern struct cheetah_err_info *cheetah_error_log; +/* UPA nodes send interrupt packet to UltraSparc with first data reg + * value low 5 (7 on Starfire) bits holding the IRQ identifier being + * delivered. We must translate this into a non-vector IRQ so we can + * set the softint on this cpu. + * + * To make processing these packets efficient and race free we use + * an array of irq buckets below. The interrupt vector handler in + * entry.S feeds incoming packets into per-cpu pil-indexed lists. + * + * If you make changes to ino_bucket, please update hand coded assembler + * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S + */ +struct ino_bucket { +/*0x00*/unsigned long __irq_chain_pa; + + /* Virtual interrupt number assigned to this INO. */ +/*0x08*/unsigned int __virt_irq; +/*0x0c*/unsigned int __pad; +}; + +extern struct ino_bucket *ivector_table; +extern unsigned long ivector_table_pa; + +extern void handler_irq(int irq, struct pt_regs *regs); +extern void init_irqwork_curcpu(void); +extern void __cpuinit sun4v_register_mondo_queues(int this_cpu); + #endif /* _ENTRY_H */ diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 5ec06c8c7fea..eb88bd6e674e 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -44,27 +44,10 @@ #include #include -/* UPA nodes send interrupt packet to UltraSparc with first data reg - * value low 5 (7 on Starfire) bits holding the IRQ identifier being - * delivered. We must translate this into a non-vector IRQ so we can - * set the softint on this cpu. - * - * To make processing these packets efficient and race free we use - * an array of irq buckets below. The interrupt vector handler in - * entry.S feeds incoming packets into per-cpu pil-indexed lists. - * - * If you make changes to ino_bucket, please update hand coded assembler - * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S - */ -struct ino_bucket { -/*0x00*/unsigned long __irq_chain_pa; - - /* Virtual interrupt number assigned to this INO. */ -/*0x08*/unsigned int __virt_irq; -/*0x0c*/unsigned int __pad; -}; +#include "entry.h" #define NUM_IVECS (IMAP_INR + 1) + struct ino_bucket *ivector_table; unsigned long ivector_table_pa; diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index 30cb76b47be1..0bb9bf531745 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -64,6 +64,7 @@ extern unsigned char virt_irq_alloc(unsigned int dev_handle, extern void virt_irq_free(unsigned int virt_irq); #endif +extern void __init init_IRQ(void); extern void fixup_irqs(void); static inline void set_softint(unsigned long bits) -- cgit v1.2.3 From cf3d7c1ef418863376d556c48c214cb828623584 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 26 Mar 2008 01:11:55 -0700 Subject: [SPARC64]: Fix sparse warnings in arch/sparc64/kernel/time.c Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.h | 2 ++ arch/sparc64/kernel/smp.c | 3 ++- arch/sparc64/kernel/time.c | 66 +++++++++++++++++++++++++++------------------ include/asm-sparc64/timer.h | 9 ++++--- 4 files changed, 49 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index 0d0de9c32a80..4e238a11bdfe 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -14,6 +14,8 @@ extern void __init boot_cpu_id_too_large(int cpu); extern unsigned int dcache_parity_tl1_occurred; extern unsigned int icache_parity_tl1_occurred; +extern void timer_interrupt(int irq, struct pt_regs *regs); + extern asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p); diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 5a1126b363a4..59f020d69d4c 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -1,6 +1,6 @@ /* smp.c: Sparc64 SMP support. * - * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include @@ -30,6 +30,7 @@ #include #include #include +#include #include #include diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index d204f1ab1d4c..e5d238970c7e 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -1,7 +1,6 @@ -/* $Id: time.c,v 1.42 2002/01/23 14:33:55 davem Exp $ - * time.c: UltraSparc timer and TOD clock support. +/* time.c: UltraSparc timer and TOD clock support. * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * * Based largely on code which is: @@ -48,6 +47,8 @@ #include #include +#include "entry.h" + DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); void __iomem *mstk48t02_regs = NULL; @@ -508,6 +509,37 @@ static int __init has_low_battery(void) return (data1 == data2); /* Was the write blocked? */ } +static void __init mostek_set_system_time(void __iomem *mregs) +{ + unsigned int year, mon, day, hour, min, sec; + u8 tmp; + + spin_lock_irq(&mostek_lock); + + /* Traditional Mostek chip. */ + tmp = mostek_read(mregs + MOSTEK_CREG); + tmp |= MSTK_CREG_READ; + mostek_write(mregs + MOSTEK_CREG, tmp); + + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); + + tmp = mostek_read(mregs + MOSTEK_CREG); + tmp &= ~MSTK_CREG_READ; + mostek_write(mregs + MOSTEK_CREG, tmp); + + spin_unlock_irq(&mostek_lock); +} + /* Probe for the real time clock chip. */ static void __init set_system_time(void) { @@ -520,7 +552,6 @@ static void __init set_system_time(void) unsigned long dregs = 0UL; void __iomem *bregs = 0UL; #endif - u8 tmp; if (!mregs && !dregs && !bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); @@ -528,20 +559,11 @@ static void __init set_system_time(void) } if (mregs) { - spin_lock_irq(&mostek_lock); - - /* Traditional Mostek chip. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); + mostek_set_system_time(mregs); + return; + } - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - } else if (bregs) { + if (bregs) { unsigned char val = readb(bregs + 0x0e); unsigned int century; @@ -596,14 +618,6 @@ static void __init set_system_time(void) xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - - if (mregs) { - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - } } /* davem suggests we keep this within the 4M locked kernel image */ @@ -1027,7 +1041,7 @@ void __init time_init(void) setup_clockevent_multiplier(clock); sparc64_clockevent.max_delta_ns = - clockevent_delta2ns(0x7fffffffffffffff, &sparc64_clockevent); + clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); sparc64_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &sparc64_clockevent); diff --git a/include/asm-sparc64/timer.h b/include/asm-sparc64/timer.h index ccbd69448866..5b779fd1f788 100644 --- a/include/asm-sparc64/timer.h +++ b/include/asm-sparc64/timer.h @@ -1,14 +1,13 @@ -/* $Id: timer.h,v 1.3 2000/05/09 17:40:15 davem Exp $ - * timer.h: System timer definitions for sun5. +/* timer.h: System timer definitions for sun5. * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net) */ #ifndef _SPARC64_TIMER_H #define _SPARC64_TIMER_H #include - +#include struct sparc64_tick_ops { unsigned long (*get_tick)(void); @@ -25,5 +24,7 @@ struct sparc64_tick_ops { extern struct sparc64_tick_ops *tick_ops; extern unsigned long sparc64_get_clock_tick(unsigned int cpu); +extern void __devinit setup_sparc64_timer(void); +extern void __init time_init(void); #endif /* _SPARC64_TIMER_H */ -- cgit v1.2.3 From 9bbafce2eec190ef7e44b0eb1095ba17ce6ad3af Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Mar 2008 19:02:47 +0900 Subject: sh: Fix occasional FPU register corruption under preempt. Presently with preempt enabled there's the possibility to be preempted after the TIF_USEDFPU test and the register save, leading to bogus state post-__switch_to(). Use an explicit preempt_disable()/enable() pair around unlazy_fpu()/clear_fpu() to avoid this. Follows the x86 change. Reported-by: Takuo Koguchi Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh2a/fpu.c | 1 + arch/sh/kernel/cpu/sh4/fpu.c | 1 + arch/sh/kernel/cpu/sh5/fpu.c | 1 + arch/sh/kernel/dump_task.c | 1 + arch/sh/kernel/process_32.c | 1 + arch/sh/kernel/signal_32.c | 1 + include/asm-sh/fpu.h | 32 ++++++++++++++++++-------------- include/asm-sh/processor.h | 1 - include/asm-sh/processor_32.h | 1 + include/asm-sh/processor_64.h | 1 + 10 files changed, 26 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c index ff99562456fb..5627c0b3ffa8 100644 --- a/arch/sh/kernel/cpu/sh2a/fpu.c +++ b/arch/sh/kernel/cpu/sh2a/fpu.c @@ -13,6 +13,7 @@ #include #include #include +#include /* The PR (precision) bit in the FP Status Register must be clear when * an frchg instruction is executed, otherwise the instruction is undefined. diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index 817f9939cda6..8020796139f1 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c @@ -16,6 +16,7 @@ #include #include #include +#include /* The PR (precision) bit in the FP Status Register must be clear when * an frchg instruction is executed, otherwise the instruction is undefined. diff --git a/arch/sh/kernel/cpu/sh5/fpu.c b/arch/sh/kernel/cpu/sh5/fpu.c index 30b76a94abf2..dd4f51ffb50e 100644 --- a/arch/sh/kernel/cpu/sh5/fpu.c +++ b/arch/sh/kernel/cpu/sh5/fpu.c @@ -17,6 +17,7 @@ #include #include #include +#include /* * Initially load the FPU with signalling NANS. This bit pattern diff --git a/arch/sh/kernel/dump_task.c b/arch/sh/kernel/dump_task.c index 4a8a4083ff0b..1db7ce0f25d4 100644 --- a/arch/sh/kernel/dump_task.c +++ b/arch/sh/kernel/dump_task.c @@ -1,5 +1,6 @@ #include #include +#include /* * Capture the user space registers if the task is not running (in user space) diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 9ab1926b9d10..b98e37a1f54c 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -25,6 +25,7 @@ #include #include #include +#include static int hlt_counter; int ubc_usercnt = 0; diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index f6b5fbfe75c4..f311551d9a05 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c @@ -29,6 +29,7 @@ #include #include #include +#include #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) diff --git a/include/asm-sh/fpu.h b/include/asm-sh/fpu.h index f8429880a270..f89abf5920d8 100644 --- a/include/asm-sh/fpu.h +++ b/include/asm-sh/fpu.h @@ -1,9 +1,8 @@ #ifndef __ASM_SH_FPU_H #define __ASM_SH_FPU_H -#define SR_FD 0x00008000 - #ifndef __ASSEMBLY__ +#include #include #ifdef CONFIG_SH_FPU @@ -28,18 +27,23 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); extern int do_fpu_inst(unsigned short, struct pt_regs *); -#define unlazy_fpu(tsk, regs) do { \ - if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ - save_fpu(tsk, regs); \ - } \ -} while (0) - -#define clear_fpu(tsk, regs) do { \ - if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ - clear_tsk_thread_flag(tsk, TIF_USEDFPU); \ - release_fpu(regs); \ - } \ -} while (0) +static inline void unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs) +{ + preempt_disable(); + if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) + save_fpu(tsk, regs); + preempt_enable(); +} + +static inline void clear_fpu(struct task_struct *tsk, struct pt_regs *regs) +{ + preempt_disable(); + if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { + clear_tsk_thread_flag(tsk, TIF_USEDFPU); + release_fpu(regs); + } + preempt_enable(); +} #endif /* __ASSEMBLY__ */ diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index 19fe47c1ca17..ec707b98e5b9 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -2,7 +2,6 @@ #define __ASM_SH_PROCESSOR_H #include -#include #ifndef __ASSEMBLY__ /* diff --git a/include/asm-sh/processor_32.h b/include/asm-sh/processor_32.h index df2d5b039ef4..c09305d6a9d9 100644 --- a/include/asm-sh/processor_32.h +++ b/include/asm-sh/processor_32.h @@ -70,6 +70,7 @@ extern struct sh_cpuinfo cpu_data[]; */ #define SR_DSP 0x00001000 #define SR_IMASK 0x000000f0 +#define SR_FD 0x00008000 /* * FPU structure and data diff --git a/include/asm-sh/processor_64.h b/include/asm-sh/processor_64.h index eda4bef448e9..88a2edf8fa5d 100644 --- a/include/asm-sh/processor_64.h +++ b/include/asm-sh/processor_64.h @@ -112,6 +112,7 @@ extern struct sh_cpuinfo cpu_data[]; #endif #define SR_IMASK 0x000000f0 +#define SR_FD 0x00008000 #define SR_SSTEP 0x08000000 #ifndef __ASSEMBLY__ -- cgit v1.2.3 From 138bed154eab2205b4ef93f02f5feb1edf6d8552 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Mar 2008 19:09:21 +0900 Subject: sh: Fix TIF_USEDFPU clearing under FPU emulation. The unlazy_fpu() path calls in to save_fpu() if the task has TIF_USEDFPU set. save_fpu() being the crap API that it is has the side effect of clearing the flag itself, which presently doesn't happen if we're using FPU emulation. Fix this up for now, pending an overhaul in 2.6.26. Signed-off-by: Paul Mundt --- include/asm-sh/fpu.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-sh/fpu.h b/include/asm-sh/fpu.h index f89abf5920d8..91462fea1507 100644 --- a/include/asm-sh/fpu.h +++ b/include/asm-sh/fpu.h @@ -20,9 +20,14 @@ struct task_struct; extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); #else + #define release_fpu(regs) do { } while (0) #define grab_fpu(regs) do { } while (0) -#define save_fpu(tsk, regs) do { } while (0) + +static inline void save_fpu(struct task_struct *tsk, struct pt_regs *regs) +{ + clear_tsk_thread_flag(tsk, TIF_USEDFPU); +} #endif extern int do_fpu_inst(unsigned short, struct pt_regs *); -- cgit v1.2.3 From d546b67a940eb42a99f56b86c5cd8d47c8348c2a Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 25 Mar 2008 17:39:12 -0700 Subject: x86: fix performance drop for glx fix the 3D performance drop reported at: http://bugzilla.kernel.org/show_bug.cgi?id=10328 fb drivers are using ioremap()/ioremap_nocache(), followed by mtrr_add with WC attribute. Recent changes in page attribute code made both ioremap()/ioremap_nocache() mappings as UC (instead of previous UC-). This breaks the graphics performance, as the effective memory type is UC instead of expected WC. The correct way to fix this is to add ioremap_wc() (which uses UC- in the absence of PAT kernel support and WC with PAT) and change all the fb drivers to use this new ioremap_wc() API. We can take this correct and longer route for post 2.6.25. For now, revert back to the UC- behavior for ioremap/ioremap_nocache. Signed-off-by: Suresh Siddha Signed-off-by: Venkatesh Pallipadi Cc: Arjan van de Ven Signed-off-by: Ingo Molnar --- arch/x86/mm/ioremap.c | 6 +++++- arch/x86/mm/pageattr.c | 2 +- include/asm-x86/pgtable.h | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 4afaba0ed722..794895c6dcc9 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -137,7 +137,11 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size, switch (mode) { case IOR_MODE_UNCACHED: default: - prot = PAGE_KERNEL_NOCACHE; + /* + * FIXME: we will use UC MINUS for now, as video fb drivers + * depend on it. Upcoming ioremap_wc() will fix this behavior. + */ + prot = PAGE_KERNEL_UC_MINUS; break; case IOR_MODE_CACHED: prot = PAGE_KERNEL; diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 14e48b5a94ba..7b79f6be4e7d 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -771,7 +771,7 @@ static inline int change_page_attr_clear(unsigned long addr, int numpages, int set_memory_uc(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, - __pgprot(_PAGE_PCD | _PAGE_PWT)); + __pgprot(_PAGE_PCD)); } EXPORT_SYMBOL(set_memory_uc); diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 174b87738714..9cf472aeb9ce 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -85,6 +85,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC; #define __PAGE_KERNEL_RX (__PAGE_KERNEL_EXEC & ~_PAGE_RW) #define __PAGE_KERNEL_EXEC_NOCACHE (__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT) #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT) +#define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD) #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER) #define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT) #define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE) @@ -101,6 +102,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC; #define PAGE_KERNEL_EXEC MAKE_GLOBAL(__PAGE_KERNEL_EXEC) #define PAGE_KERNEL_RX MAKE_GLOBAL(__PAGE_KERNEL_RX) #define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE) +#define PAGE_KERNEL_UC_MINUS MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS) #define PAGE_KERNEL_EXEC_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE) #define PAGE_KERNEL_LARGE MAKE_GLOBAL(__PAGE_KERNEL_LARGE) #define PAGE_KERNEL_LARGE_EXEC MAKE_GLOBAL(__PAGE_KERNEL_LARGE_EXEC) -- cgit v1.2.3 From c101b088ba0ed16d7109b2f3c2d16798d162a535 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 26 Mar 2008 17:32:33 -0700 Subject: [SPARC64]: Define TASK_SIZE_OF() This make "cat /proc/${PID}/pagemap" more efficient for 32-bit tasks. Based upon a report by Mariusz Kozlowski. Signed-off-by: David S. Miller --- include/asm-sparc64/processor.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h index 8da484c19822..885b6a1dcae4 100644 --- a/include/asm-sparc64/processor.h +++ b/include/asm-sparc64/processor.h @@ -37,6 +37,9 @@ #endif #define TASK_SIZE ((unsigned long)-VPTE_SIZE) +#define TASK_SIZE_OF(tsk) \ + (test_tsk_thread_flag(tsk,TIF_32BIT) ? \ + (1UL << 32UL) : TASK_SIZE) #ifdef __KERNEL__ #define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE) -- cgit v1.2.3 From b2ef749720a97053d60605a7456772a1752164cc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 26 Mar 2008 22:39:15 +0100 Subject: rdc321x: GPIO routines bugfixes This patch fixes the use of GPIO routines which are in the PCI configuration space of the RDC321x, therefore reading/writing to this space without spinlock protection can be problematic. We also now request and free GPIOs and support the MGB100 board, previous code was very AR525W-centric. Signed-off-by: Volker Weiss Signed-off-by: Florian Fainelli Signed-off-by: Ingo Molnar --- arch/x86/mach-rdc321x/gpio.c | 199 +++++++++++++++++++++------- arch/x86/mach-rdc321x/platform.c | 2 + include/asm-x86/mach-rdc321x/gpio.h | 9 +- include/asm-x86/mach-rdc321x/rdc321x_defs.h | 8 +- 4 files changed, 165 insertions(+), 53 deletions(-) (limited to 'include') diff --git a/arch/x86/mach-rdc321x/gpio.c b/arch/x86/mach-rdc321x/gpio.c index 031269163bd6..247f33d3a407 100644 --- a/arch/x86/mach-rdc321x/gpio.c +++ b/arch/x86/mach-rdc321x/gpio.c @@ -1,91 +1,194 @@ /* - * Copyright (C) 2007, OpenWrt.org, Florian Fainelli - * RDC321x architecture specific GPIO support + * GPIO support for RDC SoC R3210/R8610 + * + * Copyright (C) 2007, Florian Fainelli + * Copyright (C) 2008, Volker Weiss + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * 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 -static inline int rdc_gpio_is_valid(unsigned gpio) + +/* spin lock to protect our private copy of GPIO data register plus + the access to PCI conf registers. */ +static DEFINE_SPINLOCK(gpio_lock); + +/* copy of GPIO data registers */ +static u32 gpio_data_reg1; +static u32 gpio_data_reg2; + +static u32 gpio_request_data[2]; + + +static inline void rdc321x_conf_write(unsigned addr, u32 value) { - return (gpio <= RDC_MAX_GPIO); + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + outl(value, RDC3210_CFGREG_DATA); } -static unsigned int rdc_gpio_read(unsigned gpio) +static inline void rdc321x_conf_or(unsigned addr, u32 value) { - unsigned int val; - - val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x84:0x48)); - outl(val, RDC3210_CFGREG_ADDR); - udelay(10); - val = inl(RDC3210_CFGREG_DATA); - val |= (0x1 << (gpio & 0x1F)); - outl(val, RDC3210_CFGREG_DATA); - udelay(10); - val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x88:0x4C)); - outl(val, RDC3210_CFGREG_ADDR); - udelay(10); - val = inl(RDC3210_CFGREG_DATA); - - return val; + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + value |= inl(RDC3210_CFGREG_DATA); + outl(value, RDC3210_CFGREG_DATA); } -static void rdc_gpio_write(unsigned int val) +static inline u32 rdc321x_conf_read(unsigned addr) { - if (val) { - outl(val, RDC3210_CFGREG_DATA); - udelay(10); - } + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + + return inl(RDC3210_CFGREG_DATA); } -int rdc_gpio_get_value(unsigned gpio) +/* configure pin as GPIO */ +static void rdc321x_configure_gpio(unsigned gpio) +{ + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + rdc321x_conf_or(gpio < 32 + ? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2, + 1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); +} + +/* initially setup the 2 copies of the gpio data registers. + This function must be called by the platform setup code. */ +void __init rdc321x_gpio_setup() +{ + /* this might not be, what others (BIOS, bootloader, etc.) + wrote to these registers before, but it's a good guess. Still + better than just using 0xffffffff. */ + + gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); + gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); +} + +/* determine, if gpio number is valid */ +static inline int rdc321x_is_gpio(unsigned gpio) +{ + return gpio <= RDC321X_MAX_GPIO; +} + +/* request GPIO */ +int rdc_gpio_request(unsigned gpio, const char *label) { - if (rdc_gpio_is_valid(gpio)) - return (int)rdc_gpio_read(gpio); - else + unsigned long flags; + + if (!rdc321x_is_gpio(gpio)) return -EINVAL; + + spin_lock_irqsave(&gpio_lock, flags); + if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f))) + goto inuse; + gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +inuse: + spin_unlock_irqrestore(&gpio_lock, flags); + return -EINVAL; } -EXPORT_SYMBOL(rdc_gpio_get_value); +EXPORT_SYMBOL(rdc_gpio_request); -void rdc_gpio_set_value(unsigned gpio, int value) +/* release previously-claimed GPIO */ +void rdc_gpio_free(unsigned gpio) { - unsigned int val; + unsigned long flags; - if (!rdc_gpio_is_valid(gpio)) + if (!rdc321x_is_gpio(gpio)) return; - val = rdc_gpio_read(gpio); + spin_lock_irqsave(&gpio_lock, flags); + gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(rdc_gpio_free); + +/* read GPIO pin */ +int rdc_gpio_get_value(unsigned gpio) +{ + u32 reg; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + reg = rdc321x_conf_read(gpio < 32 + ? RDC321X_GPIO_DATA_REG1 : RDC321X_GPIO_DATA_REG2); + spin_unlock_irqrestore(&gpio_lock, flags); - if (value) - val &= ~(0x1 << (gpio & 0x1F)); - else - val |= (0x1 << (gpio & 0x1F)); + return (1 << (gpio & 0x1f)) & reg ? 1 : 0; +} +EXPORT_SYMBOL(rdc_gpio_get_value); - rdc_gpio_write(val); +/* set GPIO pin to value */ +void rdc_gpio_set_value(unsigned gpio, int value) +{ + unsigned long flags; + u32 reg; + + reg = 1 << (gpio & 0x1f); + if (gpio < 32) { + spin_lock_irqsave(&gpio_lock, flags); + if (value) + gpio_data_reg1 |= reg; + else + gpio_data_reg1 &= ~reg; + rdc321x_conf_write(RDC321X_GPIO_DATA_REG1, gpio_data_reg1); + spin_unlock_irqrestore(&gpio_lock, flags); + } else { + spin_lock_irqsave(&gpio_lock, flags); + if (value) + gpio_data_reg2 |= reg; + else + gpio_data_reg2 &= ~reg; + rdc321x_conf_write(RDC321X_GPIO_DATA_REG2, gpio_data_reg2); + spin_unlock_irqrestore(&gpio_lock, flags); + } } EXPORT_SYMBOL(rdc_gpio_set_value); +/* configure GPIO pin as input */ int rdc_gpio_direction_input(unsigned gpio) { + if (!rdc321x_is_gpio(gpio)) + return -EINVAL; + + rdc321x_configure_gpio(gpio); + return 0; } EXPORT_SYMBOL(rdc_gpio_direction_input); +/* configure GPIO pin as output and set value */ int rdc_gpio_direction_output(unsigned gpio, int value) { + if (!rdc321x_is_gpio(gpio)) + return -EINVAL; + + gpio_set_value(gpio, value); + rdc321x_configure_gpio(gpio); + return 0; } EXPORT_SYMBOL(rdc_gpio_direction_output); - - diff --git a/arch/x86/mach-rdc321x/platform.c b/arch/x86/mach-rdc321x/platform.c index dda6024a5862..a037041817c7 100644 --- a/arch/x86/mach-rdc321x/platform.c +++ b/arch/x86/mach-rdc321x/platform.c @@ -62,6 +62,8 @@ static struct platform_device *rdc321x_devs[] = { static int __init rdc_board_setup(void) { + rdc321x_gpio_setup(); + return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs)); } diff --git a/include/asm-x86/mach-rdc321x/gpio.h b/include/asm-x86/mach-rdc321x/gpio.h index db31b929b990..acce0b7d397b 100644 --- a/include/asm-x86/mach-rdc321x/gpio.h +++ b/include/asm-x86/mach-rdc321x/gpio.h @@ -5,19 +5,20 @@ extern int rdc_gpio_get_value(unsigned gpio); extern void rdc_gpio_set_value(unsigned gpio, int value); extern int rdc_gpio_direction_input(unsigned gpio); extern int rdc_gpio_direction_output(unsigned gpio, int value); - +extern int rdc_gpio_request(unsigned gpio, const char *label); +extern void rdc_gpio_free(unsigned gpio); +extern void __init rdc321x_gpio_setup(void); /* Wrappers for the arch-neutral GPIO API */ static inline int gpio_request(unsigned gpio, const char *label) { - /* Not yet implemented */ - return 0; + return rdc_gpio_request(gpio, label); } static inline void gpio_free(unsigned gpio) { - /* Not yet implemented */ + rdc_gpio_free(gpio); } static inline int gpio_direction_input(unsigned gpio) diff --git a/include/asm-x86/mach-rdc321x/rdc321x_defs.h b/include/asm-x86/mach-rdc321x/rdc321x_defs.h index 838ba8f64fd3..c8e9c8bed3d0 100644 --- a/include/asm-x86/mach-rdc321x/rdc321x_defs.h +++ b/include/asm-x86/mach-rdc321x/rdc321x_defs.h @@ -3,4 +3,10 @@ /* General purpose configuration and data registers */ #define RDC3210_CFGREG_ADDR 0x0CF8 #define RDC3210_CFGREG_DATA 0x0CFC -#define RDC_MAX_GPIO 0x3A + +#define RDC321X_GPIO_CTRL_REG1 0x48 +#define RDC321X_GPIO_CTRL_REG2 0x84 +#define RDC321X_GPIO_DATA_REG1 0x4c +#define RDC321X_GPIO_DATA_REG2 0x88 + +#define RDC321X_MAX_GPIO 58 -- cgit v1.2.3 From a6bd8e13034dd7d60b6f14217096efa192d0adc1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 28 Mar 2008 11:05:53 -0500 Subject: lguest: comment documentation update. Took some cycles to re-read the Lguest Journey end-to-end, fix some rot and tighten some phrases. Only comments change. No new jokes, but a couple of recycled old jokes. Signed-off-by: Rusty Russell --- Documentation/lguest/lguest.c | 69 ++++++++++++---------- arch/x86/lguest/boot.c | 108 +++++++++++++++++++--------------- arch/x86/lguest/i386_head.S | 15 +++-- drivers/lguest/core.c | 18 +++--- drivers/lguest/hypercalls.c | 11 +++- drivers/lguest/interrupts_and_traps.c | 7 +-- drivers/lguest/lguest_device.c | 11 ++-- drivers/lguest/lguest_user.c | 30 +++++++--- drivers/lguest/page_tables.c | 32 +++++----- drivers/lguest/x86/core.c | 33 +++++++---- drivers/lguest/x86/switcher_32.S | 8 +-- include/asm-x86/lguest_hcall.h | 2 +- include/linux/lguest_launcher.h | 6 +- 13 files changed, 208 insertions(+), 142 deletions(-) (limited to 'include') diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index d45c7f682b1b..4c1fc65a8b3d 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c @@ -1,7 +1,7 @@ /*P:100 This is the Launcher code, a simple program which lays out the - * "physical" memory for the new Guest by mapping the kernel image and the - * virtual devices, then reads repeatedly from /dev/lguest to run the Guest. -:*/ + * "physical" memory for the new Guest by mapping the kernel image and + * the virtual devices, then opens /dev/lguest to tell the kernel + * about the Guest and control it. :*/ #define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include @@ -43,7 +43,7 @@ #include "linux/virtio_console.h" #include "linux/virtio_ring.h" #include "asm-x86/bootparam.h" -/*L:110 We can ignore the 38 include files we need for this program, but I do +/*L:110 We can ignore the 39 include files we need for this program, but I do * want to draw attention to the use of kernel-style types. * * As Linus said, "C is a Spartan language, and so should your naming be." I @@ -320,7 +320,7 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr) err(1, "Reading program headers"); /* Try all the headers: there are usually only three. A read-only one, - * a read-write one, and a "note" section which isn't loadable. */ + * a read-write one, and a "note" section which we don't load. */ for (i = 0; i < ehdr->e_phnum; i++) { /* If this isn't a loadable segment, we ignore it */ if (phdr[i].p_type != PT_LOAD) @@ -387,7 +387,7 @@ static unsigned long load_kernel(int fd) if (memcmp(hdr.e_ident, ELFMAG, SELFMAG) == 0) return map_elf(fd, &hdr); - /* Otherwise we assume it's a bzImage, and try to unpack it */ + /* Otherwise we assume it's a bzImage, and try to load it. */ return load_bzimage(fd); } @@ -433,12 +433,12 @@ static unsigned long load_initrd(const char *name, unsigned long mem) return len; } -/* Once we know how much memory we have, we can construct simple linear page +/* Once we know how much memory we have we can construct simple linear page * tables which set virtual == physical which will get the Guest far enough * into the boot to create its own. * * We lay them out of the way, just below the initrd (which is why we need to - * know its size). */ + * know its size here). */ static unsigned long setup_pagetables(unsigned long mem, unsigned long initrd_size) { @@ -850,7 +850,8 @@ static void handle_console_output(int fd, struct virtqueue *vq) * * Handling output for network is also simple: we get all the output buffers * and write them (ignoring the first element) to this device's file descriptor - * (stdout). */ + * (/dev/net/tun). + */ static void handle_net_output(int fd, struct virtqueue *vq) { unsigned int head, out, in; @@ -924,7 +925,7 @@ static void enable_fd(int fd, struct virtqueue *vq) write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd)); } -/* Resetting a device is fairly easy. */ +/* When the Guest asks us to reset a device, it's is fairly easy. */ static void reset_device(struct device *dev) { struct virtqueue *vq; @@ -1003,8 +1004,8 @@ static void handle_input(int fd) if (select(devices.max_infd+1, &fds, NULL, NULL, &poll) == 0) break; - /* Otherwise, call the device(s) which have readable - * file descriptors and a method of handling them. */ + /* Otherwise, call the device(s) which have readable file + * descriptors and a method of handling them. */ for (i = devices.dev; i; i = i->next) { if (i->handle_input && FD_ISSET(i->fd, &fds)) { int dev_fd; @@ -1015,8 +1016,7 @@ static void handle_input(int fd) * should no longer service it. Networking and * console do this when there's no input * buffers to deliver into. Console also uses - * it when it discovers that stdin is - * closed. */ + * it when it discovers that stdin is closed. */ FD_CLR(i->fd, &devices.infds); /* Tell waker to ignore it too, by sending a * negative fd number (-1, since 0 is a valid @@ -1033,7 +1033,8 @@ static void handle_input(int fd) * * All devices need a descriptor so the Guest knows it exists, and a "struct * device" so the Launcher can keep track of it. We have common helper - * routines to allocate and manage them. */ + * routines to allocate and manage them. + */ /* The layout of the device page is a "struct lguest_device_desc" followed by a * number of virtqueue descriptors, then two sets of feature bits, then an @@ -1078,7 +1079,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, struct virtqueue **i, *vq = malloc(sizeof(*vq)); void *p; - /* First we need some pages for this virtqueue. */ + /* First we need some memory for this virtqueue. */ pages = (vring_size(num_descs, getpagesize()) + getpagesize() - 1) / getpagesize(); p = get_pages(pages); @@ -1122,7 +1123,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, } /* The first half of the feature bitmask is for us to advertise features. The - * second half if for the Guest to accept features. */ + * second half is for the Guest to accept features. */ static void add_feature(struct device *dev, unsigned bit) { u8 *features = get_feature_bits(dev); @@ -1151,7 +1152,9 @@ static void set_config(struct device *dev, unsigned len, const void *conf) } /* This routine does all the creation and setup of a new device, including - * calling new_dev_desc() to allocate the descriptor and device memory. */ + * calling new_dev_desc() to allocate the descriptor and device memory. + * + * See what I mean about userspace being boring? */ static struct device *new_device(const char *name, u16 type, int fd, bool (*handle_input)(int, struct device *)) { @@ -1492,7 +1495,10 @@ static int io_thread(void *_dev) while (read(vblk->workpipe[0], &c, 1) == 1) { /* We acknowledge each request immediately to reduce latency, * rather than waiting until we've done them all. I haven't - * measured to see if it makes any difference. */ + * measured to see if it makes any difference. + * + * That would be an interesting test, wouldn't it? You could + * also try having more than one I/O thread. */ while (service_io(dev)) write(vblk->done_fd, &c, 1); } @@ -1500,7 +1506,7 @@ static int io_thread(void *_dev) } /* Now we've seen the I/O thread, we return to the Launcher to see what happens - * when the thread tells us it's completed some I/O. */ + * when that thread tells us it's completed some I/O. */ static bool handle_io_finish(int fd, struct device *dev) { char c; @@ -1572,11 +1578,12 @@ static void setup_block_file(const char *filename) * more work. */ pipe(vblk->workpipe); - /* Create stack for thread and run it */ + /* Create stack for thread and run it. Since stack grows upwards, we + * point the stack pointer to the end of this region. */ stack = malloc(32768); /* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from * becoming a zombie. */ - if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1) + if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1) err(1, "Creating clone"); /* We don't need to keep the I/O thread's end of the pipes open. */ @@ -1586,14 +1593,14 @@ static void setup_block_file(const char *filename) verbose("device %u: virtblock %llu sectors\n", devices.device_num, le64_to_cpu(conf.capacity)); } -/* That's the end of device setup. :*/ +/* That's the end of device setup. */ -/* Reboot */ +/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */ static void __attribute__((noreturn)) restart_guest(void) { unsigned int i; - /* Closing pipes causes the waker thread and io_threads to die, and + /* Closing pipes causes the Waker thread and io_threads to die, and * closing /dev/lguest cleans up the Guest. Since we don't track all * open fds, we simply close everything beyond stderr. */ for (i = 3; i < FD_SETSIZE; i++) @@ -1602,7 +1609,7 @@ static void __attribute__((noreturn)) restart_guest(void) err(1, "Could not exec %s", main_args[0]); } -/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves +/*L:220 Finally we reach the core of the Launcher which runs the Guest, serves * its input and output, and finally, lays it to rest. */ static void __attribute__((noreturn)) run_guest(int lguest_fd) { @@ -1643,7 +1650,7 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd) err(1, "Resetting break"); } } -/* +/*L:240 * This is the end of the Launcher. The good news: we are over halfway * through! The bad news: the most fiendish part of the code still lies ahead * of us. @@ -1690,8 +1697,8 @@ int main(int argc, char *argv[]) * device receive input from a file descriptor, we keep an fdset * (infds) and the maximum fd number (max_infd) with the head of the * list. We also keep a pointer to the last device. Finally, we keep - * the next interrupt number to hand out (1: remember that 0 is used by - * the timer). */ + * the next interrupt number to use for devices (1: remember that 0 is + * used by the timer). */ FD_ZERO(&devices.infds); devices.max_infd = -1; devices.lastdev = NULL; @@ -1792,8 +1799,8 @@ int main(int argc, char *argv[]) lguest_fd = tell_kernel(pgdir, start); /* We fork off a child process, which wakes the Launcher whenever one - * of the input file descriptors needs attention. Otherwise we would - * run the Guest until it tries to output something. */ + * of the input file descriptors needs attention. We call this the + * Waker, and we'll cover it in a moment. */ waker_fd = setup_waker(lguest_fd); /* Finally, run the Guest. This doesn't return. */ diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index a104c532ff70..3335b4595efd 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -10,21 +10,19 @@ * (such as the example in Documentation/lguest/lguest.c) is called the * Launcher. * - * Secondly, we only run specially modified Guests, not normal kernels. When - * you set CONFIG_LGUEST to 'y' or 'm', this automatically sets - * CONFIG_LGUEST_GUEST=y, which compiles this file into the kernel so it knows - * how to be a Guest. This means that you can use the same kernel you boot - * normally (ie. as a Host) as a Guest. + * Secondly, we only run specially modified Guests, not normal kernels: setting + * CONFIG_LGUEST_GUEST to "y" compiles this file into the kernel so it knows + * how to be a Guest at boot time. This means that you can use the same kernel + * you boot normally (ie. as a Host) as a Guest. * * These Guests know that they cannot do privileged operations, such as disable * interrupts, and that they have to ask the Host to do such things explicitly. * This file consists of all the replacements for such low-level native * hardware operations: these special Guest versions call the Host. * - * So how does the kernel know it's a Guest? The Guest starts at a special - * entry point marked with a magic string, which sets up a few things then - * calls here. We replace the native functions various "paravirt" structures - * with our Guest versions, then boot like normal. :*/ + * So how does the kernel know it's a Guest? We'll see that later, but let's + * just say that we end up here where we replace the native functions various + * "paravirt" structures with our Guest versions, then boot like normal. :*/ /* * Copyright (C) 2006, Rusty Russell IBM Corporation. @@ -134,7 +132,7 @@ static void async_hcall(unsigned long call, unsigned long arg1, * lguest_leave_lazy_mode(). * * So, when we're in lazy mode, we call async_hcall() to store the call for - * future processing. */ + * future processing: */ static void lazy_hcall(unsigned long call, unsigned long arg1, unsigned long arg2, @@ -147,7 +145,7 @@ static void lazy_hcall(unsigned long call, } /* When lazy mode is turned off reset the per-cpu lazy mode variable and then - * issue a hypercall to flush any stored calls. */ + * issue the do-nothing hypercall to flush any stored calls. */ static void lguest_leave_lazy_mode(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); @@ -164,7 +162,7 @@ static void lguest_leave_lazy_mode(void) * * So instead we keep an "irq_enabled" field inside our "struct lguest_data", * which the Guest can update with a single instruction. The Host knows to - * check there when it wants to deliver an interrupt. + * check there before it tries to deliver an interrupt. */ /* save_flags() is expected to return the processor state (ie. "flags"). The @@ -196,10 +194,15 @@ static void irq_enable(void) /*M:003 Note that we don't check for outstanding interrupts when we re-enable * them (or when we unmask an interrupt). This seems to work for the moment, * since interrupts are rare and we'll just get the interrupt on the next timer - * tick, but when we turn on CONFIG_NO_HZ, we should revisit this. One way + * tick, but now we can run with CONFIG_NO_HZ, we should revisit this. One way * would be to put the "irq_enabled" field in a page by itself, and have the * Host write-protect it when an interrupt comes in when irqs are disabled. - * There will then be a page fault as soon as interrupts are re-enabled. :*/ + * There will then be a page fault as soon as interrupts are re-enabled. + * + * A better method is to implement soft interrupt disable generally for x86: + * instead of disabling interrupts, we set a flag. If an interrupt does come + * in, we then disable them for real. This is uncommon, so we could simply use + * a hypercall for interrupt control and not worry about efficiency. :*/ /*G:034 * The Interrupt Descriptor Table (IDT). @@ -212,6 +215,10 @@ static void irq_enable(void) static void lguest_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g) { + /* The gate_desc structure is 8 bytes long: we hand it to the Host in + * two 32-bit chunks. The whole 32-bit kernel used to hand descriptors + * around like this; typesafety wasn't a big concern in Linux's early + * years. */ u32 *desc = (u32 *)g; /* Keep the local copy up to date. */ native_write_idt_entry(dt, entrynum, g); @@ -243,7 +250,8 @@ static void lguest_load_idt(const struct desc_ptr *desc) * * This is the opposite of the IDT code where we have a LOAD_IDT_ENTRY * hypercall and use that repeatedly to load a new IDT. I don't think it - * really matters, but wouldn't it be nice if they were the same? + * really matters, but wouldn't it be nice if they were the same? Wouldn't + * it be even better if you were the one to send the patch to fix it? */ static void lguest_load_gdt(const struct desc_ptr *desc) { @@ -298,9 +306,9 @@ static void lguest_load_tr_desc(void) /* The "cpuid" instruction is a way of querying both the CPU identity * (manufacturer, model, etc) and its features. It was introduced before the - * Pentium in 1993 and keeps getting extended by both Intel and AMD. As you - * might imagine, after a decade and a half this treatment, it is now a giant - * ball of hair. Its entry in the current Intel manual runs to 28 pages. + * Pentium in 1993 and keeps getting extended by both Intel, AMD and others. + * As you might imagine, after a decade and a half this treatment, it is now a + * giant ball of hair. Its entry in the current Intel manual runs to 28 pages. * * This instruction even it has its own Wikipedia entry. The Wikipedia entry * has been translated into 4 languages. I am not making this up! @@ -594,17 +602,17 @@ static unsigned long lguest_get_wallclock(void) return lguest_data.time.tv_sec; } -/* The TSC is a Time Stamp Counter. The Host tells us what speed it runs at, - * or 0 if it's unusable as a reliable clock source. This matches what we want - * here: if we return 0 from this function, the x86 TSC clock will not register - * itself. */ +/* The TSC is an Intel thing called the Time Stamp Counter. The Host tells us + * what speed it runs at, or 0 if it's unusable as a reliable clock source. + * This matches what we want here: if we return 0 from this function, the x86 + * TSC clock will give up and not register itself. */ static unsigned long lguest_cpu_khz(void) { return lguest_data.tsc_khz; } -/* If we can't use the TSC, the kernel falls back to our "lguest_clock", where - * we read the time value given to us by the Host. */ +/* If we can't use the TSC, the kernel falls back to our lower-priority + * "lguest_clock", where we read the time value given to us by the Host. */ static cycle_t lguest_clock_read(void) { unsigned long sec, nsec; @@ -648,12 +656,16 @@ static struct clocksource lguest_clock = { static int lguest_clockevent_set_next_event(unsigned long delta, struct clock_event_device *evt) { + /* FIXME: I don't think this can ever happen, but James tells me he had + * to put this code in. Maybe we should remove it now. Anyone? */ if (delta < LG_CLOCK_MIN_DELTA) { if (printk_ratelimit()) printk(KERN_DEBUG "%s: small delta %lu ns\n", __FUNCTION__, delta); return -ETIME; } + + /* Please wake us this far in the future. */ hcall(LHCALL_SET_CLOCKEVENT, delta, 0, 0); return 0; } @@ -738,7 +750,7 @@ static void lguest_time_init(void) * will not tolerate us trying to use that), the stack pointer, and the number * of pages in the stack. */ static void lguest_load_sp0(struct tss_struct *tss, - struct thread_struct *thread) + struct thread_struct *thread) { lazy_hcall(LHCALL_SET_STACK, __KERNEL_DS|0x1, thread->sp0, THREAD_SIZE/PAGE_SIZE); @@ -786,9 +798,8 @@ static void lguest_safe_halt(void) hcall(LHCALL_HALT, 0, 0, 0); } -/* Perhaps CRASH isn't the best name for this hypercall, but we use it to get a - * message out when we're crashing as well as elegant termination like powering - * off. +/* The SHUTDOWN hypercall takes a string to describe what's happening, and + * an argument which says whether this to restart (reboot) the Guest or not. * * Note that the Host always prefers that the Guest speak in physical addresses * rather than virtual addresses, so we use __pa() here. */ @@ -816,8 +827,9 @@ static struct notifier_block paniced = { /* Setting up memory is fairly easy. */ static __init char *lguest_memory_setup(void) { - /* We do this here and not earlier because lockcheck barfs if we do it - * before start_kernel() */ + /* We do this here and not earlier because lockcheck used to barf if we + * did it before start_kernel(). I think we fixed that, so it'd be + * nice to move it back to lguest_init. Patch welcome... */ atomic_notifier_chain_register(&panic_notifier_list, &paniced); /* The Linux bootloader header contains an "e820" memory map: the @@ -850,12 +862,19 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) return len; } +/* Rebooting also tells the Host we're finished, but the RESTART flag tells the + * Launcher to reboot us. */ +static void lguest_restart(char *reason) +{ + hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); +} + /*G:050 * Patching (Powerfully Placating Performance Pedants) * - * We have already seen that pv_ops structures let us replace simple - * native instructions with calls to the appropriate back end all throughout - * the kernel. This allows the same kernel to run as a Guest and as a native + * We have already seen that pv_ops structures let us replace simple native + * instructions with calls to the appropriate back end all throughout the + * kernel. This allows the same kernel to run as a Guest and as a native * kernel, but it's slow because of all the indirect branches. * * Remember that David Wheeler quote about "Any problem in computer science can @@ -908,14 +927,9 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf, return insn_len; } -static void lguest_restart(char *reason) -{ - hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); -} - -/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops - * structures in the kernel provide points for (almost) every routine we have - * to override to avoid privileged instructions. */ +/*G:030 Once we get to lguest_init(), we know we're a Guest. The various + * pv_ops structures in the kernel provide points for (almost) every routine we + * have to override to avoid privileged instructions. */ __init void lguest_init(void) { /* We're under lguest, paravirt is enabled, and we're running at @@ -1003,9 +1017,9 @@ __init void lguest_init(void) * the normal data segment to get through booting. */ asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory"); - /* The Host uses the top of the Guest's virtual address space for the - * Host<->Guest Switcher, and it tells us how big that is in - * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */ + /* The Host<->Guest Switcher lives at the top of our address space, and + * the Host told us how big it is when we made LGUEST_INIT hypercall: + * it put the answer in lguest_data.reserve_mem */ reserve_top_address(lguest_data.reserve_mem); /* If we don't initialize the lock dependency checker now, it crashes @@ -1027,6 +1041,7 @@ __init void lguest_init(void) /* Math is always hard! */ new_cpu_data.hard_math = 1; + /* We don't have features. We have puppies! Puppies! */ #ifdef CONFIG_X86_MCE mce_disabled = 1; #endif @@ -1044,10 +1059,11 @@ __init void lguest_init(void) virtio_cons_early_init(early_put_chars); /* Last of all, we set the power management poweroff hook to point to - * the Guest routine to power off. */ + * the Guest routine to power off, and the reboot hook to our restart + * routine. */ pm_power_off = lguest_power_off; - machine_ops.restart = lguest_restart; + /* Now we're set up, call start_kernel() in init/main.c and we proceed * to boot as normal. It never returns. */ start_kernel(); diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 95b6fbcded63..5c7cef34c9e7 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S @@ -5,13 +5,20 @@ #include #include -/*G:020 This is where we begin: head.S notes that the boot header's platform - * type field is "1" (lguest), so calls us here. +/*G:020 Our story starts with the kernel booting into startup_32 in + * arch/x86/kernel/head_32.S. It expects a boot header, which is created by + * the bootloader (the Launcher in our case). + * + * The startup_32 function does very little: it clears the uninitialized global + * C variables which we expect to be zero (ie. BSS) and then copies the boot + * header and kernel command line somewhere safe. Finally it checks the + * 'hardware_subarch' field. This was introduced in 2.6.24 for lguest and Xen: + * if it's set to '1' (lguest's assigned number), then it calls us here. * * WARNING: be very careful here! We're running at addresses equal to physical * addesses (around 0), not above PAGE_OFFSET as most code expectes * (eg. 0xC0000000). Jumps are relative, so they're OK, but we can't touch any - * data. + * data without remembering to subtract __PAGE_OFFSET! * * The .section line puts this code in .init.text so it will be discarded after * boot. */ @@ -24,7 +31,7 @@ ENTRY(lguest_entry) int $LGUEST_TRAP_ENTRY /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl - * instruction uses %esi implicitly as the source for the copy we' + * instruction uses %esi implicitly as the source for the copy we're * about to do. */ movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index c632c08cbbdc..5eea4356d703 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c @@ -1,8 +1,6 @@ /*P:400 This contains run_guest() which actually calls into the Host<->Guest * Switcher and analyzes the return, such as determining if the Guest wants the - * Host to do something. This file also contains useful helper routines, and a - * couple of non-obvious setup and teardown pieces which were implemented after - * days of debugging pain. :*/ + * Host to do something. This file also contains useful helper routines. :*/ #include #include #include @@ -49,8 +47,8 @@ static __init int map_switcher(void) * easy. */ - /* We allocate an array of "struct page"s. map_vm_area() wants the - * pages in this form, rather than just an array of pointers. */ + /* We allocate an array of struct page pointers. map_vm_area() wants + * this, rather than just an array of pages. */ switcher_page = kmalloc(sizeof(switcher_page[0])*TOTAL_SWITCHER_PAGES, GFP_KERNEL); if (!switcher_page) { @@ -172,7 +170,7 @@ void __lgread(struct lg_cpu *cpu, void *b, unsigned long addr, unsigned bytes) } } -/* This is the write (copy into guest) version. */ +/* This is the write (copy into Guest) version. */ void __lgwrite(struct lg_cpu *cpu, unsigned long addr, const void *b, unsigned bytes) { @@ -209,9 +207,9 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user) if (cpu->break_out) return -EAGAIN; - /* Check if there are any interrupts which can be delivered - * now: if so, this sets up the hander to be executed when we - * next run the Guest. */ + /* Check if there are any interrupts which can be delivered now: + * if so, this sets up the hander to be executed when we next + * run the Guest. */ maybe_do_interrupt(cpu); /* All long-lived kernel loops need to check with this horrible @@ -246,8 +244,10 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user) lguest_arch_handle_trap(cpu); } + /* Special case: Guest is 'dead' but wants a reboot. */ if (cpu->lg->dead == ERR_PTR(-ERESTART)) return -ERESTART; + /* The Guest is dead => "No such file or directory" */ return -ENOENT; } diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 0f2cb4fd7c69..54d66f05fefa 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -29,7 +29,7 @@ #include "lg.h" /*H:120 This is the core hypercall routine: where the Guest gets what it wants. - * Or gets killed. Or, in the case of LHCALL_CRASH, both. */ + * Or gets killed. Or, in the case of LHCALL_SHUTDOWN, both. */ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args) { switch (args->arg0) { @@ -190,6 +190,13 @@ static void initialize(struct lg_cpu *cpu) * pagetable. */ guest_pagetable_clear_all(cpu); } +/*:*/ + +/*M:013 If a Guest reads from a page (so creates a mapping) that it has never + * written to, and then the Launcher writes to it (ie. the output of a virtual + * device), the Guest will still see the old page. In practice, this never + * happens: why would the Guest read a page which it has never written to? But + * a similar scenario might one day bite us, so it's worth mentioning. :*/ /*H:100 * Hypercalls @@ -227,7 +234,7 @@ void do_hypercalls(struct lg_cpu *cpu) * However, if we are signalled or the Guest sends I/O to the * Launcher, the run_guest() loop will exit without running the * Guest. When it comes back it would try to re-run the - * hypercall. */ + * hypercall. Finding that bug sucked. */ cpu->hcall = NULL; } } diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 32e97c1858e5..0414ddf87587 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -144,7 +144,6 @@ void maybe_do_interrupt(struct lg_cpu *cpu) if (copy_from_user(&blk, cpu->lg->lguest_data->blocked_interrupts, sizeof(blk))) return; - bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS); /* Find the first interrupt. */ @@ -237,9 +236,9 @@ void free_interrupts(void) clear_bit(syscall_vector, used_vectors); } -/*H:220 Now we've got the routines to deliver interrupts, delivering traps - * like page fault is easy. The only trick is that Intel decided that some - * traps should have error codes: */ +/*H:220 Now we've got the routines to deliver interrupts, delivering traps like + * page fault is easy. The only trick is that Intel decided that some traps + * should have error codes: */ static int has_err(unsigned int trap) { return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17); diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 1b2ec0bf5eb1..2bc9bf7e88e5 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -1,10 +1,10 @@ /*P:050 Lguest guests use a very simple method to describe devices. It's a - * series of device descriptors contained just above the top of normal + * series of device descriptors contained just above the top of normal Guest * memory. * * We use the standard "virtio" device infrastructure, which provides us with a * console, a network and a block driver. Each one expects some configuration - * information and a "virtqueue" mechanism to send and receive data. :*/ + * information and a "virtqueue" or two to send and receive data. :*/ #include #include #include @@ -53,7 +53,7 @@ struct lguest_device { * Device configurations * * The configuration information for a device consists of one or more - * virtqueues, a feature bitmaks, and some configuration bytes. The + * virtqueues, a feature bitmap, and some configuration bytes. The * configuration bytes don't really matter to us: the Launcher sets them up, and * the driver will look at them during setup. * @@ -179,7 +179,7 @@ struct lguest_vq_info }; /* When the virtio_ring code wants to prod the Host, it calls us here and we - * make a hypercall. We hand the page number of the virtqueue so the Host + * make a hypercall. We hand the physical address of the virtqueue so the Host * knows which virtqueue we're talking about. */ static void lg_notify(struct virtqueue *vq) { @@ -199,7 +199,8 @@ static void lg_notify(struct virtqueue *vq) * allocate its own pages and tell the Host where they are, but for lguest it's * simpler for the Host to simply tell us where the pages are. * - * So we provide devices with a "find virtqueue and set it up" function. */ + * So we provide drivers with a "find the Nth virtqueue and set it up" + * function. */ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct virtqueue *vq)) diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 2221485b0773..564e425d71dd 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -73,7 +73,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) if (current != cpu->tsk) return -EPERM; - /* If the guest is already dead, we indicate why */ + /* If the Guest is already dead, we indicate why */ if (lg->dead) { size_t len; @@ -88,7 +88,7 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) return len; } - /* If we returned from read() last time because the Guest notified, + /* If we returned from read() last time because the Guest sent I/O, * clear the flag. */ if (cpu->pending_notify) cpu->pending_notify = 0; @@ -97,14 +97,20 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) return run_guest(cpu, (unsigned long __user *)user); } +/*L:025 This actually initializes a CPU. For the moment, a Guest is only + * uniprocessor, so "id" is always 0. */ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) { + /* We have a limited number the number of CPUs in the lguest struct. */ if (id >= NR_CPUS) return -EINVAL; + /* Set up this CPU's id, and pointer back to the lguest struct. */ cpu->id = id; cpu->lg = container_of((cpu - id), struct lguest, cpus[0]); cpu->lg->nr_cpus++; + + /* Each CPU has a timer it can set. */ init_clockdev(cpu); /* We need a complete page for the Guest registers: they are accessible @@ -120,11 +126,11 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) * address. */ lguest_arch_setup_regs(cpu, start_ip); - /* Initialize the queue for the waker to wait on */ + /* Initialize the queue for the Waker to wait on */ init_waitqueue_head(&cpu->break_wq); /* We keep a pointer to the Launcher task (ie. current task) for when - * other Guests want to wake this one (inter-Guest I/O). */ + * other Guests want to wake this one (eg. console input). */ cpu->tsk = current; /* We need to keep a pointer to the Launcher's memory map, because if @@ -136,6 +142,7 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) * when the same Guest runs on the same CPU twice. */ cpu->last_pages = NULL; + /* No error == success. */ return 0; } @@ -185,14 +192,13 @@ static int initialize(struct file *file, const unsigned long __user *input) lg->mem_base = (void __user *)(long)args[0]; lg->pfn_limit = args[1]; - /* This is the first cpu */ + /* This is the first cpu (cpu 0) and it will start booting at args[3] */ err = lg_cpu_start(&lg->cpus[0], 0, args[3]); if (err) goto release_guest; /* Initialize the Guest's shadow page tables, using the toplevel - * address the Launcher gave us. This allocates memory, so can - * fail. */ + * address the Launcher gave us. This allocates memory, so can fail. */ err = init_guest_pagetable(lg, args[2]); if (err) goto free_regs; @@ -218,11 +224,16 @@ unlock: /*L:010 The first operation the Launcher does must be a write. All writes * start with an unsigned long number: for the first write this must be * LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use - * writes of other values to send interrupts. */ + * writes of other values to send interrupts. + * + * Note that we overload the "offset" in the /dev/lguest file to indicate what + * CPU number we're dealing with. Currently this is always 0, since we only + * support uniprocessor Guests, but you can see the beginnings of SMP support + * here. */ static ssize_t write(struct file *file, const char __user *in, size_t size, loff_t *off) { - /* Once the guest is initialized, we hold the "struct lguest" in the + /* Once the Guest is initialized, we hold the "struct lguest" in the * file private data. */ struct lguest *lg = file->private_data; const unsigned long __user *input = (const unsigned long __user *)in; @@ -230,6 +241,7 @@ static ssize_t write(struct file *file, const char __user *in, struct lg_cpu *uninitialized_var(cpu); unsigned int cpu_id = *off; + /* The first value tells us what this request is. */ if (get_user(req, input) != 0) return -EFAULT; input++; diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index a7f64a9d67e0..d93500f24fbb 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -2,8 +2,8 @@ * previous encounters. It's functional, and as neat as it can be in the * circumstances, but be wary, for these things are subtle and break easily. * The Guest provides a virtual to physical mapping, but we can neither trust - * it nor use it: we verify and convert it here to point the hardware to the - * actual Guest pages when running the Guest. :*/ + * it nor use it: we verify and convert it here then point the CPU to the + * converted Guest pages when running the Guest. :*/ /* Copyright (C) Rusty Russell IBM Corporation 2006. * GPL v2 and any later version */ @@ -106,6 +106,11 @@ static unsigned long gpte_addr(pgd_t gpgd, unsigned long vaddr) BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT)); return gpage + ((vaddr>>PAGE_SHIFT) % PTRS_PER_PTE) * sizeof(pte_t); } +/*:*/ + +/*M:014 get_pfn is slow; it takes the mmap sem and calls get_user_pages. We + * could probably try to grab batches of pages here as an optimization + * (ie. pre-faulting). :*/ /*H:350 This routine takes a page number given by the Guest and converts it to * an actual, physical page number. It can fail for several reasons: the @@ -113,8 +118,8 @@ static unsigned long gpte_addr(pgd_t gpgd, unsigned long vaddr) * and the page is read-only, or the write flag was set and the page was * shared so had to be copied, but we ran out of memory. * - * This holds a reference to the page, so release_pte() is careful to - * put that back. */ + * This holds a reference to the page, so release_pte() is careful to put that + * back. */ static unsigned long get_pfn(unsigned long virtpfn, int write) { struct page *page; @@ -532,13 +537,13 @@ static void do_set_pte(struct lg_cpu *cpu, int idx, * all processes. So when the page table above that address changes, we update * all the page tables, not just the current one. This is rare. * - * The benefit is that when we have to track a new page table, we can copy keep - * all the kernel mappings. This speeds up context switch immensely. */ + * The benefit is that when we have to track a new page table, we can keep all + * the kernel mappings. This speeds up context switch immensely. */ void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir, unsigned long vaddr, pte_t gpte) { - /* Kernel mappings must be changed on all top levels. Slow, but - * doesn't happen often. */ + /* Kernel mappings must be changed on all top levels. Slow, but doesn't + * happen often. */ if (vaddr >= cpu->lg->kernel_address) { unsigned int i; for (i = 0; i < ARRAY_SIZE(cpu->lg->pgdirs); i++) @@ -704,12 +709,11 @@ static __init void populate_switcher_pte_page(unsigned int cpu, /* We've made it through the page table code. Perhaps our tired brains are * still processing the details, or perhaps we're simply glad it's over. * - * If nothing else, note that all this complexity in juggling shadow page - * tables in sync with the Guest's page tables is for one reason: for most - * Guests this page table dance determines how bad performance will be. This - * is why Xen uses exotic direct Guest pagetable manipulation, and why both - * Intel and AMD have implemented shadow page table support directly into - * hardware. + * If nothing else, note that all this complexity in juggling shadow page tables + * in sync with the Guest's page tables is for one reason: for most Guests this + * page table dance determines how bad performance will be. This is why Xen + * uses exotic direct Guest pagetable manipulation, and why both Intel and AMD + * have implemented shadow page table support directly into hardware. * * There is just one file remaining in the Host. */ diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 635187812d52..5126d5d9ea0e 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -17,6 +17,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/*P:450 This file contains the x86-specific lguest code. It used to be all + * mixed in with drivers/lguest/core.c but several foolhardy code slashers + * wrestled most of the dependencies out to here in preparation for porting + * lguest to other architectures (see what I mean by foolhardy?). + * + * This also contains a couple of non-obvious setup and teardown pieces which + * were implemented after days of debugging pain. :*/ #include #include #include @@ -157,6 +164,8 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) * also simplify copy_in_guest_info(). Note that we'd still need to restore * things when we exit to Launcher userspace, but that's fairly easy. * + * We could also try using this hooks for PGE, but that might be too expensive. + * * The hooks were designed for KVM, but we can also put them to good use. :*/ /*H:040 This is the i386-specific code to setup and run the Guest. Interrupts @@ -182,7 +191,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) * was doing. */ run_guest_once(cpu, lguest_pages(raw_smp_processor_id())); - /* Note that the "regs" pointer contains two extra entries which are + /* Note that the "regs" structure contains two extra entries which are * not really registers: a trap number which says what interrupt or * trap made the switcher code come back, and an error code which some * traps set. */ @@ -293,11 +302,10 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) break; case 14: /* We've intercepted a Page Fault. */ /* The Guest accessed a virtual address that wasn't mapped. - * This happens a lot: we don't actually set up most of the - * page tables for the Guest at all when we start: as it runs - * it asks for more and more, and we set them up as - * required. In this case, we don't even tell the Guest that - * the fault happened. + * This happens a lot: we don't actually set up most of the page + * tables for the Guest at all when we start: as it runs it asks + * for more and more, and we set them up as required. In this + * case, we don't even tell the Guest that the fault happened. * * The errcode tells whether this was a read or a write, and * whether kernel or userspace code. */ @@ -342,7 +350,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) if (!deliver_trap(cpu, cpu->regs->trapnum)) /* If the Guest doesn't have a handler (either it hasn't * registered any yet, or it's one of the faults we don't let - * it handle), it dies with a cryptic error message. */ + * it handle), it dies with this cryptic error message. */ kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)", cpu->regs->trapnum, cpu->regs->eip, cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault @@ -375,8 +383,8 @@ void __init lguest_arch_host_init(void) * The only exception is the interrupt handlers in switcher.S: their * addresses are placed in a table (default_idt_entries), so we need to * update the table with the new addresses. switcher_offset() is a - * convenience function which returns the distance between the builtin - * switcher code and the high-mapped copy we just made. */ + * convenience function which returns the distance between the + * compiled-in switcher code and the high-mapped copy we just made. */ for (i = 0; i < IDT_ENTRIES; i++) default_idt_entries[i] += switcher_offset(); @@ -416,7 +424,7 @@ void __init lguest_arch_host_init(void) state->guest_gdt_desc.address = (long)&state->guest_gdt; /* We know where we want the stack to be when the Guest enters - * the switcher: in pages->regs. The stack grows upwards, so + * the Switcher: in pages->regs. The stack grows upwards, so * we start it at the end of that structure. */ state->guest_tss.sp0 = (long)(&pages->regs + 1); /* And this is the GDT entry to use for the stack: we keep a @@ -513,8 +521,8 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu) { u32 tsc_speed; - /* The pointer to the Guest's "struct lguest_data" is the only - * argument. We check that address now. */ + /* The pointer to the Guest's "struct lguest_data" is the only argument. + * We check that address now. */ if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1, sizeof(*cpu->lg->lguest_data))) return -EFAULT; @@ -546,6 +554,7 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu) return 0; } +/*:*/ /*L:030 lguest_arch_setup_regs() * diff --git a/drivers/lguest/x86/switcher_32.S b/drivers/lguest/x86/switcher_32.S index 0af8baaa0d4a..3fc15318a80f 100644 --- a/drivers/lguest/x86/switcher_32.S +++ b/drivers/lguest/x86/switcher_32.S @@ -1,6 +1,6 @@ -/*P:900 This is the Switcher: code which sits at 0xFFC00000 to do the low-level - * Guest<->Host switch. It is as simple as it can be made, but it's naturally - * very specific to x86. +/*P:900 This is the Switcher: code which sits at 0xFFC00000 astride both the + * Host and Guest to do the low-level Guest<->Host switch. It is as simple as + * it can be made, but it's naturally very specific to x86. * * You have now completed Preparation. If this has whet your appetite; if you * are feeling invigorated and refreshed then the next, more challenging stage @@ -189,7 +189,7 @@ ENTRY(switch_to_guest) // Interrupts are turned back on: we are Guest. iret -// We treat two paths to switch back to the Host +// We tread two paths to switch back to the Host // Yet both must save Guest state and restore Host // So we put the routine in a macro. #define SWITCH_TO_HOST \ diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h index 758b9a5d4539..f239e7069cab 100644 --- a/include/asm-x86/lguest_hcall.h +++ b/include/asm-x86/lguest_hcall.h @@ -27,7 +27,7 @@ #ifndef __ASSEMBLY__ #include -/*G:031 First, how does our Guest contact the Host to ask for privileged +/*G:031 But first, how does our Guest contact the Host to ask for privileged * operations? There are two ways: the direct way is to make a "hypercall", * to make requests of the Host Itself. * diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h index 589be3e1f3ac..e7217dc58f39 100644 --- a/include/linux/lguest_launcher.h +++ b/include/linux/lguest_launcher.h @@ -16,6 +16,10 @@ * a new device, we simply need to write a new virtio driver and create support * for it in the Launcher: this code won't need to change. * + * Virtio devices are also used by kvm, so we can simply reuse their optimized + * device drivers. And one day when everyone uses virtio, my plan will be + * complete. Bwahahahah! + * * Devices are described by a simplified ID, a status byte, and some "config" * bytes which describe this device's configuration. This is placed by the * Launcher just above the top of physical memory: @@ -26,7 +30,7 @@ struct lguest_device_desc { /* The number of virtqueues (first in config array) */ __u8 num_vq; /* The number of bytes of feature bits. Multiply by 2: one for host - * features and one for guest acknowledgements. */ + * features and one for Guest acknowledgements. */ __u8 feature_len; /* The number of bytes of the config array after virtqueues. */ __u8 config_len; -- cgit v1.2.3 From 7c4b93d8269b9d35971a8239426b1f6ddc3d5ef7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 21 Mar 2008 23:59:49 -0400 Subject: [PATCH] count ghost references to vfsmounts make propagate_mount_busy() exclude references from the vfsmounts that had been isolated by umount_tree() and are just waiting for release_mounts() to dispose of their ->mnt_parent/->mnt_mountpoint. Signed-off-by: Al Viro --- fs/namespace.c | 5 ++++- fs/pnode.c | 2 +- include/linux/mount.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/fs/namespace.c b/fs/namespace.c index 6324dfc80dc6..c175218ebae1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -548,6 +548,7 @@ void release_mounts(struct list_head *head) m = mnt->mnt_parent; mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; + m->mnt_ghosts--; spin_unlock(&vfsmount_lock); dput(dentry); mntput(m); @@ -572,8 +573,10 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) __touch_mnt_namespace(p->mnt_ns); p->mnt_ns = NULL; list_del_init(&p->mnt_child); - if (p->mnt_parent != p) + if (p->mnt_parent != p) { + p->mnt_parent->mnt_ghosts++; p->mnt_mountpoint->d_mounted--; + } change_mnt_propagation(p, MS_PRIVATE); } } diff --git a/fs/pnode.c b/fs/pnode.c index 05ba692bc540..1d8f5447f3f7 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -225,7 +225,7 @@ out: */ static inline int do_refcount_check(struct vfsmount *mnt, int count) { - int mycount = atomic_read(&mnt->mnt_count); + int mycount = atomic_read(&mnt->mnt_count) - mnt->mnt_ghosts; return (mycount > count); } diff --git a/include/linux/mount.h b/include/linux/mount.h index 6d3047d8c91c..dac5e67ff3ee 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -61,6 +61,7 @@ struct vfsmount { atomic_t mnt_count; int mnt_expiry_mark; /* true if marked for expiry */ int mnt_pinned; + int mnt_ghosts; }; static inline struct vfsmount *mntget(struct vfsmount *mnt) -- cgit v1.2.3 From c35038becad0adb0e25261fff66d85b1a6ddd0c2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Mar 2008 00:46:23 -0400 Subject: [PATCH] do shrink_submounts() for all fs types ... and take it out of ->umount_begin() instances. Call with all locks already taken (by do_umount()) and leave calling release_mounts() to caller (it will do release_mounts() anyway, so we can just put into the same list). Signed-off-by: Al Viro --- fs/afs/internal.h | 1 - fs/afs/mntpt.c | 8 -------- fs/afs/super.c | 1 - fs/cifs/cifs_dfs_ref.c | 1 - fs/namespace.c | 23 ++++++++++------------- fs/nfs/super.c | 2 -- include/linux/mount.h | 1 - 7 files changed, 10 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 5ca3625cd39e..9ba16edc0af2 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -573,7 +573,6 @@ extern const struct file_operations afs_mntpt_file_operations; extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); extern void afs_mntpt_kill_timer(void); -extern void afs_umount_begin(struct vfsmount *, int); /* * proc.c diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index a3510b8ba3e7..2f5503902c37 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -283,11 +283,3 @@ void afs_mntpt_kill_timer(void) cancel_delayed_work(&afs_mntpt_expiry_timer); flush_scheduled_work(); } - -/* - * begin unmount by attempting to remove all automounted mountpoints we added - */ -void afs_umount_begin(struct vfsmount *vfsmnt, int flags) -{ - shrink_submounts(vfsmnt, &afs_vfsmounts); -} diff --git a/fs/afs/super.c b/fs/afs/super.c index 36bbce45f44b..4b572b801d8d 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = { .write_inode = afs_write_inode, .destroy_inode = afs_destroy_inode, .clear_inode = afs_clear_inode, - .umount_begin = afs_umount_begin, .put_super = afs_put_super, .show_options = generic_show_options, }; diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index a1a95b027136..56c924033b78 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -33,7 +33,6 @@ void dfs_shrink_umount_helper(struct vfsmount *vfsmnt) { mark_mounts_for_expiry(&cifs_dfs_automount_list); mark_mounts_for_expiry(&cifs_dfs_automount_list); - shrink_submounts(vfsmnt, &cifs_dfs_automount_list); } /** diff --git a/fs/namespace.c b/fs/namespace.c index 1c78917ec930..7bd74b25930c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -581,6 +581,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) } } +static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts); + static int do_umount(struct vfsmount *mnt, int flags) { struct super_block *sb = mnt->mnt_sb; @@ -653,6 +655,9 @@ static int do_umount(struct vfsmount *mnt, int flags) spin_lock(&vfsmount_lock); event++; + if (!(flags & MNT_DETACH)) + shrink_submounts(mnt, &umount_list); + retval = -EBUSY; if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { if (!list_empty(&mnt->mnt_list)) @@ -1302,30 +1307,22 @@ resume: * process a list of expirable mountpoints with the intent of discarding any * submounts of a specific parent mountpoint */ -void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts) +static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts) { LIST_HEAD(graveyard); - LIST_HEAD(umounts); - struct vfsmount *mnt; + struct vfsmount *m; - down_write(&namespace_sem); - spin_lock(&vfsmount_lock); /* extract submounts of 'mountpoint' from the expiration list */ - while (select_submounts(mountpoint, &graveyard)) { + while (select_submounts(mnt, &graveyard)) { while (!list_empty(&graveyard)) { - mnt = list_first_entry(&graveyard, struct vfsmount, + m = list_first_entry(&graveyard, struct vfsmount, mnt_expire); touch_mnt_namespace(mnt->mnt_ns); - umount_tree(mnt, 1, &umounts); + umount_tree(mnt, 1, umounts); } } - spin_unlock(&vfsmount_lock); - up_write(&namespace_sem); - release_mounts(&umounts); } -EXPORT_SYMBOL_GPL(shrink_submounts); - /* * Some copy_from_user() implementations do not return the exact number of * bytes remaining to copy on a fault. But copy_mount_options() requires that. diff --git a/fs/nfs/super.c b/fs/nfs/super.c index dd4dfcd632ec..f9219024f31a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -589,8 +589,6 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); struct rpc_clnt *rpc; - shrink_submounts(vfsmnt, &nfs_automount_list); - if (!(flags & MNT_FORCE)) return; /* -EIO all pending I/O */ diff --git a/include/linux/mount.h b/include/linux/mount.h index dac5e67ff3ee..5ee2df217cdf 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -99,7 +99,6 @@ extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, int mnt_flags, struct list_head *fslist); extern void mark_mounts_for_expiry(struct list_head *mounts); -extern void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts); extern spinlock_t vfsmount_lock; extern dev_t name_to_dev_t(char *name); -- cgit v1.2.3 From 8c703d35fa91911dd92a18c31a718853f483ad80 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 28 Mar 2008 14:15:49 -0700 Subject: in_atomic(): document why it is unsuitable for general use Discourage people from inappropriately using in_atomic() Signed-off-by: Jonathan Corbet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hardirq.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 49829988bfa0..897f723bd222 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -72,6 +72,13 @@ #define in_softirq() (softirq_count()) #define in_interrupt() (irq_count()) +/* + * Are we running in atomic context? WARNING: this macro cannot + * always detect atomic context; in particular, it cannot know about + * held spinlocks in non-preemptible kernels. Thus it should not be + * used in the general case to determine whether sleeping is possible. + * Do not use in_atomic() in driver code. + */ #define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != 0) #ifdef CONFIG_PREEMPT -- cgit v1.2.3 From 3afe3925987adc3fc052abe404e44520c2072fc8 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Fri, 28 Mar 2008 14:16:01 -0700 Subject: kernel: add bit rotation helpers for 16 and 8 bit Will replace open-coded variants elsewhere. Done in the same style as the 32-bit versions. Signed-off-by: Harvey Harrison Acked-by: Randy Dunlap Cc: Johannes Berg Cc: John W. Linville Cc: Joe Perches Cc: Jiri Benc Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/bitops.h | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'include') diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 69c1edb9fe54..40d54731de7e 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -65,6 +65,46 @@ static inline __u32 ror32(__u32 word, unsigned int shift) return (word >> shift) | (word << (32 - shift)); } +/** + * rol16 - rotate a 16-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u16 rol16(__u16 word, unsigned int shift) +{ + return (word << shift) | (word >> (16 - shift)); +} + +/** + * ror16 - rotate a 16-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u16 ror16(__u16 word, unsigned int shift) +{ + return (word >> shift) | (word << (16 - shift)); +} + +/** + * rol8 - rotate an 8-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u8 rol8(__u8 word, unsigned int shift) +{ + return (word << shift) | (word >> (8 - shift)); +} + +/** + * ror8 - rotate an 8-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u8 ror8(__u8 word, unsigned int shift) +{ + return (word >> shift) | (word << (8 - shift)); +} + static inline unsigned fls_long(unsigned long l) { if (sizeof(l) == 4) -- cgit v1.2.3 From 5ac7ec85bcc70ef605657fb2d1106d27ab3bd131 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 28 Mar 2008 14:16:03 -0700 Subject: ext3: don't export ext3_fs.h and jbd.h Neither of the headers actually compiles when included from userpsace nor should it be made available as userspace tools should be using the libraries or at least headers from e2fsprogs. Signed-off-by: Christoph Hellwig Acked-by: "Theodore Ts'o" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/Kbuild | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 4108b38ebb16..4a446a19295e 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -195,7 +195,6 @@ unifdef-y += ethtool.h unifdef-y += eventpoll.h unifdef-y += signalfd.h unifdef-y += ext2_fs.h -unifdef-y += ext3_fs.h unifdef-y += fb.h unifdef-y += fcntl.h unifdef-y += filter.h @@ -248,7 +247,6 @@ unifdef-y += isdn.h unifdef-y += isdnif.h unifdef-y += isdn_divertif.h unifdef-y += isdn_ppp.h -unifdef-y += jbd.h unifdef-y += joystick.h unifdef-y += kdev_t.h unifdef-y += kd.h -- cgit v1.2.3 From 3ec25ebd69dc120d0590e64caaf1477aa88c8a93 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 27 Mar 2008 18:37:14 +0900 Subject: libata: ATA_EHI_LPM should be ATA_EH_LPM EH actions are ATA_EH_* not ATA_EHI_*. Rename ATA_EHI_LPM to ATA_EH_LPM. Signed-off-by: Tejun Heo Cc: Kristen Carlson Accardi Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-eh.c | 2 +- include/linux/libata.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c4248b37ff64..48519887f94a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -972,7 +972,7 @@ static void ata_dev_disable_pm(struct ata_device *dev) void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy) { ap->pm_policy = policy; - ap->link.eh_info.action |= ATA_EHI_LPM; + ap->link.eh_info.action |= ATA_EH_LPM; ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY; ata_port_schedule_eh(ap); } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 681252fd8143..a5830329eda4 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2748,7 +2748,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->i.flags &= ~ATA_EHI_SETMODE; } - if (ehc->i.action & ATA_EHI_LPM) + if (ehc->i.action & ATA_EH_LPM) ata_link_for_each_dev(dev, link) ata_dev_enable_pm(dev, ap->pm_policy); diff --git a/include/linux/libata.h b/include/linux/libata.h index 269cdba09578..b064bfeb69ee 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -295,6 +295,7 @@ enum { ATA_EH_SOFTRESET = (1 << 1), ATA_EH_HARDRESET = (1 << 2), ATA_EH_ENABLE_LINK = (1 << 3), + ATA_EH_LPM = (1 << 4), /* link power management action */ ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, @@ -304,7 +305,6 @@ enum { ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ ATA_EHI_QUIET = (1 << 3), /* be quiet */ - ATA_EHI_LPM = (1 << 4), /* link power management action */ ATA_EHI_DID_SOFTRESET = (1 << 16), /* already soft-reset this port */ ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */ -- cgit v1.2.3 From 729d4de96a5c090e40a918a41f63b7fb1b27c240 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sat, 29 Mar 2008 19:55:17 +0100 Subject: ide: fix defining SUPPORT_VLB_SYNC We need to check for CONFIG_{CRIS,FRV} not {CRIS,FRV}. Signed-off-by: Bartlomiej Zolnierkiewicz --- include/linux/ide.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/ide.h b/include/linux/ide.h index a3b69c10d667..bc26b2f27359 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -26,7 +26,7 @@ #include #include -#if defined(CRIS) || defined(FRV) +#if defined(CONFIG_CRIS) || defined(CONFIG_FRV) # define SUPPORT_VLB_SYNC 0 #else # define SUPPORT_VLB_SYNC 1 -- cgit v1.2.3 From 7c43f2b888f9ca1fcb7b07abc4cbff4ca1b8e03b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 29 Mar 2008 03:08:18 +0000 Subject: NULL noise: frv cmpxchg() Signed-off-by: Al Viro Acked-by: Harvey Harrison Signed-off-by: Linus Torvalds --- include/asm-frv/system.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h index b400cea81487..2c57f4734746 100644 --- a/include/asm-frv/system.h +++ b/include/asm-frv/system.h @@ -234,7 +234,7 @@ extern void free_initmem(void); break; \ \ default: \ - __xg_orig = 0; \ + __xg_orig = (__typeof__(__xg_orig))0; \ asm volatile("break"); \ break; \ } \ @@ -259,7 +259,7 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new); (__force uint32_t)__xg_test, \ (__force uint32_t)__xg_new); break; \ default: \ - __xg_orig = 0; \ + __xg_orig = (__typeof__(__xg_orig))0; \ asm volatile("break"); \ break; \ } \ -- cgit v1.2.3 From 7d61c4596d11d624efb4bbcbad01f9cf2b321162 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 29 Mar 2008 03:09:28 +0000 Subject: compat_sys_wait4() prototype misannotation Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- include/linux/compat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/compat.h b/include/linux/compat.h index a671dbff7a1f..8fa7857e153b 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -192,8 +192,8 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, struct compat_timeval __user *tvp); asmlinkage long compat_sys_wait4(compat_pid_t pid, - compat_uint_t *stat_addr, int options, - struct compat_rusage *ru); + compat_uint_t __user *stat_addr, int options, + struct compat_rusage __user *ru); #define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t)) -- cgit v1.2.3 From b2ddb9019ea13fb7b62d8e45adcc468376af0de7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 29 Mar 2008 03:09:38 +0000 Subject: dma_page_list ->base_address is a userland pointer Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- include/linux/dmaengine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 261e43a4c873..34d440698293 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -423,7 +423,7 @@ void dma_async_device_unregister(struct dma_device *device); /* --- Helper iov-locking functions --- */ struct dma_page_list { - char *base_address; + char __user *base_address; int nr_pages; struct page **pages; }; -- cgit v1.2.3 From 7d7f7c3ed2c519a462a4ae989ad3d55cc7f7f6ec Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 31 Mar 2008 01:53:43 +0300 Subject: remove include/asm-sh/floppy.h This patch removes the unused include/asm-sh/floppy.h (ARCH_MAY_HAVE_PC_FDC was not enabled). Signed-off-by: Adrian Bunk Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 3 - include/asm-sh/floppy.h | 268 ------------------------------------------------ 2 files changed, 271 deletions(-) delete mode 100644 include/asm-sh/floppy.h (limited to 'include') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 12720489e458..8d2cd1de5726 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -72,9 +72,6 @@ config SYS_SUPPORTS_NUMA config SYS_SUPPORTS_PCI bool -config ARCH_MAY_HAVE_PC_FDC - bool - config STACKTRACE_SUPPORT def_bool y diff --git a/include/asm-sh/floppy.h b/include/asm-sh/floppy.h deleted file mode 100644 index 59fbfdc90dfb..000000000000 --- a/include/asm-sh/floppy.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Architecture specific parts of the Floppy driver - * include/asm-i386/floppy.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) 1995 - */ -#ifndef __ASM_SH_FLOPPY_H -#define __ASM_SH_FLOPPY_H - -#include - - -/* - * The DMA channel used by the floppy controller cannot access data at - * addresses >= 16MB - * - * Went back to the 1MB limit, as some people had problems with the floppy - * driver otherwise. It doesn't matter much for performance anyway, as most - * floppy accesses go through the track buffer. - */ -#define _CROSS_64KB(a,s,vdma) \ -(!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) - -#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1) - - -#define SW fd_routine[use_virtual_dma&1] -#define CSW fd_routine[can_use_virtual_dma & 1] - - -#define fd_inb(port) inb_p(port) -#define fd_outb(value,port) outb_p(value,port) - -#define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy") -#define fd_free_dma() CSW._free_dma(FLOPPY_DMA) -#define fd_enable_irq() enable_irq(FLOPPY_IRQ) -#define fd_disable_irq() disable_irq(FLOPPY_IRQ) -#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) -#define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA) -#define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size) -#define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io) - -#define FLOPPY_CAN_FALLBACK_ON_NODMA - -static int virtual_dma_count; -static int virtual_dma_residue; -static char *virtual_dma_addr; -static int virtual_dma_mode; -static int doing_pdma; - -static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) -{ - register unsigned char st; - -#undef TRACE_FLPY_INT - -#ifdef TRACE_FLPY_INT - static int calls=0; - static int bytes=0; - static int dma_wait=0; -#endif - if(!doing_pdma) { - floppy_interrupt(irq, dev_id, regs); - return; - } - -#ifdef TRACE_FLPY_INT - if(!calls) - bytes = virtual_dma_count; -#endif - - { - register int lcount; - register char *lptr; - - st = 1; - for(lcount=virtual_dma_count, lptr=virtual_dma_addr; - lcount; lcount--, lptr++) { - st=inb(virtual_dma_port+4) & 0xa0 ; - if(st != 0xa0) - break; - if(virtual_dma_mode) - outb_p(*lptr, virtual_dma_port+5); - else - *lptr = inb_p(virtual_dma_port+5); - } - virtual_dma_count = lcount; - virtual_dma_addr = lptr; - st = inb(virtual_dma_port+4); - } - -#ifdef TRACE_FLPY_INT - calls++; -#endif - if(st == 0x20) - return; - if(!(st & 0x20)) { - virtual_dma_residue += virtual_dma_count; - virtual_dma_count=0; -#ifdef TRACE_FLPY_INT - printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", - virtual_dma_count, virtual_dma_residue, calls, bytes, - dma_wait); - calls = 0; - dma_wait=0; -#endif - doing_pdma = 0; - floppy_interrupt(irq, dev_id, regs); - return; - } -#ifdef TRACE_FLPY_INT - if(!virtual_dma_count) - dma_wait++; -#endif -} - -static void fd_disable_dma(void) -{ - if(! (can_use_virtual_dma & 1)) - disable_dma(FLOPPY_DMA); - doing_pdma = 0; - virtual_dma_residue += virtual_dma_count; - virtual_dma_count=0; -} - -static int vdma_request_dma(unsigned int dmanr, const char * device_id) -{ - return 0; -} - -static void vdma_nop(unsigned int dummy) -{ -} - - -static int vdma_get_dma_residue(unsigned int dummy) -{ - return virtual_dma_count + virtual_dma_residue; -} - - -static int fd_request_irq(void) -{ - if(can_use_virtual_dma) - return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", NULL); - else - return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); -} - -static unsigned long dma_mem_alloc(unsigned long size) -{ - return __get_dma_pages(GFP_KERNEL,get_order(size)); -} - - -static unsigned long vdma_mem_alloc(unsigned long size) -{ - return (unsigned long) vmalloc(size); - -} - -#define nodma_mem_alloc(size) vdma_mem_alloc(size) - -static void _fd_dma_mem_free(unsigned long addr, unsigned long size) -{ - if((unsigned int) addr >= (unsigned int) high_memory) - return vfree((void *)addr); - else - free_pages(addr, get_order(size)); -} - -#define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size) - -static void _fd_chose_dma_mode(char *addr, unsigned long size) -{ - if(can_use_virtual_dma == 2) { - if((unsigned int) addr >= (unsigned int) high_memory || - virt_to_phys(addr) >= 0x10000000) - use_virtual_dma = 1; - else - use_virtual_dma = 0; - } else { - use_virtual_dma = can_use_virtual_dma & 1; - } -} - -#define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size) - - -static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) -{ - doing_pdma = 1; - virtual_dma_port = io; - virtual_dma_mode = (mode == DMA_MODE_WRITE); - virtual_dma_addr = addr; - virtual_dma_count = size; - virtual_dma_residue = 0; - return 0; -} - -static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) -{ -#ifdef FLOPPY_SANITY_CHECK - if (CROSS_64KB(addr, size)) { - printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size); - return -1; - } -#endif - - __flush_purge_region(addr, size); - - /* actual, physical DMA */ - doing_pdma = 0; - clear_dma_ff(FLOPPY_DMA); - set_dma_mode(FLOPPY_DMA,mode); - set_dma_addr(FLOPPY_DMA,virt_to_phys(addr)); - set_dma_count(FLOPPY_DMA,size); - enable_dma(FLOPPY_DMA); - return 0; -} - -static struct fd_routine_l { - int (*_request_dma)(unsigned int dmanr, const char * device_id); - void (*_free_dma)(unsigned int dmanr); - int (*_get_dma_residue)(unsigned int dummy); - unsigned long (*_dma_mem_alloc) (unsigned long size); - int (*_dma_setup)(char *addr, unsigned long size, int mode, int io); -} fd_routine[] = { - { - request_dma, - free_dma, - get_dma_residue, - dma_mem_alloc, - hard_dma_setup - }, - { - vdma_request_dma, - vdma_nop, - vdma_get_dma_residue, - vdma_mem_alloc, - vdma_dma_setup - } -}; - - -static int FDC1 = 0x3f0; -static int FDC2 = -1; - -/* - * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock - * is needed to prevent corrupted CMOS RAM in case "insmod floppy" - * coincides with another rtc CMOS user. Paul G. - */ -#define FLOPPY0_TYPE (4) -#define FLOPPY1_TYPE (0) - -#define N_FDC 2 -#define N_DRIVE 8 - -#define EXTRA_FLOPPY_PARAMS - -#endif /* __ASM_SH_FLOPPY_H */ -- cgit v1.2.3 From a7097ff89c3204737a07eecbc83f9ae6002cc534 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 1 Apr 2008 00:22:53 -0400 Subject: Input: make sure input interfaces pin parent input devices Recent driver core change causes references to parent devices being dropped early, at device_del() time, as opposed to when all children are freed. This causes oops in evdev with grabbed devices. Take the reference to the parent input device ourselves to ensure that it stays around long enough. Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 6 ++---- drivers/input/joydev.c | 3 ++- drivers/input/mousedev.c | 3 ++- include/linux/input.h | 5 +++-- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 99562cee827e..b32984bc516f 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -124,6 +124,7 @@ static void evdev_free(struct device *dev) { struct evdev *evdev = container_of(dev, struct evdev, dev); + input_put_device(evdev->handle.dev); kfree(evdev); } @@ -853,9 +854,6 @@ static void evdev_cleanup(struct evdev *evdev) evdev_hangup(evdev); evdev_remove_chrdev(evdev); - if (evdev->grab) - evdev_ungrab(evdev, evdev->grab); - /* evdev is marked dead so no one else accesses evdev->open */ if (evdev->open) { input_flush_device(handle, NULL); @@ -896,7 +894,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, evdev->exist = 1; evdev->minor = minor; - evdev->handle.dev = dev; + evdev->handle.dev = input_get_device(dev); evdev->handle.name = evdev->name; evdev->handle.handler = handler; evdev->handle.private = evdev; diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 22b2789ef58a..65d7077a75a1 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -171,6 +171,7 @@ static void joydev_free(struct device *dev) { struct joydev *joydev = container_of(dev, struct joydev, dev); + input_put_device(joydev->handle.dev); kfree(joydev); } @@ -750,7 +751,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, joydev->minor = minor; joydev->exist = 1; - joydev->handle.dev = dev; + joydev->handle.dev = input_get_device(dev); joydev->handle.name = joydev->name; joydev->handle.handler = handler; joydev->handle.private = joydev; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index bbbe5e81adc1..b989748598ae 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -414,6 +414,7 @@ static void mousedev_free(struct device *dev) { struct mousedev *mousedev = container_of(dev, struct mousedev, dev); + input_put_device(mousedev->handle.dev); kfree(mousedev); } @@ -865,7 +866,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev, mousedev->minor = minor; mousedev->exist = 1; - mousedev->handle.dev = dev; + mousedev->handle.dev = input_get_device(dev); mousedev->handle.name = mousedev->name; mousedev->handle.handler = handler; mousedev->handle.private = mousedev; diff --git a/include/linux/input.h b/include/linux/input.h index 1bdc39a8c76c..cae2c35d1206 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1227,12 +1227,13 @@ void input_free_device(struct input_dev *dev); static inline struct input_dev *input_get_device(struct input_dev *dev) { - return to_input_dev(get_device(&dev->dev)); + return dev ? to_input_dev(get_device(&dev->dev)) : NULL; } static inline void input_put_device(struct input_dev *dev) { - put_device(&dev->dev); + if (dev) + put_device(&dev->dev); } static inline void *input_get_drvdata(struct input_dev *dev) -- cgit v1.2.3 From 758e285faca4db948ecddefb523007255b29cdb7 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 27 Mar 2008 16:09:31 +0300 Subject: [MIPS] Alchemy: work around clock misdetection on early Au1000 Work around the CPU clock miscalculation on Au1000DA/HA/HB due the sys_cpupll register being write-only, i.e. actually do what the comment before cal_r4off() function advertised for years but the code failed at. This is achieved by just giving user a chance to define the clock explicitly in the board config. via CONFIG_SOC_AU1000_FREQUENCY option, defaulting to 396 MHz if the option is not given... The patch is based on the AMD's big unpublished patch, the issue seems to be an undocumented errata (or feature :-)... Signed-off-by: Sergei Shtylyov Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/cputable.c | 36 +++++++++++++++++------------------ arch/mips/au1000/common/setup.c | 13 ++++++++++--- arch/mips/au1000/common/time.c | 24 +++++++++++++---------- include/asm-mips/mach-au1x00/au1000.h | 1 + 4 files changed, 43 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c index d8df5fdb045f..5c0d35d6e22a 100644 --- a/arch/mips/au1000/common/cputable.c +++ b/arch/mips/au1000/common/cputable.c @@ -22,24 +22,24 @@ struct cpu_spec* cur_cpu_spec[NR_CPUS]; /* With some thought, we can probably use the mask to reduce the * size of the table. */ -struct cpu_spec cpu_specs[] = { - { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0 }, - { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0 }, - { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0 }, - { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1 }, - { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1 }, - { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1 }, - { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1 }, - { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1 }, - { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1 }, - { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1 }, - { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1 }, - { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, - { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, - { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, - { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, - { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0 }, - { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, +struct cpu_spec cpu_specs[] = { + { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 }, + { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 }, + { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 }, + { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 }, + { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 }, + { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 }, + { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 }, + { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 }, + { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 }, + { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 }, + { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 }, + { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 }, + { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 }, + { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 }, + { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 }, + { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 }, + { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 } }; void diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index d885e3848ec6..9e4ab80caab6 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -57,7 +57,7 @@ void __init plat_mem_setup(void) { struct cpu_spec *sp; char *argptr; - unsigned long prid, cpupll, bclk = 1; + unsigned long prid, cpufreq, bclk = 1; set_cpuspec(); sp = cur_cpu_spec[0]; @@ -65,8 +65,15 @@ void __init plat_mem_setup(void) board_setup(); /* board specific setup */ prid = read_c0_prid(); - cpupll = (au_readl(0xB1900060) & 0x3F) * 12; - printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll); + if (sp->cpu_pll_wo) +#ifdef CONFIG_SOC_AU1000_FREQUENCY + cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000; +#else + cpufreq = 396; +#endif + else + cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12; + printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq); bclk = sp->cpu_bclk; if (bclk) diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index f113b512d7b1..e122bbc6cd88 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -209,18 +209,22 @@ unsigned long cal_r4koff(void) while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); au_writel(0, SYS_TOYWRITE); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); + } else + no_au1xxx_32khz = 1; - cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * - AU1000_SRC_CLK; - } - else { - /* The 32KHz oscillator isn't running, so assume there - * isn't one and grab the processor speed from the PLL. - * NOTE: some old silicon doesn't allow reading the PLL. - */ + /* + * On early Au1000, sys_cpupll was write-only. Since these + * silicon versions of Au1000 are not sold by AMD, we don't bend + * over backwards trying to determine the frequency. + */ + if (cur_cpu_spec[0]->cpu_pll_wo) +#ifdef CONFIG_SOC_AU1000_FREQUENCY + cpu_speed = CONFIG_SOC_AU1000_FREQUENCY; +#else + cpu_speed = 396000000; +#endif + else cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - no_au1xxx_32khz = 1; - } mips_hpt_frequency = cpu_speed; // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h index cb18af989645..5bb57bf2b9d7 100644 --- a/include/asm-mips/mach-au1x00/au1000.h +++ b/include/asm-mips/mach-au1x00/au1000.h @@ -1786,6 +1786,7 @@ struct cpu_spec { char *cpu_name; unsigned char cpu_od; /* Set Config[OD] */ unsigned char cpu_bclk; /* Enable BCLK switching */ + unsigned char cpu_pll_wo; /* sys_cpupll reg. write-only */ }; extern struct cpu_spec cpu_specs[]; -- cgit v1.2.3 From 34e6bbf23c8f43e8713d9bd092680f1660494b4a Mon Sep 17 00:00:00 2001 From: Fabio Checconi Date: Wed, 2 Apr 2008 14:31:02 +0200 Subject: cfq-iosched: fix rcu freeing of cfq io contexts SLAB_DESTROY_BY_RCU is not a direct substitute for normal call_rcu() freeing, since it'll page freeing but NOT object freeing. So change cfq to do the freeing on its own. Signed-off-by: Fabio Checconi Acked-by: Paul E. McKenney Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 57 ++++++++++++++++++++++------------------------- include/linux/iocontext.h | 3 +++ 2 files changed, 30 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 0f962ecae91f..f26da2bfcc15 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1143,24 +1143,37 @@ static void cfq_put_queue(struct cfq_queue *cfqq) } /* - * Call func for each cic attached to this ioc. Returns number of cic's seen. + * Call func for each cic attached to this ioc. */ -static unsigned int +static void call_for_each_cic(struct io_context *ioc, void (*func)(struct io_context *, struct cfq_io_context *)) { struct cfq_io_context *cic; struct hlist_node *n; - int called = 0; rcu_read_lock(); - hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) { + hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) func(ioc, cic); - called++; - } rcu_read_unlock(); +} + +static void cfq_cic_free_rcu(struct rcu_head *head) +{ + struct cfq_io_context *cic; + + cic = container_of(head, struct cfq_io_context, rcu_head); + + kmem_cache_free(cfq_ioc_pool, cic); + elv_ioc_count_dec(ioc_count); + + if (ioc_gone && !elv_ioc_count_read(ioc_count)) + complete(ioc_gone); +} - return called; +static void cfq_cic_free(struct cfq_io_context *cic) +{ + call_rcu(&cic->rcu_head, cfq_cic_free_rcu); } static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) @@ -1174,24 +1187,18 @@ static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) hlist_del_rcu(&cic->cic_list); spin_unlock_irqrestore(&ioc->lock, flags); - kmem_cache_free(cfq_ioc_pool, cic); + cfq_cic_free(cic); } static void cfq_free_io_context(struct io_context *ioc) { - int freed; - /* - * ioc->refcount is zero here, so no more cic's are allowed to be - * linked into this ioc. So it should be ok to iterate over the known - * list, we will see all cic's since no new ones are added. + * ioc->refcount is zero here, or we are called from elv_unregister(), + * so no more cic's are allowed to be linked into this ioc. So it + * should be ok to iterate over the known list, we will see all cic's + * since no new ones are added. */ - freed = call_for_each_cic(ioc, cic_free_func); - - elv_ioc_count_mod(ioc_count, -freed); - - if (ioc_gone && !elv_ioc_count_read(ioc_count)) - complete(ioc_gone); + call_for_each_cic(ioc, cic_free_func); } static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) @@ -1458,15 +1465,6 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc, return cfqq; } -static void cfq_cic_free(struct cfq_io_context *cic) -{ - kmem_cache_free(cfq_ioc_pool, cic); - elv_ioc_count_dec(ioc_count); - - if (ioc_gone && !elv_ioc_count_read(ioc_count)) - complete(ioc_gone); -} - /* * We drop cfq io contexts lazily, so we may find a dead one. */ @@ -2138,7 +2136,7 @@ static int __init cfq_slab_setup(void) if (!cfq_pool) goto fail; - cfq_ioc_pool = KMEM_CACHE(cfq_io_context, SLAB_DESTROY_BY_RCU); + cfq_ioc_pool = KMEM_CACHE(cfq_io_context, 0); if (!cfq_ioc_pool) goto fail; @@ -2286,7 +2284,6 @@ static void __exit cfq_exit(void) smp_wmb(); if (elv_ioc_count_read(ioc_count)) wait_for_completion(ioc_gone); - synchronize_rcu(); cfq_slab_kill(); } diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h index 1b4ccf25b4d2..cac4b364cd40 100644 --- a/include/linux/iocontext.h +++ b/include/linux/iocontext.h @@ -2,6 +2,7 @@ #define IOCONTEXT_H #include +#include /* * This is the per-process anticipatory I/O scheduler state. @@ -54,6 +55,8 @@ struct cfq_io_context { void (*dtor)(struct io_context *); /* destructor */ void (*exit)(struct io_context *); /* called on task exit */ + + struct rcu_head rcu_head; }; /* -- cgit v1.2.3 From dd135ebbd2a6b5e07dadb66c4dd033bb69531051 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 2 Apr 2008 13:04:40 -0700 Subject: kvm: provide kvm.h for all architecture: fixes headers_install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently include/linux/kvm.h is not considered by make headers_install, because Kbuild cannot handle " unifdef-$(CONFIG_FOO) += foo.h. This problem was introduced by commit fb56dbb31c4738a3918db81fd24da732ce3b4ae6 Author: Avi Kivity Date: Sun Dec 2 10:50:06 2007 +0200 KVM: Export include/linux/kvm.h only if $ARCH actually supports KVM Currently, make headers_check barfs due to , which includes, not existing. Rather than add a zillion s, export kvm. only if the arch actually supports it. Signed-off-by: Avi Kivity which makes this an 2.6.25 regression. One way of solving the issue is to enhance Kbuild, but Avi and David conviced me, that changing headers_install is not the way to go. This patch changes the definition for linux/kvm.h to unifdef-y. If  unifdef-y is used for linux/kvm.h "make headers_check" will fail on all architectures without asm/kvm.h. Therefore, this patch also provides asm/kvm.h on all architectures. Signed-off-by: Christian Borntraeger Acked-by: Avi Kivity Cc: Sam Ravnborg Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/kvm.h | 6 ++++++ include/asm-arm/kvm.h | 6 ++++++ include/asm-avr32/kvm.h | 6 ++++++ include/asm-blackfin/kvm.h | 6 ++++++ include/asm-cris/kvm.h | 6 ++++++ include/asm-frv/kvm.h | 6 ++++++ include/asm-generic/Kbuild.asm | 2 ++ include/asm-h8300/kvm.h | 6 ++++++ include/asm-ia64/kvm.h | 6 ++++++ include/asm-m32r/kvm.h | 6 ++++++ include/asm-m68k/kvm.h | 6 ++++++ include/asm-m68knommu/kvm.h | 6 ++++++ include/asm-mips/kvm.h | 6 ++++++ include/asm-mn10300/kvm.h | 6 ++++++ include/asm-parisc/kvm.h | 6 ++++++ include/asm-powerpc/kvm.h | 6 ++++++ include/asm-s390/kvm.h | 6 ++++++ include/asm-sh/kvm.h | 6 ++++++ include/asm-sparc/kvm.h | 6 ++++++ include/asm-sparc64/kvm.h | 6 ++++++ include/asm-um/kvm.h | 6 ++++++ include/asm-v850/kvm.h | 6 ++++++ include/asm-xtensa/kvm.h | 6 ++++++ include/linux/Kbuild | 2 +- 24 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 include/asm-alpha/kvm.h create mode 100644 include/asm-arm/kvm.h create mode 100644 include/asm-avr32/kvm.h create mode 100644 include/asm-blackfin/kvm.h create mode 100644 include/asm-cris/kvm.h create mode 100644 include/asm-frv/kvm.h create mode 100644 include/asm-h8300/kvm.h create mode 100644 include/asm-ia64/kvm.h create mode 100644 include/asm-m32r/kvm.h create mode 100644 include/asm-m68k/kvm.h create mode 100644 include/asm-m68knommu/kvm.h create mode 100644 include/asm-mips/kvm.h create mode 100644 include/asm-mn10300/kvm.h create mode 100644 include/asm-parisc/kvm.h create mode 100644 include/asm-powerpc/kvm.h create mode 100644 include/asm-s390/kvm.h create mode 100644 include/asm-sh/kvm.h create mode 100644 include/asm-sparc/kvm.h create mode 100644 include/asm-sparc64/kvm.h create mode 100644 include/asm-um/kvm.h create mode 100644 include/asm-v850/kvm.h create mode 100644 include/asm-xtensa/kvm.h (limited to 'include') diff --git a/include/asm-alpha/kvm.h b/include/asm-alpha/kvm.h new file mode 100644 index 000000000000..b9daec429689 --- /dev/null +++ b/include/asm-alpha/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_ALPHA_H +#define __LINUX_KVM_ALPHA_H + +/* alpha does not support KVM */ + +#endif diff --git a/include/asm-arm/kvm.h b/include/asm-arm/kvm.h new file mode 100644 index 000000000000..cb3c08cbcb9e --- /dev/null +++ b/include/asm-arm/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_ARM_H +#define __LINUX_KVM_ARM_H + +/* arm does not support KVM */ + +#endif diff --git a/include/asm-avr32/kvm.h b/include/asm-avr32/kvm.h new file mode 100644 index 000000000000..8c5777020e2c --- /dev/null +++ b/include/asm-avr32/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_AVR32_H +#define __LINUX_KVM_AVR32_H + +/* avr32 does not support KVM */ + +#endif diff --git a/include/asm-blackfin/kvm.h b/include/asm-blackfin/kvm.h new file mode 100644 index 000000000000..e3477d77c014 --- /dev/null +++ b/include/asm-blackfin/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_BLACKFIN_H +#define __LINUX_KVM_BLACKFIN_H + +/* blackfin does not support KVM */ + +#endif diff --git a/include/asm-cris/kvm.h b/include/asm-cris/kvm.h new file mode 100644 index 000000000000..c860f51149f0 --- /dev/null +++ b/include/asm-cris/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_CRIS_H +#define __LINUX_KVM_CRIS_H + +/* cris does not support KVM */ + +#endif diff --git a/include/asm-frv/kvm.h b/include/asm-frv/kvm.h new file mode 100644 index 000000000000..9c8a4f08d0a9 --- /dev/null +++ b/include/asm-frv/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_FRV_H +#define __LINUX_KVM_FRV_H + +/* frv does not support KVM */ + +#endif diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm index fd9dcfd91c39..92a6d91d0c1a 100644 --- a/include/asm-generic/Kbuild.asm +++ b/include/asm-generic/Kbuild.asm @@ -1,3 +1,5 @@ +header-y += kvm.h + ifeq ($(wildcard include/asm-$(SRCARCH)/a.out.h),include/asm-$(SRCARCH)/a.out.h) unifdef-y += a.out.h endif diff --git a/include/asm-h8300/kvm.h b/include/asm-h8300/kvm.h new file mode 100644 index 000000000000..bdbed7b987e1 --- /dev/null +++ b/include/asm-h8300/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_H8300_H +#define __LINUX_KVM_H8300_H + +/* h8300 does not support KVM */ + +#endif diff --git a/include/asm-ia64/kvm.h b/include/asm-ia64/kvm.h new file mode 100644 index 000000000000..030d29b4b26b --- /dev/null +++ b/include/asm-ia64/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_IA64_H +#define __LINUX_KVM_IA64_H + +/* ia64 does not support KVM */ + +#endif diff --git a/include/asm-m32r/kvm.h b/include/asm-m32r/kvm.h new file mode 100644 index 000000000000..99a40515b77e --- /dev/null +++ b/include/asm-m32r/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_M32R_H +#define __LINUX_KVM_M32R_H + +/* m32r does not support KVM */ + +#endif diff --git a/include/asm-m68k/kvm.h b/include/asm-m68k/kvm.h new file mode 100644 index 000000000000..7ed27fce5240 --- /dev/null +++ b/include/asm-m68k/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_M68K_H +#define __LINUX_KVM_M68K_H + +/* m68k does not support KVM */ + +#endif diff --git a/include/asm-m68knommu/kvm.h b/include/asm-m68knommu/kvm.h new file mode 100644 index 000000000000..b49d4258dabb --- /dev/null +++ b/include/asm-m68knommu/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_M68KNOMMU_H +#define __LINUX_KVM_M68KNOMMU_H + +/* m68knommu does not support KVM */ + +#endif diff --git a/include/asm-mips/kvm.h b/include/asm-mips/kvm.h new file mode 100644 index 000000000000..093a5b7f796b --- /dev/null +++ b/include/asm-mips/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_MIPS_H +#define __LINUX_KVM_MIPS_H + +/* mips does not support KVM */ + +#endif diff --git a/include/asm-mn10300/kvm.h b/include/asm-mn10300/kvm.h new file mode 100644 index 000000000000..f6b609ff4a57 --- /dev/null +++ b/include/asm-mn10300/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_MN10300_H +#define __LINUX_KVM_MN10300_H + +/* mn10300 does not support KVM */ + +#endif diff --git a/include/asm-parisc/kvm.h b/include/asm-parisc/kvm.h new file mode 100644 index 000000000000..00cc45812547 --- /dev/null +++ b/include/asm-parisc/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_PARISC_H +#define __LINUX_KVM_PARISC_H + +/* parisc does not support KVM */ + +#endif diff --git a/include/asm-powerpc/kvm.h b/include/asm-powerpc/kvm.h new file mode 100644 index 000000000000..d1b530fbf8dd --- /dev/null +++ b/include/asm-powerpc/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_POWERPC_H +#define __LINUX_KVM_POWERPC_H + +/* powerpc does not support KVM */ + +#endif diff --git a/include/asm-s390/kvm.h b/include/asm-s390/kvm.h new file mode 100644 index 000000000000..573f2a351386 --- /dev/null +++ b/include/asm-s390/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_S390_H +#define __LINUX_KVM_S390_H + +/* s390 does not support KVM */ + +#endif diff --git a/include/asm-sh/kvm.h b/include/asm-sh/kvm.h new file mode 100644 index 000000000000..6af51dbab2d0 --- /dev/null +++ b/include/asm-sh/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_SH_H +#define __LINUX_KVM_SH_H + +/* sh does not support KVM */ + +#endif diff --git a/include/asm-sparc/kvm.h b/include/asm-sparc/kvm.h new file mode 100644 index 000000000000..2e5478da3819 --- /dev/null +++ b/include/asm-sparc/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_SPARC_H +#define __LINUX_KVM_SPARC_H + +/* sparc does not support KVM */ + +#endif diff --git a/include/asm-sparc64/kvm.h b/include/asm-sparc64/kvm.h new file mode 100644 index 000000000000..380537a77bf9 --- /dev/null +++ b/include/asm-sparc64/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_SPARC64_H +#define __LINUX_KVM_SPARC64_H + +/* sparc64 does not support KVM */ + +#endif diff --git a/include/asm-um/kvm.h b/include/asm-um/kvm.h new file mode 100644 index 000000000000..66aa77094551 --- /dev/null +++ b/include/asm-um/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_UM_H +#define __LINUX_KVM_UM_H + +/* um does not support KVM */ + +#endif diff --git a/include/asm-v850/kvm.h b/include/asm-v850/kvm.h new file mode 100644 index 000000000000..3f729b79febc --- /dev/null +++ b/include/asm-v850/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_V850_H +#define __LINUX_KVM_V850_H + +/* v850 does not support KVM */ + +#endif diff --git a/include/asm-xtensa/kvm.h b/include/asm-xtensa/kvm.h new file mode 100644 index 000000000000..bda4e331e98c --- /dev/null +++ b/include/asm-xtensa/kvm.h @@ -0,0 +1,6 @@ +#ifndef __LINUX_KVM_XTENSA_H +#define __LINUX_KVM_XTENSA_H + +/* xtensa does not support KVM */ + +#endif diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 4a446a19295e..9cdd12a9e843 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -253,7 +253,7 @@ unifdef-y += kd.h unifdef-y += kernelcapi.h unifdef-y += kernel.h unifdef-y += keyboard.h -unifdef-$(CONFIG_HAVE_KVM) += kvm.h +unifdef-y += kvm.h unifdef-y += llc.h unifdef-y += loop.h unifdef-y += lp.h -- cgit v1.2.3 From c143d43aa3149b83e4b40624a27aa2b18638afec Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Wed, 2 Apr 2008 13:04:43 -0700 Subject: alpha: fix ALSA DMA mmap crash Make dma_alloc_coherent respect gfp flags (__GFP_COMP is one that matters). Signed-off-by: Ivan Kokshaysky Tested-by: Michael Cree Cc: Richard Henderson Cc: Jaroslav Kysela Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/pci_iommu.c | 8 +++++--- include/asm-alpha/dma-mapping.h | 2 +- include/asm-alpha/pci.h | 8 +++++++- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index 4e1c08636edd..dd6e334ab9e1 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -424,11 +424,13 @@ EXPORT_SYMBOL(pci_unmap_page); else DMA_ADDRP is undefined. */ void * -pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) +__pci_alloc_consistent(struct pci_dev *pdev, size_t size, + dma_addr_t *dma_addrp, gfp_t gfp) { void *cpu_addr; long order = get_order(size); - gfp_t gfp = GFP_ATOMIC; + + gfp &= ~GFP_DMA; try_again: cpu_addr = (void *)__get_free_pages(gfp, order); @@ -458,7 +460,7 @@ try_again: return cpu_addr; } -EXPORT_SYMBOL(pci_alloc_consistent); +EXPORT_SYMBOL(__pci_alloc_consistent); /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must be values that were returned from pci_alloc_consistent. SIZE must diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h index 75a1aff5b57b..db351d1296f4 100644 --- a/include/asm-alpha/dma-mapping.h +++ b/include/asm-alpha/dma-mapping.h @@ -11,7 +11,7 @@ #define dma_unmap_single(dev, addr, size, dir) \ pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir) #define dma_alloc_coherent(dev, size, addr, gfp) \ - pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr) + __pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr, gfp) #define dma_free_coherent(dev, size, va, addr) \ pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr) #define dma_map_page(dev, page, off, size, dir) \ diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h index d5b10ef64364..d31fd49ff79a 100644 --- a/include/asm-alpha/pci.h +++ b/include/asm-alpha/pci.h @@ -76,7 +76,13 @@ extern inline void pcibios_penalize_isa_irq(int irq, int active) successful and sets *DMA_ADDRP to the pci side dma address as well, else DMA_ADDRP is undefined. */ -extern void *pci_alloc_consistent(struct pci_dev *, size_t, dma_addr_t *); +extern void *__pci_alloc_consistent(struct pci_dev *, size_t, + dma_addr_t *, gfp_t); +static inline void * +pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma) +{ + return __pci_alloc_consistent(dev, size, dma, GFP_ATOMIC); +} /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must be values that were returned from pci_alloc_consistent. SIZE must -- cgit v1.2.3 From 06f11f37aa84e83b48cdf36037c4414f5a83c13f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 2 Apr 2008 13:04:52 -0700 Subject: alpha: get_current(): don't add zero to current_thread_info()->task A nasty compile error: In file included from security/keys/internal.h:16, from security/keys/sysctl.c:14: include/linux/key-ui.h: In function 'key_permission': include/linux/key-ui.h:51: error: invalid use of undefined type 'struct task_struct' apparently the compiler has decided that it needs to know sizeof(task_struct) so that it can add zero to a task_struct* (which is rather dumb of it). Getting task_struct in scope in these deeply-nested headers is scary-looking, so let's just remove the "+ 0". Cc: David Howells Cc: Richard Henderson Cc: Ivan Kokshaysky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/current.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-alpha/current.h b/include/asm-alpha/current.h index 8d88a13c1bec..094d285a1b34 100644 --- a/include/asm-alpha/current.h +++ b/include/asm-alpha/current.h @@ -3,7 +3,7 @@ #include -#define get_current() (current_thread_info()->task + 0) +#define get_current() (current_thread_info()->task) #define current get_current() #endif /* _ALPHA_CURRENT_H */ -- cgit v1.2.3