From 94e549eaa6e8959404a559d23a8bef9ab1e6e4b3 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 17 Sep 2003 03:06:26 -0700 Subject: [PATCH] USB: psdocs fails for usbgadget It updates the "gadget" kerneldoc, removing some (new) warnings, and showing some fields it hadn't previously been showing (due to limitations in docproc). Plus it adds a bit of information about recent changes (new drivers). --- include/linux/usb_gadget.h | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h index c98a95dbe250..da2d9749baf6 100644 --- a/include/linux/usb_gadget.h +++ b/include/linux/usb_gadget.h @@ -72,9 +72,9 @@ struct usb_request { unsigned length; dma_addr_t dma; - unsigned no_interrupt : 1, - zero : 1, - short_not_ok : 1; + unsigned no_interrupt:1; + unsigned zero:1; + unsigned short_not_ok:1; void (*complete)(struct usb_ep *ep, struct usb_request *req); @@ -122,9 +122,11 @@ struct usb_ep_ops { /** * struct usb_ep - device side representation of USB endpoint * @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk" + * @ops: Function pointers used to access hardware-specific operations. * @ep_list:the gadget's ep_list holds all of its endpoints - * @maxpacket:the maximum packet size used on this endpoint, as - * configured when the endpoint was enabled. + * @maxpacket:The maximum packet size used on this endpoint. The initial + * value can sometimes be reduced (hardware allowing), according to + * the endpoint descriptor used to configure the endpoint. * @driver_data:for use by the gadget driver. all other fields are * read-only to gadget drivers. * @@ -138,7 +140,7 @@ struct usb_ep { const char *name; const struct usb_ep_ops *ops; struct list_head ep_list; - unsigned maxpacket : 16; + unsigned maxpacket:16; }; /*-------------------------------------------------------------------------*/ @@ -443,18 +445,21 @@ struct usb_gadget_ops { /** * struct usb_gadget - represents a usb slave device + * @ops: Function pointers used to access hardware-specific operations. * @ep0: Endpoint zero, used when reading or writing responses to * driver setup() requests * @ep_list: List of other endpoints supported by the device. * @speed: Speed of current connection to USB host. * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. + * @dev: Driver model state for this abstract device. * * Gadgets have a mostly-portable "gadget driver" implementing device - * functions, handling all usb configurations and interfaces. They - * also have a hardware-specific driver (accessed through ops vectors), - * which insulates the gadget driver from hardware details and packages - * the hardware endpoints through generic i/o queues. + * functions, handling all usb configurations and interfaces. Gadget + * drivers talk to hardware-specific code indirectly, through ops vectors. + * That insulates the gadget driver from hardware details, and packages + * the hardware endpoints through generic i/o queues. The "usb_gadget" + * and "usb_ep" interfaces provide that insulation from the hardware. * * Except for the driver data, all fields in this structure are * read-only to the gadget driver. That driver data is part of the @@ -469,10 +474,6 @@ struct usb_gadget { struct list_head ep_list; /* of usb_ep */ enum usb_device_speed speed; const char *name; - - /* use this to allocate dma-coherent buffers or set up - * dma mappings. or print diagnostics, etc. - */ struct device dev; }; @@ -576,6 +577,7 @@ usb_gadget_clear_selfpowered (struct usb_gadget *gadget) * Called in a context that permits sleeping. * @suspend: Invoked on USB suspend. May be called in_interrupt. * @resume: Invoked on USB resume. May be called in_interrupt. + * @driver: Driver model state for this driver. * * Devices are disabled till a gadget driver successfully bind()s, which * means the driver will handle setup() requests needed to enumerate (and -- cgit v1.2.3 From 46c4d99be2f36abda46f51b33ecb2e9fb940e927 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 17 Sep 2003 03:59:57 -0700 Subject: [PATCH] USB: Changes to core/config.c (6 of 9) This patch removes the home-brewed resizeable arrays used to store altsetting structures, along with the now-unneeded max_altsetting field. Since we are already making a preliminary pass through all the descriptors to check their lengths, we take the opportunity to also count the number of altsetting descriptors for each interface. Then exactly the right number can be allocated all at once. This also moves the code that allocates the altsettings outside the usb_parse_interface() routine. Though not important now, this change will come in handy in the next patch. --- drivers/usb/core/config.c | 89 ++++++++++++++++++++++++++++------------------- include/linux/usb.h | 2 -- 2 files changed, 54 insertions(+), 37 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 89112f2bde2f..4ce45e0091d7 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -10,7 +10,6 @@ /* these maximums are arbitrary */ #define USB_MAXCONFIG 8 -#define USB_ALTSETTINGALLOC 4 #define USB_MAXINTERFACES 32 static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char *buffer, int size) @@ -108,43 +107,27 @@ static int usb_parse_interface(struct usb_interface *interface, unsigned char *b struct usb_host_interface *ifp; unsigned char *begin; - interface->max_altsetting = USB_ALTSETTINGALLOC; - interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, - GFP_KERNEL); - if (!interface->altsetting) { - err("couldn't kmalloc interface->altsetting"); - return -ENOMEM; - } - - while (size > 0) { + ifp = interface->altsetting; + while (size >= sizeof(struct usb_descriptor_header)) { struct usb_interface_descriptor *d; - if (interface->num_altsetting >= interface->max_altsetting) { - struct usb_host_interface *ptr; - int oldmas; + d = (struct usb_interface_descriptor *) buffer; + if (d->bAlternateSetting >= interface->num_altsetting) { - oldmas = interface->max_altsetting; - interface->max_altsetting += USB_ALTSETTINGALLOC; - if (interface->max_altsetting > USB_MAXALTSETTING) { - warn("too many alternate settings (incr %d max %d)\n", - USB_ALTSETTINGALLOC, USB_MAXALTSETTING); - return -EINVAL; - } + /* Skip to the next interface descriptor */ + buffer += d->bLength; + size -= d->bLength; + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *) buffer; - ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL); - if (ptr == NULL) { - err("couldn't kmalloc interface->altsetting"); - return -ENOMEM; + if (header->bDescriptorType == USB_DT_INTERFACE) + break; + buffer += header->bLength; + size -= header->bLength; } - memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas); - kfree(interface->altsetting); - interface->altsetting = ptr; + continue; } - ifp = interface->altsetting + interface->num_altsetting; - memset(ifp, 0, sizeof(*ifp)); - interface->num_altsetting++; - memcpy(&ifp->desc, buffer, USB_DT_INTERFACE_SIZE); buffer += ifp->desc.bLength; @@ -216,6 +199,8 @@ static int usb_parse_interface(struct usb_interface *interface, unsigned char *b || d->bDescriptorType != USB_DT_INTERFACE || !d->bAlternateSetting) break; + + ++ifp; } return buffer - buffer0; @@ -223,7 +208,7 @@ static int usb_parse_interface(struct usb_interface *interface, unsigned char *b int usb_parse_configuration(struct usb_host_config *config, char *buffer) { - int nintf; + int nintf, nintf_orig; int i, j, size; struct usb_interface *interface; char *buffer2; @@ -237,7 +222,7 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer) le16_to_cpus(&config->desc.wTotalLength); size = config->desc.wTotalLength; - nintf = config->desc.bNumInterfaces; + nintf = nintf_orig = config->desc.bNumInterfaces; if (nintf > USB_MAXINTERFACES) { warn("too many interfaces (%d max %d)", nintf, USB_MAXINTERFACES); @@ -260,7 +245,8 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer) get_device(&interface->dev); } - /* Go through the descriptors, checking their length */ + /* Go through the descriptors, checking their length and counting the + * number of altsettings for each interface */ buffer2 = buffer; size2 = size; j = 0; @@ -272,10 +258,21 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer) } if (header->bDescriptorType == USB_DT_INTERFACE) { + struct usb_interface_descriptor *d; + if (header->bLength < USB_DT_INTERFACE_SIZE) { warn("invalid interface descriptor"); return -EINVAL; } + d = (struct usb_interface_descriptor *) header; + i = d->bInterfaceNumber; + if (i >= nintf_orig) { + warn("invalid interface number (%d/%d)", + i, nintf_orig); + return -EINVAL; + } + if (i < nintf) + ++config->interface[i]->num_altsetting; } else if ((header->bDescriptorType == USB_DT_DEVICE || header->bDescriptorType == USB_DT_CONFIG) && j) { @@ -288,6 +285,28 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer) size2 -= header->bLength; } + /* Allocate the altsetting arrays */ + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + interface = config->interface[i]; + if (interface->num_altsetting > USB_MAXALTSETTING) { + warn("too many alternate settings for interface %d (%d max %d)\n", + i, interface->num_altsetting, USB_MAXALTSETTING); + return -EINVAL; + } + if (interface->num_altsetting == 0) { + warn("no alternate settings for interface %d", i); + return -EINVAL; + } + + len = sizeof(*interface->altsetting) * interface->num_altsetting; + interface->altsetting = kmalloc(len, GFP_KERNEL); + if (!interface->altsetting) { + err("couldn't kmalloc interface->altsetting"); + return -ENOMEM; + } + memset(interface->altsetting, 0, len); + } + buffer += config->desc.bLength; size -= config->desc.bLength; @@ -325,7 +344,7 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer) } /* Parse all the interface/altsetting descriptors */ - for (i = 0; i < nintf; i++) { + for (i = 0; i < nintf_orig; i++) { retval = usb_parse_interface(config->interface[i], buffer, size); if (retval < 0) return retval; diff --git a/include/linux/usb.h b/include/linux/usb.h index a20b33d953aa..5575ebfb276d 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -80,7 +80,6 @@ struct usb_host_interface { * @act_altsetting: index of current altsetting. this number is always * less than num_altsetting. after the device is configured, each * interface uses its default setting of zero. - * @max_altsetting: the max number of altsettings for this interface. * @driver: the USB driver that is bound to this interface. * @minor: the minor number assigned to this interface, if this * interface is bound to a driver that uses the USB major number. @@ -118,7 +117,6 @@ struct usb_interface { unsigned act_altsetting; /* active alternate setting */ unsigned num_altsetting; /* number of alternate settings */ - unsigned max_altsetting; /* total memory allocated */ struct usb_driver *driver; /* driver */ int minor; /* minor number this interface is bound to */ -- cgit v1.2.3 From 2e92db0d917437a4f2f522e4be0522a8dbd048b2 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Thu, 18 Sep 2003 11:17:37 -0700 Subject: Input: Big Synaptics update: Restore synaptics pad mode on module unload. Support Synaptics touchpads with multiple buttons. Make Synaptics touchpad support optional. Add passthrough support for Synaptics touchpads. [Dmitry] Add support for old Synaptics protocol. Set mode byte correctly for old Synaptics pads. Fix multibutton support of Synaptics pads. --- Documentation/kernel-parameters.txt | 4 + drivers/input/mouse/Kconfig | 20 +- drivers/input/mouse/psmouse-base.c | 69 +++++-- drivers/input/mouse/psmouse.h | 22 ++- drivers/input/mouse/synaptics.c | 362 ++++++++++++++++++++++++++++-------- drivers/input/mouse/synaptics.h | 27 ++- drivers/input/serio/serio.c | 25 +++ include/linux/serio.h | 3 + 8 files changed, 423 insertions(+), 109 deletions(-) (limited to 'include/linux') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f6121f18c501..3a66d54c51e0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -788,6 +788,10 @@ running once the system is up. psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions + psmouse_resetafter= + [HW,MOUSE] Try to reset Synaptics Touchpad after so many + bad packets (0 = never). + pss= [HW,OSS] Personal Sound System (ECHO ESC614) Format: ,,,,, diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index a6b481994163..9105f6c697b3 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -19,9 +19,7 @@ config MOUSE_PS2 Say Y here if you have a PS/2 mouse connected to your system. This includes the standard 2 or 3-button PS/2 mouse, as well as PS/2 mice with wheels and extra buttons, Microsoft, Logitech or Genius - compatible. Support for Synaptics TouchPads is also included. - For Synaptics TouchPad support in XFree86 you'll need this XFree86 - driver: http://w1.894.telia.com/~u89404340/touchpad/index.html + compatible. If unsure, say Y. @@ -30,6 +28,22 @@ config MOUSE_PS2 The module will be called psmouse. If you want to compile it as a module, say M here and read . +config MOUSE_PS2_SYNAPTICS + bool "Synaptics TouchPad" + default n + depends on INPUT && INPUT_MOUSE && SERIO && MOUSE_PS2 + ---help--- + Say Y here if you have a Synaptics TouchPad connected to your system. + This touchpad is found on many modern laptop computers. + + Note that you also need a user space driver to interpret the data + generated by the kernel. A compatible driver for XFree86 is available + from http://w1.894.telia.com/~u89404340/touchpad/index.html + + The gpm program is not yet able to interpret the data from this + driver, so if you need to use the touchpad in the console, you have to + say N for now. + config MOUSE_SERIAL tristate "Serial mouse" depends on INPUT && INPUT_MOUSE && SERIO diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index c97fd2db0f41..f8aee39268a1 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -29,6 +29,8 @@ MODULE_PARM(psmouse_resolution, "i"); MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi."); MODULE_PARM(psmouse_smartscroll, "i"); MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); +MODULE_PARM(psmouse_resetafter, "i"); +MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never)."); MODULE_LICENSE("GPL"); #define PSMOUSE_LOGITECH_SMARTSCROLL 1 @@ -36,11 +38,12 @@ MODULE_LICENSE("GPL"); static int psmouse_noext; int psmouse_resolution; int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL; +unsigned int psmouse_resetafter; static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "Synaptics"}; /* - * psmouse_process_packet() anlyzes the PS/2 mouse packet contents and + * psmouse_process_packet() analyzes the PS/2 mouse packet contents and * reports relevant events to the input module. */ @@ -108,6 +111,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, { struct psmouse *psmouse = serio->private; + if (psmouse->state == PSMOUSE_IGNORE) + goto out; + if (psmouse->acking) { switch (data) { case PSMOUSE_RET_ACK: @@ -132,31 +138,46 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, } if (psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { - printk(KERN_WARNING "psmouse.c: Lost synchronization, throwing %d bytes away.\n", psmouse->pktcnt); + printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", + psmouse->name, psmouse->phys, psmouse->pktcnt); psmouse->pktcnt = 0; } psmouse->last = jiffies; psmouse->packet[psmouse->pktcnt++] = data; - if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) { - psmouse_process_packet(psmouse, regs); - psmouse->pktcnt = 0; - goto out; + if (psmouse->packet[0] == PSMOUSE_RET_BAT) { + if (psmouse->pktcnt == 1) + goto out; + + if (psmouse->pktcnt == 2) { + if (psmouse->packet[1] == PSMOUSE_RET_ID) { + psmouse->state = PSMOUSE_IGNORE; + serio_rescan(serio); + goto out; + } + if (psmouse->type == PSMOUSE_SYNAPTICS) { + /* neither 0xAA nor 0x00 are valid first bytes + * for a packet in absolute mode + */ + psmouse->pktcnt = 0; + goto out; + } + } } - if (psmouse->pktcnt == 1 && psmouse->type == PSMOUSE_SYNAPTICS) { + if (psmouse->type == PSMOUSE_SYNAPTICS) { /* * The synaptics driver has its own resync logic, * so it needs to receive all bytes one at a time. */ synaptics_process_byte(psmouse, regs); - psmouse->pktcnt = 0; goto out; } - if (psmouse->pktcnt == 1 && psmouse->packet[0] == PSMOUSE_RET_BAT) { - serio_rescan(serio); + if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) { + psmouse_process_packet(psmouse, regs); + psmouse->pktcnt = 0; goto out; } out: @@ -227,7 +248,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) for (i = 0; i < receive; i++) param[i] = psmouse->cmdbuf[(receive - 1) - i]; - if (psmouse->cmdcnt) + if (psmouse->cmdcnt) return (psmouse->cmdcnt = 0) - 1; return 0; @@ -450,14 +471,18 @@ static void psmouse_initialize(struct psmouse *psmouse) */ psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM); +} /* - * Last, we enable the mouse so that we get reports from it. + * psmouse_activate() enables the mouse so that we get motion reports from it. */ +static void psmouse_activate(struct psmouse *psmouse) +{ if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE)) printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys); + psmouse->state = PSMOUSE_ACTIVATED; } /* @@ -478,8 +503,9 @@ static void psmouse_cleanup(struct serio *serio) static void psmouse_disconnect(struct serio *serio) { struct psmouse *psmouse = serio->private; - if (psmouse->type == PSMOUSE_SYNAPTICS) - synaptics_disconnect(psmouse); + + psmouse->state = PSMOUSE_IGNORE; + synaptics_disconnect(psmouse); input_unregister_device(&psmouse->dev); serio_close(serio); kfree(psmouse); @@ -494,7 +520,8 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) { struct psmouse *psmouse; - if ((serio->type & SERIO_TYPE) != SERIO_8042) + if ((serio->type & SERIO_TYPE) != SERIO_8042 && + (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU) return; if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) @@ -507,6 +534,7 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); + psmouse->state = PSMOUSE_NEW_DEVICE; psmouse->serio = serio; psmouse->dev.private = psmouse; @@ -540,6 +568,10 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); psmouse_initialize(psmouse); + + synaptics_pt_init(psmouse); + + psmouse_activate(psmouse); } static struct serio_dev psmouse_dev = { @@ -568,9 +600,16 @@ static int __init psmouse_smartscroll_setup(char *str) return 1; } +static int __init psmouse_resetafter_setup(char *str) +{ + get_option(&str, &psmouse_resetafter); + return 1; +} + __setup("psmouse_noext", psmouse_noext_setup); __setup("psmouse_resolution=", psmouse_resolution_setup); __setup("psmouse_smartscroll=", psmouse_smartscroll_setup); +__setup("psmouse_resetafter=", psmouse_resetafter_setup); #endif diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 05a24de18d7d..a69cb72d8a80 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -13,9 +13,15 @@ #define PSMOUSE_CMD_RESET_BAT 0x02ff #define PSMOUSE_RET_BAT 0xaa +#define PSMOUSE_RET_ID 0x00 #define PSMOUSE_RET_ACK 0xfa #define PSMOUSE_RET_NAK 0xfe +/* psmouse states */ +#define PSMOUSE_NEW_DEVICE 0 +#define PSMOUSE_ACTIVATED 1 +#define PSMOUSE_IGNORE 2 + struct psmouse { void *private; struct input_dev dev; @@ -29,6 +35,7 @@ struct psmouse { unsigned char type; unsigned char model; unsigned long last; + unsigned char state; char acking; volatile char ack; char error; @@ -36,16 +43,17 @@ struct psmouse { char phys[32]; }; -#define PSMOUSE_PS2 1 -#define PSMOUSE_PS2PP 2 -#define PSMOUSE_PS2TPP 3 -#define PSMOUSE_GENPS 4 -#define PSMOUSE_IMPS 5 -#define PSMOUSE_IMEX 6 -#define PSMOUSE_SYNAPTICS 7 +#define PSMOUSE_PS2 1 +#define PSMOUSE_PS2PP 2 +#define PSMOUSE_PS2TPP 3 +#define PSMOUSE_GENPS 4 +#define PSMOUSE_IMPS 5 +#define PSMOUSE_IMEX 6 +#define PSMOUSE_SYNAPTICS 7 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command); extern int psmouse_smartscroll; +extern unsigned int psmouse_resetafter; #endif /* _PSMOUSE_H */ diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index de950db4aa8f..9ba48609d77e 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1,6 +1,9 @@ /* * Synaptics TouchPad PS/2 mouse driver * + * 2003 Dmitry Torokhov + * Added support for pass-through port + * * 2003 Peter Osterlund * Ported to 2.5 input device infrastructure. * @@ -21,6 +24,7 @@ #include #include +#include #include "psmouse.h" #include "synaptics.h" @@ -71,7 +75,7 @@ static int synaptics_set_mode(struct psmouse *psmouse, unsigned char mode) if (synaptics_special_cmd(psmouse, mode)) return -1; - param[0] = 0x14; + param[0] = SYN_PS_SET_MODE2; if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE)) return -1; return 0; @@ -83,7 +87,7 @@ static int synaptics_reset(struct psmouse *psmouse) if (psmouse_command(psmouse, r, PSMOUSE_CMD_RESET_BAT)) return -1; - if (r[0] == 0xAA && r[1] == 0x00) + if (r[0] == PSMOUSE_RET_BAT && r[1] == PSMOUSE_RET_ID) return 0; return -1; } @@ -106,16 +110,25 @@ static int synaptics_model_id(struct psmouse *psmouse, unsigned long int *model_ * Read the capability-bits from the touchpad * see also the SYN_CAP_* macros */ -static int synaptics_capability(struct psmouse *psmouse, unsigned long int *capability) +static int synaptics_capability(struct psmouse *psmouse, unsigned long int *capability, unsigned long int *ext_cap) { unsigned char cap[3]; if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) return -1; *capability = (cap[0]<<16) | (cap[1]<<8) | cap[2]; - if (SYN_CAP_VALID(*capability)) - return 0; - return -1; + *ext_cap = 0; + if (!SYN_CAP_VALID(*capability)) + return -1; + + if (SYN_EXT_CAP_REQUESTS(*capability)) { + if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { + printk(KERN_ERR "Synaptics claims to have extended capabilities," + " but I'm not able to read them."); + } else + *ext_cap = (cap[0]<<16) | (cap[1]<<8) | cap[2]; + } + return 0; } /* @@ -134,19 +147,11 @@ static int synaptics_identify(struct psmouse *psmouse, unsigned long int *ident) return -1; } -static int synaptics_enable_device(struct psmouse *psmouse) -{ - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE)) - return -1; - return 0; -} - static void print_ident(struct synaptics_data *priv) { printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity)); printk(KERN_INFO " Firmware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity)); - if (SYN_MODEL_ROT180(priv->model_id)) printk(KERN_INFO " 180 degree mounted touchpad\n"); if (SYN_MODEL_PORTRAIT(priv->model_id)) @@ -159,12 +164,17 @@ static void print_ident(struct synaptics_data *priv) if (SYN_CAP_EXTENDED(priv->capabilities)) { printk(KERN_INFO " Touchpad has extended capability bits\n"); - if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) + printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n", + (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))); + else if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) printk(KERN_INFO " -> four buttons\n"); if (SYN_CAP_MULTIFINGER(priv->capabilities)) printk(KERN_INFO " -> multifinger detection\n"); if (SYN_CAP_PALMDETECT(priv->capabilities)) printk(KERN_INFO " -> palm detection\n"); + if (SYN_CAP_PASS_THROUGH(priv->capabilities)) + printk(KERN_INFO " -> pass-through port\n"); } } @@ -172,6 +182,7 @@ static int query_hardware(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; int retries = 0; + int mode; while ((retries++ < 3) && synaptics_reset(psmouse)) printk(KERN_ERR "synaptics reset failed\n"); @@ -180,17 +191,107 @@ static int query_hardware(struct psmouse *psmouse) return -1; if (synaptics_model_id(psmouse, &priv->model_id)) return -1; - if (synaptics_capability(psmouse, &priv->capabilities)) + if (synaptics_capability(psmouse, &priv->capabilities, &priv->ext_cap)) return -1; - if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE | - SYN_BIT_HIGH_RATE | - SYN_BIT_DISABLE_GESTURE | - SYN_BIT_W_MODE))) + + mode = SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE; + if (SYN_ID_MAJOR(priv->identity) >= 4) + mode |= SYN_BIT_DISABLE_GESTURE; + if (SYN_CAP_EXTENDED(priv->capabilities)) + mode |= SYN_BIT_W_MODE; + if (synaptics_set_mode(psmouse, mode)) return -1; - synaptics_enable_device(psmouse); + return 0; +} - print_ident(priv); +/***************************************************************************** + * Synaptics pass-through PS/2 port support + ****************************************************************************/ +static int synaptics_pt_open(struct serio *port) +{ + return 0; +} + +static void synaptics_pt_close(struct serio *port) +{ +} + +static int synaptics_pt_write(struct serio *port, unsigned char c) +{ + struct psmouse *parent = port->driver; + char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ + + if (synaptics_special_cmd(parent, c)) + return -1; + if (psmouse_command(parent, &rate_param, PSMOUSE_CMD_SETRATE)) + return -1; + return 0; +} + +static inline int synaptics_is_pt_packet(unsigned char *buf) +{ + return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; +} + +static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) +{ + struct psmouse *child = ptport->private; + + if (child) { + if (child->state == PSMOUSE_ACTIVATED) { + serio_interrupt(ptport, packet[1], 0, NULL); + serio_interrupt(ptport, packet[4], 0, NULL); + serio_interrupt(ptport, packet[5], 0, NULL); + if (child->type >= PSMOUSE_GENPS) + serio_interrupt(ptport, packet[2], 0, NULL); + } else if (child->state != PSMOUSE_IGNORE) { + serio_interrupt(ptport, packet[1], 0, NULL); + } + } +} + +int synaptics_pt_init(struct psmouse *psmouse) +{ + struct synaptics_data *priv = psmouse->private; + struct serio *port; + struct psmouse *child; + + if (psmouse->type != PSMOUSE_SYNAPTICS) + return -1; + if (!SYN_CAP_EXTENDED(priv->capabilities)) + return -1; + if (!SYN_CAP_PASS_THROUGH(priv->capabilities)) + return -1; + + priv->ptport = port = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!port) { + printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n"); + return -1; + } + + memset(port, 0, sizeof(struct serio)); + port->type = SERIO_PS_PSTHRU; + port->name = "Synaptics pass-through"; + port->phys = "synaptics-pt/serio0"; + port->write = synaptics_pt_write; + port->open = synaptics_pt_open; + port->close = synaptics_pt_close; + port->driver = psmouse; + + printk(KERN_INFO "serio: %s port at %s\n", port->name, psmouse->phys); + serio_register_slave_port(port); + + /* adjust the touchpad to child's choice of protocol */ + child = port->private; + if (child && child->type >= PSMOUSE_GENPS) { + if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE | + SYN_BIT_HIGH_RATE | + SYN_BIT_DISABLE_GESTURE | + SYN_BIT_FOUR_BYTE_CLIENT | + SYN_BIT_W_MODE))) + printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n"); + } return 0; } @@ -213,18 +314,23 @@ int synaptics_init(struct psmouse *psmouse) { struct synaptics_data *priv; +#ifndef CONFIG_MOUSE_PS2_SYNAPTICS + return -1; +#endif psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL); if (!priv) return -1; memset(priv, 0, sizeof(struct synaptics_data)); - priv->inSync = 1; + priv->out_of_sync = 0; if (query_hardware(psmouse)) { printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n"); goto init_fail; } + print_ident(priv); + /* * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, * which says that they should be valid regardless of the actual size of @@ -243,7 +349,24 @@ int synaptics_init(struct psmouse *psmouse) set_bit(BTN_RIGHT, psmouse->dev.keybit); set_bit(BTN_FORWARD, psmouse->dev.keybit); set_bit(BTN_BACK, psmouse->dev.keybit); - + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) + switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { + default: + printk(KERN_ERR "This touchpad reports more than 8 multi-buttons, don't know how to handle.\n"); + case 8: + set_bit(BTN_7, psmouse->dev.keybit); + set_bit(BTN_6, psmouse->dev.keybit); + case 6: + set_bit(BTN_5, psmouse->dev.keybit); + set_bit(BTN_4, psmouse->dev.keybit); + case 4: + set_bit(BTN_3, psmouse->dev.keybit); + set_bit(BTN_2, psmouse->dev.keybit); + case 2: + set_bit(BTN_1, psmouse->dev.keybit); + set_bit(BTN_0, psmouse->dev.keybit); + break; + } clear_bit(EV_REL, psmouse->dev.evbit); clear_bit(REL_X, psmouse->dev.relbit); clear_bit(REL_Y, psmouse->dev.relbit); @@ -259,45 +382,85 @@ void synaptics_disconnect(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; - /* Restore touchpad to power on default state */ - synaptics_set_mode(psmouse, 0); - - kfree(priv); + if (psmouse->type == PSMOUSE_SYNAPTICS && priv) { + synaptics_set_mode(psmouse, 0); + if (priv->ptport) { + serio_unregister_slave_port(priv->ptport); + kfree(priv->ptport); + } + kfree(priv); + } } /***************************************************************************** * Functions to interpret the absolute mode packets ****************************************************************************/ -static void synaptics_parse_hw_state(struct synaptics_data *priv, struct synaptics_hw_state *hw) +static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) { - unsigned char *buf = priv->proto_buf; - - hw->x = (((buf[3] & 0x10) << 8) | - ((buf[1] & 0x0f) << 8) | - buf[4]); - hw->y = (((buf[3] & 0x20) << 7) | - ((buf[1] & 0xf0) << 4) | - buf[5]); - - hw->z = buf[2]; - hw->w = (((buf[0] & 0x30) >> 2) | - ((buf[0] & 0x04) >> 1) | - ((buf[3] & 0x04) >> 2)); - - hw->left = (buf[0] & 0x01) ? 1 : 0; - hw->right = (buf[0] & 0x2) ? 1 : 0; hw->up = 0; hw->down = 0; + hw->b0 = 0; + hw->b1 = 0; + hw->b2 = 0; + hw->b3 = 0; + hw->b4 = 0; + hw->b5 = 0; + hw->b6 = 0; + hw->b7 = 0; + + if (SYN_MODEL_NEWABS(priv->model_id)) { + hw->x = (((buf[3] & 0x10) << 8) | + ((buf[1] & 0x0f) << 8) | + buf[4]); + hw->y = (((buf[3] & 0x20) << 7) | + ((buf[1] & 0xf0) << 4) | + buf[5]); + + hw->z = buf[2]; + hw->w = (((buf[0] & 0x30) >> 2) | + ((buf[0] & 0x04) >> 1) | + ((buf[3] & 0x04) >> 2)); + + hw->left = (buf[0] & 0x01) ? 1 : 0; + hw->right = (buf[0] & 0x02) ? 1 : 0; + if (SYN_CAP_EXTENDED(priv->capabilities) && + (SYN_CAP_FOUR_BUTTON(priv->capabilities))) { + hw->up = ((buf[3] & 0x01)) ? 1 : 0; + if (hw->left) + hw->up = !hw->up; + hw->down = ((buf[3] & 0x02)) ? 1 : 0; + if (hw->right) + hw->down = !hw->down; + } + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && + ((buf[3] & 2) ? !hw->right : hw->right)) { + switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { + default: + ; /* we did comment while initialising... */ + case 8: + hw->b7 = ((buf[5] & 0x08)) ? 1 : 0; + hw->b6 = ((buf[4] & 0x08)) ? 1 : 0; + case 6: + hw->b5 = ((buf[5] & 0x04)) ? 1 : 0; + hw->b4 = ((buf[4] & 0x04)) ? 1 : 0; + case 4: + hw->b3 = ((buf[5] & 0x02)) ? 1 : 0; + hw->b2 = ((buf[4] & 0x02)) ? 1 : 0; + case 2: + hw->b1 = ((buf[5] & 0x01)) ? 1 : 0; + hw->b0 = ((buf[4] & 0x01)) ? 1 : 0; + } + } + } else { + hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); + hw->y = (((buf[4] & 0x1f) << 8) | buf[5]); + + hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F)); + hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1)); - if (SYN_CAP_EXTENDED(priv->capabilities) && - (SYN_CAP_FOUR_BUTTON(priv->capabilities))) { - hw->up = ((buf[3] & 0x01)) ? 1 : 0; - if (hw->left) - hw->up = !hw->up; - hw->down = ((buf[3] & 0x02)) ? 1 : 0; - if (hw->right) - hw->down = !hw->down; + hw->left = (buf[0] & 0x01) ? 1 : 0; + hw->right = (buf[0] & 0x02) ? 1 : 0; } } @@ -310,7 +473,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) struct synaptics_data *priv = psmouse->private; struct synaptics_hw_state hw; - synaptics_parse_hw_state(priv, &hw); + synaptics_parse_hw_state(psmouse->packet, priv, &hw); if (hw.z > 0) { int w_ok = 0; @@ -350,7 +513,24 @@ static void synaptics_process_packet(struct psmouse *psmouse) input_report_key(dev, BTN_RIGHT, hw.right); input_report_key(dev, BTN_FORWARD, hw.up); input_report_key(dev, BTN_BACK, hw.down); - + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) + switch(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { + default: + ; /* we did comment while initialising... */ + case 8: + input_report_key(dev, BTN_7, hw.b7); + input_report_key(dev, BTN_6, hw.b6); + case 6: + input_report_key(dev, BTN_5, hw.b5); + input_report_key(dev, BTN_4, hw.b4); + case 4: + input_report_key(dev, BTN_3, hw.b3); + input_report_key(dev, BTN_2, hw.b2); + case 2: + input_report_key(dev, BTN_1, hw.b1); + input_report_key(dev, BTN_0, hw.b0); + break; + } input_sync(dev); } @@ -358,35 +538,59 @@ void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) { struct input_dev *dev = &psmouse->dev; struct synaptics_data *priv = psmouse->private; - unsigned char *pBuf = priv->proto_buf; - unsigned char u = psmouse->packet[0]; + unsigned char data = psmouse->packet[psmouse->pktcnt - 1]; + int newabs = SYN_MODEL_NEWABS(priv->model_id); input_regs(dev, regs); - pBuf[priv->proto_buf_tail++] = u; - - /* check first byte */ - if ((priv->proto_buf_tail == 1) && ((u & 0xC8) != 0x80)) { - priv->inSync = 0; - priv->proto_buf_tail = 0; - printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n"); - return; - } + switch (psmouse->pktcnt) { + case 1: + if (newabs ? ((data & 0xC8) != 0x80) : ((data & 0xC0) != 0xC0)) { + printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n"); + goto bad_sync; + } + break; + case 2: + if (!newabs && ((data & 0x60) != 0x00)) { + printk(KERN_WARNING "Synaptics driver lost sync at 2nd byte\n"); + goto bad_sync; + } + break; + case 4: + if (newabs ? ((data & 0xC8) != 0xC0) : ((data & 0xC0) != 0x80)) { + printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n"); + goto bad_sync; + } + break; + case 5: + if (!newabs && ((data & 0x60) != 0x00)) { + printk(KERN_WARNING "Synaptics driver lost sync at 5th byte\n"); + goto bad_sync; + } + break; + default: + if (psmouse->pktcnt >= 6) { /* Full packet received */ + if (priv->out_of_sync) { + priv->out_of_sync = 0; + printk(KERN_NOTICE "Synaptics driver resynced.\n"); + } - /* check 4th byte */ - if ((priv->proto_buf_tail == 4) && ((u & 0xc8) != 0xc0)) { - priv->inSync = 0; - priv->proto_buf_tail = 0; - printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n"); - return; - } + if (priv->ptport && synaptics_is_pt_packet(psmouse->packet)) + synaptics_pass_pt_packet(priv->ptport, psmouse->packet); + else + synaptics_process_packet(psmouse); - if (priv->proto_buf_tail >= 6) { /* Full packet received */ - if (!priv->inSync) { - priv->inSync = 1; - printk(KERN_NOTICE "Synaptics driver resynced.\n"); + psmouse->pktcnt = 0; } - synaptics_process_packet(psmouse); - priv->proto_buf_tail = 0; + break; + } + return; + + bad_sync: + priv->out_of_sync++; + psmouse->pktcnt = 0; + if (psmouse_resetafter > 0 && priv->out_of_sync == psmouse_resetafter) { + psmouse->state = PSMOUSE_IGNORE; + serio_rescan(psmouse->serio); } } diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 6e3e029a3bdd..4dad98abd54e 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -12,6 +12,7 @@ extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs); extern int synaptics_init(struct psmouse *psmouse); +extern int synaptics_pt_init(struct psmouse *psmouse); extern void synaptics_disconnect(struct psmouse *psmouse); /* synaptics queries */ @@ -22,12 +23,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse); #define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06 #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 #define SYN_QUE_RESOLUTION 0x08 +#define SYN_QUE_EXT_CAPAB 0x09 /* synatics modes */ #define SYN_BIT_ABSOLUTE_MODE (1 << 7) #define SYN_BIT_HIGH_RATE (1 << 6) #define SYN_BIT_SLEEP_MODE (1 << 3) #define SYN_BIT_DISABLE_GESTURE (1 << 2) +#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1) #define SYN_BIT_W_MODE (1 << 0) /* synaptics model ID bits */ @@ -42,11 +45,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse); /* synaptics capability bits */ #define SYN_CAP_EXTENDED(c) ((c) & (1 << 23)) +#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7)) #define SYN_CAP_SLEEP(c) ((c) & (1 << 4)) #define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3)) #define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) #define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) +#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1) +#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) /* synaptics modes query bits */ #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) @@ -62,6 +68,10 @@ extern void synaptics_disconnect(struct psmouse *psmouse); #define SYN_ID_MINOR(i) (((i) >> 16) & 0xff) #define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47) +/* synaptics special commands */ +#define SYN_PS_SET_MODE2 0x14 +#define SYN_PS_CLIENT_CMD 0x28 + /* * A structure to describe the state of the touchpad hardware (buttons and pad) */ @@ -75,21 +85,28 @@ struct synaptics_hw_state { int right; int up; int down; + int b0; + int b1; + int b2; + int b3; + int b4; + int b5; + int b6; + int b7; }; struct synaptics_data { /* Data read from the touchpad */ unsigned long int model_id; /* Model-ID */ unsigned long int capabilities; /* Capabilities */ + unsigned long int ext_cap; /* Extended Capabilities */ unsigned long int identity; /* Identification */ /* Data for normal processing */ - unsigned char proto_buf[6]; /* Buffer for Packet */ - unsigned char last_byte; /* last received byte */ - int inSync; /* Packets in sync */ - int proto_buf_tail; - + unsigned int out_of_sync; /* # of packets out of sync */ int old_w; /* Previous w value */ + + struct serio *ptport; /* pass-through port */ }; #endif /* _SYNAPTICS_H */ diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 78c51d96dea6..35fc0b2827d3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -49,7 +49,9 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(serio_register_port); +EXPORT_SYMBOL(serio_register_slave_port); EXPORT_SYMBOL(serio_unregister_port); +EXPORT_SYMBOL(serio_unregister_slave_port); EXPORT_SYMBOL(serio_register_device); EXPORT_SYMBOL(serio_unregister_device); EXPORT_SYMBOL(serio_open); @@ -166,6 +168,17 @@ void serio_register_port(struct serio *serio) up(&serio_sem); } +/* + * Same as serio_register_port but does not try to acquire serio_sem. + * Should be used when registering a serio from other input device's + * connect() function. + */ +void serio_register_slave_port(struct serio *serio) +{ + list_add_tail(&serio->node, &serio_list); + serio_find_dev(serio); +} + void serio_unregister_port(struct serio *serio) { down(&serio_sem); @@ -175,6 +188,18 @@ void serio_unregister_port(struct serio *serio) up(&serio_sem); } +/* + * Same as serio_unregister_port but does not try to acquire serio_sem. + * Should be used when unregistering a serio from other input device's + * disconnect() function. + */ +void serio_unregister_slave_port(struct serio *serio) +{ + list_del_init(&serio->node); + if (serio->dev && serio->dev->disconnect) + serio->dev->disconnect(serio); +} + void serio_register_device(struct serio_dev *dev) { struct serio *serio; diff --git a/include/linux/serio.h b/include/linux/serio.h index f1c67ff70f2a..66fdaf9b1be5 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -65,7 +65,9 @@ void serio_rescan(struct serio *serio); irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs); void serio_register_port(struct serio *serio); +void serio_register_slave_port(struct serio *serio); void serio_unregister_port(struct serio *serio); +void serio_unregister_slave_port(struct serio *serio); void serio_register_device(struct serio_dev *dev); void serio_unregister_device(struct serio_dev *dev); @@ -104,6 +106,7 @@ static __inline__ void serio_cleanup(struct serio *serio) #define SERIO_RS232 0x02000000UL #define SERIO_HIL_MLC 0x03000000UL #define SERIO_PC9800 0x04000000UL +#define SERIO_PS_PSTHRU 0x05000000UL #define SERIO_PROTO 0xFFUL #define SERIO_MSC 0x01 -- cgit v1.2.3 From 5b48a707bca11ec6bf32875f91d92ccbb25beaae Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Thu, 18 Sep 2003 11:22:06 -0700 Subject: input.h, keyboard.c, evdev.c: Fix the INPUT_KEYCODE macro and its usage. --- drivers/char/keyboard.c | 2 +- drivers/input/evdev.c | 12 +++++------- include/linux/input.h | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 26c5df39f937..32347f8c9369 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -205,7 +205,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode) INPUT_KEYCODE(dev, scancode) = keycode; for (i = 0; i < dev->keycodemax; i++) - if(INPUT_KEYCODE(dev, scancode) == oldkey) + if(keycode == oldkey) break; if (i == dev->keycodemax) clear_bit(oldkey, dev->keybit); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 10a13ac90c48..ca56ac39e2b8 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -208,7 +208,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, struct evdev *evdev = list->evdev; struct input_dev *dev = evdev->handle.dev; struct input_absinfo abs; - int i, t, u; + int i, t, u, v; if (!evdev->exist) return -ENODEV; @@ -239,14 +239,12 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case EVIOCSKEYCODE: if (get_user(t, ((int *) arg) + 0)) return -EFAULT; if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL; + if (get_user(v, ((int *) arg) + 1)) return -EFAULT; u = INPUT_KEYCODE(dev, t); - if (get_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT; - - for (i = 0; i < dev->keycodemax; i++) - if(INPUT_KEYCODE(dev, t) == u) break; + INPUT_KEYCODE(dev, t) = v; + for (i = 0; i < dev->keycodemax; i++) if (v == u) break; if (i == dev->keycodemax) clear_bit(u, dev->keybit); - set_bit(INPUT_KEYCODE(dev, t), dev->keybit); - + set_bit(v, dev->keybit); return 0; case EVIOCSFF: diff --git a/include/linux/input.h b/include/linux/input.h index da49f7ee0f18..c98e6fc575fe 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -751,7 +751,7 @@ struct ff_effect { #define LONG(x) ((x)/BITS_PER_LONG) #define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \ - ((dev->keycodesize == 1) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode]))) + ((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode]))) #define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0) -- cgit v1.2.3 From 972b4a74dcacecc9ae50fa46daa10d4efcaef4d1 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 20 Sep 2003 20:20:02 -0700 Subject: [PATCH] Move EISA_bus When I change the setting of CONFIG_EISA, everything rebuilds. This is because EISA_bus is declared in which is implicitly included by just about everything. This is a silly place to declare it, so this patch moves it to include/linux/eisa.h. While I'm at it, I also move the variable definition to drivers/eisa/eisa-bus.c. The rest of this patch is fixing up the fallout from having to include if you use EISA_bus. --- arch/alpha/Kconfig | 3 +++ arch/i386/kernel/i386_ksyms.c | 3 --- arch/i386/kernel/traps.c | 5 +---- arch/mips/jazz/setup.c | 1 + arch/mips/kernel/mips_ksyms.c | 4 ---- arch/mips/kernel/setup.c | 9 --------- arch/mips/sgi-ip22/ip22-eisa.c | 1 + arch/mips/sni/setup.c | 1 + arch/parisc/kernel/irq.c | 3 ++- arch/parisc/kernel/parisc_ksyms.c | 3 --- arch/parisc/kernel/pci.c | 1 + arch/parisc/kernel/setup.c | 4 ---- drivers/eisa/eisa-bus.c | 5 +++++ drivers/net/ac3200.c | 1 + drivers/net/dgrs.c | 1 + drivers/net/es3210.c | 1 + drivers/net/hp100.c | 1 + drivers/net/lne390.c | 1 + drivers/net/ne3210.c | 1 + drivers/net/smc-ultra32.c | 1 + drivers/net/tlan.c | 1 + include/asm-alpha/processor.h | 1 - include/asm-arm/processor.h | 1 - include/asm-arm26/processor.h | 1 - include/asm-h8300/processor.h | 1 - include/asm-i386/processor.h | 5 ----- include/asm-ia64/processor.h | 1 - include/asm-m68k/processor.h | 1 - include/asm-m68knommu/processor.h | 1 - include/asm-mips/processor.h | 6 ------ include/asm-parisc/processor.h | 6 ------ include/asm-ppc/processor.h | 1 - include/asm-ppc64/processor.h | 2 -- include/asm-sh/processor.h | 2 -- include/asm-sparc/processor.h | 1 - include/asm-sparc64/processor.h | 1 - include/asm-v850/processor.h | 2 -- include/asm-x86_64/processor.h | 1 - include/linux/eisa.h | 13 +++++++++++++ 39 files changed, 36 insertions(+), 62 deletions(-) (limited to 'include/linux') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index da6dd08713b7..28b21380b8ea 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -484,6 +484,9 @@ config EISA Otherwise, say N. +config EISA_ALWAYS + def_bool EISA + config SMP bool "Symmetric multi-processing support" depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 38b72b42f877..4b770c5dfe8b 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -63,9 +63,6 @@ extern unsigned long get_cmos_time(void); /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); -#ifdef CONFIG_EISA -EXPORT_SYMBOL(EISA_bus); -#endif EXPORT_SYMBOL(MCA_bus); #ifdef CONFIG_DISCONTIGMEM EXPORT_SYMBOL(node_data); diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index a22eb78ae0b0..fa0935e3510f 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -28,6 +28,7 @@ #ifdef CONFIG_EISA #include +#include #endif #ifdef CONFIG_MCA @@ -832,10 +833,6 @@ static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) } -#ifdef CONFIG_EISA -int EISA_bus; -#endif - void __init trap_init(void) { #ifdef CONFIG_EISA diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c index aadaa904b0da..6af2f79944a9 100644 --- a/arch/mips/jazz/setup.c +++ b/arch/mips/jazz/setup.c @@ -9,6 +9,7 @@ * Copyright (C) 2001 MIPS Technologies, Inc. */ #include +#include #include #include #include diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index baf44da69264..6bdf758af0e8 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -43,10 +43,6 @@ extern long __strnlen_user_asm(const char *s); EXPORT_SYMBOL(mips_machtype); -#ifdef CONFIG_EISA -EXPORT_SYMBOL(EISA_bus); -#endif - /* * String functions */ diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index cdbaf4dd8c1f..0960259c6062 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -44,15 +44,6 @@ struct cpuinfo_mips cpu_data[NR_CPUS]; struct screen_info screen_info; #endif -/* - * Set if box has EISA slots. - */ -#ifdef CONFIG_EISA -int EISA_bus; - -EXPORT_SYMBOL(EISA_bus); -#endif - #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) extern struct fd_ops no_fd_ops; struct fd_ops *fd_ops; diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c index 68ccb2f64bfd..0ab4abf65d58 100644 --- a/arch/mips/sgi-ip22/ip22-eisa.c +++ b/arch/mips/sgi-ip22/ip22-eisa.c @@ -20,6 +20,7 @@ */ #include +#include #include #include #include diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index 4acde68fe94b..2f96ca61c1ed 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c @@ -8,6 +8,7 @@ * Copyright (C) 1996, 1997, 1998, 2000, 2003 by Ralf Baechle */ #include +#include #include #include #include diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 9d3a97a5b0bb..eafb849da3a0 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -22,7 +22,7 @@ */ #include #include -#include +#include #include #include #include @@ -39,6 +39,7 @@ #include #include +#include #undef DEBUG_IRQ #undef PARISC_IRQ_CR16_COUNTS diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 4a16af09be6d..f6d87e4d7575 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -42,9 +42,6 @@ EXPORT_SYMBOL(probe_irq_mask); #include EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(boot_cpu_data); -#ifdef CONFIG_EISA -EXPORT_SYMBOL(EISA_bus); -#endif #include EXPORT_SYMBOL(pm_power_off); diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 1e299167edfc..189a6ae02bb9 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -10,6 +10,7 @@ * Copyright (C) 1999-2001 Grant Grundler */ #include +#include #include #include #include diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 5dde472c50fc..42f74c99072b 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -52,10 +52,6 @@ char command_line[COMMAND_LINE_SIZE]; struct proc_dir_entry * proc_runway_root = NULL; struct proc_dir_entry * proc_gsc_root = NULL; -#ifdef CONFIG_EISA -int EISA_bus; /* This has to go somewhere in architecture specific code. */ -#endif - void __init setup_cmdline(char **cmdline_p) { extern unsigned int boot_args[]; diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 6f1b766fddcf..055872a85889 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -427,6 +427,11 @@ module_param(disable_dev, intarray, 0444); postcore_initcall (eisa_init); +#ifndef CONFIG_EISA_ALWAYS +int EISA_bus; +EXPORT_SYMBOL(EISA_bus); +#endif + EXPORT_SYMBOL (eisa_bus_type); EXPORT_SYMBOL (eisa_driver_register); EXPORT_SYMBOL (eisa_driver_unregister); diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index 5fc6d725e29c..8cba7e2ce149 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -25,6 +25,7 @@ static const char version[] = "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; #include +#include #include #include #include diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 21fd87cd4999..84652b61a8a4 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -84,6 +84,7 @@ */ #include +#include #include #include #include diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c index 96952230b132..a46ee65e173a 100644 --- a/drivers/net/es3210.c +++ b/drivers/net/es3210.c @@ -49,6 +49,7 @@ static const char version[] = "es3210.c: Driver revision v0.03, 14/09/96\n"; #include +#include #include #include #include diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 38c802e16418..3e7facd034d0 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -104,6 +104,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c index ed77dcfeab1f..16e41a1438a2 100644 --- a/drivers/net/lne390.c +++ b/drivers/net/lne390.c @@ -35,6 +35,7 @@ static const char *version = "lne390.c: Driver revision v0.99.1, 01/09/2000\n"; #include +#include #include #include #include diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index 16fc263dbc02..201aa1f59c04 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c @@ -29,6 +29,7 @@ static const char *version = "ne3210.c: Driver revision v0.03, 30/09/98\n"; #include +#include #include #include #include diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c index 5781d29f2793..aac76a58342d 100644 --- a/drivers/net/smc-ultra32.c +++ b/drivers/net/smc-ultra32.c @@ -47,6 +47,7 @@ static const char *version = "smc-ultra32.c: 06/97 v1.00\n"; #include +#include #include #include #include diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index c5b6999712fb..499b60d0bfd4 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -169,6 +169,7 @@ #include #include #include +#include #include #include #include diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h index 830d6f73bea1..fe03e7309686 100644 --- a/include/asm-alpha/processor.h +++ b/include/asm-alpha/processor.h @@ -29,7 +29,6 @@ /* * Bus types */ -#define EISA_bus 1 #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 31c888ba601c..3890d6038355 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h @@ -19,7 +19,6 @@ #ifdef __KERNEL__ -#define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro diff --git a/include/asm-arm26/processor.h b/include/asm-arm26/processor.h index 8f9f6ad53474..9e0d90433795 100644 --- a/include/asm-arm26/processor.h +++ b/include/asm-arm26/processor.h @@ -20,7 +20,6 @@ #ifdef __KERNEL__ -#define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro diff --git a/include/asm-h8300/processor.h b/include/asm-h8300/processor.h index 819c9b34e152..a0bc63dd8b2b 100644 --- a/include/asm-h8300/processor.h +++ b/include/asm-h8300/processor.h @@ -48,7 +48,6 @@ extern inline void wrusp(unsigned long usp) { /* * Bus types */ -#define EISA_bus 0 #define MCA_bus 0 struct thread_struct { diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 9eb3f78ffd51..7a65d14b1dca 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -260,11 +260,6 @@ static inline void clear_in_cr4 (unsigned long mask) * Bus types (default is ISA, but people can check others with these..) * pc98 indicates PC98 systems (CBUS) */ -#ifdef CONFIG_EISA -extern int EISA_bus; -#else -#define EISA_bus (0) -#endif extern int MCA_bus; #ifdef CONFIG_X86_PC9800 #define pc98 1 diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index c6b4af2b3643..ed83487c5dc1 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -56,7 +56,6 @@ /* * Bus types */ -#define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h index fb463bda10de..7516e2945ecd 100644 --- a/include/asm-m68k/processor.h +++ b/include/asm-m68k/processor.h @@ -56,7 +56,6 @@ extern inline void wrusp(unsigned long usp) { /* * Bus types */ -#define EISA_bus 0 #define MCA_bus 0 struct task_work { diff --git a/include/asm-m68knommu/processor.h b/include/asm-m68knommu/processor.h index 547a96604b46..736e3192f464 100644 --- a/include/asm-m68knommu/processor.h +++ b/include/asm-m68knommu/processor.h @@ -58,7 +58,6 @@ extern inline void wrusp(unsigned long usp) /* * Bus types */ -#define EISA_bus 0 #define MCA_bus 0 /* diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h index c08e0bf6e76c..33e8cc7c721d 100644 --- a/include/asm-mips/processor.h +++ b/include/asm-mips/processor.h @@ -135,12 +135,6 @@ extern unsigned int vced_count, vcei_count; /* * Bus types (default is ISA, but people can check others with these..) */ -#ifdef CONFIG_EISA -extern int EISA_bus; -#else -#define EISA_bus (0) -#endif - #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h index ded1c4904510..4779a6efeb91 100644 --- a/include/asm-parisc/processor.h +++ b/include/asm-parisc/processor.h @@ -101,12 +101,6 @@ extern struct cpuinfo_parisc cpu_data[NR_CPUS]; #define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF) -#ifdef CONFIG_EISA -extern int EISA_bus; -#else -#define EISA_bus 0 -#endif - #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index 3a893e9d6b47..2a5437042ad8 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -803,7 +803,6 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); /* * Bus types */ -#define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h index 7d0246bd87cb..f878c5b05d42 100644 --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h @@ -612,8 +612,6 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); /* * Bus types */ -#define EISA_bus 0 -#define EISA_bus__is_a_macro /* for versions in ksyms.c */ #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index 99661c8d8cb0..1308d81838fd 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -169,8 +169,6 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* * Bus types */ -#define EISA_bus 0 -#define EISA_bus__is_a_macro /* for versions in ksyms.c */ #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index c2b7125aa005..3f3bf3ca874c 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -27,7 +27,6 @@ /* * Bus types */ -#define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h index bec2ef59d771..416fad2ef1b1 100644 --- a/include/asm-sparc64/processor.h +++ b/include/asm-sparc64/processor.h @@ -22,7 +22,6 @@ #include /* Bus types */ -#define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h index 025202b4df7e..b28582ecce02 100644 --- a/include/asm-v850/processor.h +++ b/include/asm-v850/processor.h @@ -52,8 +52,6 @@ /* * Bus types */ -#define EISA_bus 0 -#define EISA_bus__is_a_macro /* for versions in ksyms.c */ #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 7b4430ce23a0..805b7c03dbbc 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -160,7 +160,6 @@ static inline void clear_in_cr4 (unsigned long mask) /* * Bus types */ -#define EISA_bus 0 #define MCA_bus 0 #define MCA_bus__is_a_macro diff --git a/include/linux/eisa.h b/include/linux/eisa.h index 2ef648847879..dc76d57b10d0 100644 --- a/include/linux/eisa.h +++ b/include/linux/eisa.h @@ -1,6 +1,19 @@ #ifndef _LINUX_EISA_H #define _LINUX_EISA_H +#include +#include + +#ifdef CONFIG_EISA +# ifdef CONFIG_EISA_ALWAYS +# define EISA_bus 1 +# else + extern int EISA_bus; +# endif +#else +# define EISA_bus 0 +#endif + #define EISA_SIG_LEN 8 #define EISA_MAX_SLOTS 8 -- cgit v1.2.3 From 5fc4d8394c3192ba18c19f82f629b71e7e68cc0d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:36:53 -0700 Subject: [PATCH] ECC support From: "Nakajima, Jun" Split the increasingly messy compiler.h file into per-compiler files and also add support for non-gcc compilers. With the current implementation: include/linux/compiler.h defines the compiler-dependent abstractions which can be overwritten by per-compiler definitions. include/linux/compiler-gcc.h contains the common definitions for all gcc versions. include/linux/compiler-gcc[2,3,+].h contains gcc major version specific definitions. include/linux/compiler-intel.h contains intel compiler specific definitions." --- include/linux/compiler-gcc+.h | 14 ++++++++ include/linux/compiler-gcc.h | 17 ++++++++++ include/linux/compiler-gcc2.h | 23 ++++++++++++++ include/linux/compiler-gcc3.h | 22 +++++++++++++ include/linux/compiler-intel.h | 24 ++++++++++++++ include/linux/compiler.h | 72 +++++++++++++++++++++++------------------- include/linux/kernel.h | 4 --- 7 files changed, 139 insertions(+), 37 deletions(-) create mode 100644 include/linux/compiler-gcc+.h create mode 100644 include/linux/compiler-gcc.h create mode 100644 include/linux/compiler-gcc2.h create mode 100644 include/linux/compiler-gcc3.h create mode 100644 include/linux/compiler-intel.h (limited to 'include/linux') diff --git a/include/linux/compiler-gcc+.h b/include/linux/compiler-gcc+.h new file mode 100644 index 000000000000..f6ae9e76b825 --- /dev/null +++ b/include/linux/compiler-gcc+.h @@ -0,0 +1,14 @@ +/* Never include this file directly. Include instead. */ + +/* + * These definitions are for Ueber-GCC: always newer than the latest + * version and hence sporting everything plus a kitchen-sink. + */ +#include + +#define inline __inline__ __attribute__((always_inline)) +#define __inline__ __inline__ __attribute__((always_inline)) +#define __inline __inline__ __attribute__((always_inline)) +#define __deprecated __attribute__((deprecated)) +#define __attribute_used__ __attribute__((__used__)) +#define __attribute_pure__ __attribute__((pure)) diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h new file mode 100644 index 000000000000..152734055403 --- /dev/null +++ b/include/linux/compiler-gcc.h @@ -0,0 +1,17 @@ +/* Never include this file directly. Include instead. */ + +/* + * Common definitions for all gcc versions go here. + */ + + +/* Optimization barrier */ +/* The "volatile" is due to gcc bugs */ +#define barrier() __asm__ __volatile__("": : :"memory") + +/* This macro obfuscates arithmetic on a variable address so that gcc + shouldn't recognize the original var, and make assumptions about it */ +#define RELOC_HIDE(ptr, off) \ + ({ unsigned long __ptr; \ + __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \ + (typeof(ptr)) (__ptr + (off)); }) diff --git a/include/linux/compiler-gcc2.h b/include/linux/compiler-gcc2.h new file mode 100644 index 000000000000..6f4f9d526abe --- /dev/null +++ b/include/linux/compiler-gcc2.h @@ -0,0 +1,23 @@ +/* Never include this file directly. Include instead. */ + +/* These definitions are for GCC v2.x. */ + +/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented + a mechanism by which the user can annotate likely branch directions and + expect the blocks to be reordered appropriately. Define __builtin_expect + to nothing for earlier compilers. */ +#include + +#if __GNUC_MINOR__ < 96 +# define __builtin_expect(x, expected_value) (x) +#endif + +#define __attribute_used__ __attribute__((__unused__)) + +/* + * The attribute `pure' is not implemented in GCC versions earlier + * than 2.96. + */ +#if __GNUC_MINOR__ >= 96 +# define __attribute_pure__ __attribute__((pure)) +#endif diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h new file mode 100644 index 000000000000..4eac3db89fda --- /dev/null +++ b/include/linux/compiler-gcc3.h @@ -0,0 +1,22 @@ +/* Never include this file directly. Include instead. */ + +/* These definitions are for GCC v3.x. */ +#include + +#if __GNUC_MINOR__ >= 1 +# define inline __inline__ __attribute__((always_inline)) +# define __inline__ __inline__ __attribute__((always_inline)) +# define __inline __inline__ __attribute__((always_inline)) +#endif + +#if __GNUC_MINOR__ > 0 +# define __deprecated __attribute__((deprecated)) +#endif + +#if __GNUC_MINOR__ >= 3 +# define __attribute_used__ __attribute__((__used__)) +#else +# define __attribute_used__ __attribute__((__unused__)) +#endif + +#define __attribute_pure__ __attribute__((pure)) diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h new file mode 100644 index 000000000000..1d1c3ceaff4e --- /dev/null +++ b/include/linux/compiler-intel.h @@ -0,0 +1,24 @@ +/* Never include this file directly. Include instead. */ + +#ifdef __ECC + +/* Some compiler specific definitions are overwritten here + * for Intel ECC compiler + */ + +#include + +/* Intel ECC compiler doesn't support gcc specific asm stmts. + * It uses intrinsics to do the equivalent things. + */ +#undef barrier +#undef RELOC_HIDE + +#define barrier() __memory_barrier() + +#define RELOC_HIDE(ptr, off) \ + ({ unsigned long __ptr; \ + __ptr = (unsigned long) (ptr); \ + (typeof(ptr)) (__ptr + (off)); }) + +#endif diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 356428f649fc..528641f69043 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -2,28 +2,36 @@ #define __LINUX_COMPILER_H #ifdef __CHECKER__ - #define __user __attribute__((noderef, address_space(1))) - #define __kernel /* default address space */ +# define __user __attribute__((noderef, address_space(1))) +# define __kernel /* default address space */ #else - #define __user - #define __kernel +# define __user +# define __kernel #endif -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -#define inline __inline__ __attribute__((always_inline)) -#define __inline__ __inline__ __attribute__((always_inline)) -#define __inline __inline__ __attribute__((always_inline)) +#if __GNUC__ > 3 +# include /* catch-all for GCC 4, 5, etc. */ +#elif __GNUC__ == 3 +# include +#elif __GNUC__ == 2 +# include +#else +# error Sorry, your compiler is too old/not recognized. #endif -/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented - a mechanism by which the user can annotate likely branch directions and - expect the blocks to be reordered appropriately. Define __builtin_expect - to nothing for earlier compilers. */ - -#if __GNUC__ == 2 && __GNUC_MINOR__ < 96 -#define __builtin_expect(x, expected_value) (x) +/* Intel compiler defines __GNUC__. So we will overwrite implementations + * coming from above header files here + */ +#ifdef __INTEL_COMPILER +# include #endif +/* + * Generic compiler-dependent macros required for kernel + * build go below this comment. Actual compiler/compiler version + * specific implementations come from the above header files + */ + #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) @@ -33,10 +41,8 @@ * Usage is: * int __deprecated foo(void) */ -#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3 -#define __deprecated __attribute__((deprecated)) -#else -#define __deprecated +#ifndef __deprecated +# define __deprecated /* unimplemented */ #endif /* @@ -50,10 +56,8 @@ * In prior versions of gcc, such functions and data would be emitted, but * would be warned about except with attribute((unused)). */ -#if __GNUC__ == 3 && __GNUC_MINOR__ >= 3 || __GNUC__ > 3 -#define __attribute_used__ __attribute__((__used__)) -#else -#define __attribute_used__ __attribute__((__unused__)) +#ifndef __attribute_used__ +# define __attribute_used__ /* unimplemented */ #endif /* @@ -65,19 +69,21 @@ * elimination and loop optimization just as an arithmetic operator * would be. * [...] - * The attribute `pure' is not implemented in GCC versions earlier - * than 2.96. */ -#if (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || __GNUC__ > 2 -#define __attribute_pure__ __attribute__((pure)) -#else -#define __attribute_pure__ /* unimplemented */ +#ifndef __attribute_pure__ +# define __attribute_pure__ /* unimplemented */ +#endif + +/* Optimization barrier */ +#ifndef barrier +# define barrier() __memory_barrier() #endif -/* This macro obfuscates arithmetic on a variable address so that gcc - shouldn't recognize the original var, and make assumptions about it */ -#define RELOC_HIDE(ptr, off) \ +#ifndef RELOC_HIDE +# define RELOC_HIDE(ptr, off) \ ({ unsigned long __ptr; \ - __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \ + __ptr = (unsigned long) (ptr); \ (typeof(ptr)) (__ptr + (off)); }) +#endif + #endif /* __LINUX_COMPILER_H */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b2d17ea0dac0..6403c9ef2210 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -15,10 +15,6 @@ #include #include -/* Optimization barrier */ -/* The "volatile" is due to gcc bugs */ -#define barrier() __asm__ __volatile__("": : :"memory") - #define INT_MAX ((int)(~0U>>1)) #define INT_MIN (-INT_MAX - 1) #define UINT_MAX (~0U) -- cgit v1.2.3 From 55b50278ec233024c2e5be04855d66ebdcebc35e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:37:01 -0700 Subject: [PATCH] real-time enhanced page allocator and throttling From: Robert Love - Let real-time tasks dip further into the reserves than usual in __alloc_pages(). There are a lot of ways to special case this. This patch just cuts z->pages_low in half, before doing the incremental min thing, for real-time tasks. I do not do anything in the low memory slow path. We can be a _lot_ more aggressive if we want. Right now, we just give real-time tasks a little help. - Never ever call balance_dirty_pages() on a real-time task. Where and how exactly we handle this is up for debate. We could, for example, special case real-time tasks inside balance_dirty_pages(). This would allow us to perform some of the work (say, waking up pdflush) but not other work (say, the active throttling). As it stands now, we do the per-processor accounting in balance_dirty_pages_ratelimited() but we never call balance_dirty_pages(). Lots of approaches work. What we want to do is never engage the real-time task in forced writeback. --- include/linux/sched.h | 4 +++- include/linux/writeback.h | 1 - kernel/sched.c | 1 - mm/page-writeback.c | 10 ++++++++-- mm/page_alloc.c | 31 ++++++++++++++++++++++--------- 5 files changed, 33 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index 3c6e3129144d..3d9aba07d508 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -281,7 +281,9 @@ struct signal_struct { #define MAX_RT_PRIO MAX_USER_RT_PRIO #define MAX_PRIO (MAX_RT_PRIO + 40) - + +#define rt_task(p) ((p)->prio < MAX_RT_PRIO) + /* * Some day this will be a full-fledged user tracking system.. */ diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 373e58fee2d4..1424811e1eab 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -84,7 +84,6 @@ int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *, void __user *, size_t *); void page_writeback_init(void); -void balance_dirty_pages(struct address_space *mapping); void balance_dirty_pages_ratelimited(struct address_space *mapping); int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); int do_writepages(struct address_space *mapping, struct writeback_control *wbc); diff --git a/kernel/sched.c b/kernel/sched.c index 89f1bb28dacd..1c5802ceedae 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -179,7 +179,6 @@ static DEFINE_PER_CPU(struct runqueue, runqueues); #define this_rq() (&__get_cpu_var(runqueues)) #define task_rq(p) cpu_rq(task_cpu(p)) #define cpu_curr(cpu) (cpu_rq(cpu)->curr) -#define rt_task(p) ((p)->prio < MAX_RT_PRIO) /* * Default context-switch locking: diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 80047ad9a25e..327700df7e33 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -111,6 +111,7 @@ get_dirty_limits(struct page_state *ps, long *pbackground, long *pdirty) int unmapped_ratio; long background; long dirty; + struct task_struct *tsk; get_page_state(ps); @@ -129,7 +130,8 @@ get_dirty_limits(struct page_state *ps, long *pbackground, long *pdirty) background = (background_ratio * total_pages) / 100; dirty = (dirty_ratio * total_pages) / 100; - if (current->flags & PF_LESS_THROTTLE) { + tsk = current; + if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) { background += background / 4; dirty += dirty / 4; } @@ -144,7 +146,7 @@ get_dirty_limits(struct page_state *ps, long *pbackground, long *pdirty) * If we're over `background_thresh' then pdflush is woken to perform some * writeout. */ -void balance_dirty_pages(struct address_space *mapping) +static void balance_dirty_pages(struct address_space *mapping) { struct page_state ps; long nr_reclaimable; @@ -219,6 +221,10 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping) if (dirty_exceeded) ratelimit = 8; + /* + * Check the rate limiting. Also, we do not want to throttle real-time + * tasks in balance_dirty_pages(). Period. + */ if (get_cpu_var(ratelimits)++ >= ratelimit) { __get_cpu_var(ratelimits) = 0; put_cpu_var(ratelimits); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4051a19b0ab5..4ac2982747c9 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -520,7 +520,8 @@ static struct page *buffered_rmqueue(struct zone *zone, int order, int cold) * * Herein lies the mysterious "incremental min". That's the * - * min += z->pages_low; + * local_low = z->pages_low; + * min += local_low; * * thing. The intent here is to provide additional protection to low zones for * allocation requests which _could_ use higher zones. So a GFP_HIGHMEM @@ -538,10 +539,11 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, unsigned long min; struct zone **zones, *classzone; struct page *page; + struct reclaim_state reclaim_state; + struct task_struct *p = current; int i; int cold; int do_retry; - struct reclaim_state reclaim_state; might_sleep_if(wait); @@ -558,8 +560,17 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, min = 1UL << order; for (i = 0; zones[i] != NULL; i++) { struct zone *z = zones[i]; + unsigned long local_low; + + /* + * This is the fabled 'incremental min'. We let real-time tasks + * dip their real-time paws a little deeper into reserves. + */ + local_low = z->pages_low; + if (rt_task(p)) + local_low >>= 1; + min += local_low; - min += z->pages_low; if (z->free_pages >= min || (!wait && z->free_pages >= z->pages_high)) { page = buffered_rmqueue(z, order, cold); @@ -582,6 +593,8 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, local_min = z->pages_min; if (gfp_mask & __GFP_HIGH) local_min >>= 2; + if (rt_task(p)) + local_min >>= 1; min += local_min; if (z->free_pages >= min || (!wait && z->free_pages >= z->pages_high)) { @@ -595,7 +608,7 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, /* here we're in the low on memory slow path */ rebalance: - if ((current->flags & (PF_MEMALLOC | PF_MEMDIE)) && !in_interrupt()) { + if ((p->flags & (PF_MEMALLOC | PF_MEMDIE)) && !in_interrupt()) { /* go through the zonelist yet again, ignoring mins */ for (i = 0; zones[i] != NULL; i++) { struct zone *z = zones[i]; @@ -611,14 +624,14 @@ rebalance: if (!wait) goto nopage; - current->flags |= PF_MEMALLOC; + p->flags |= PF_MEMALLOC; reclaim_state.reclaimed_slab = 0; - current->reclaim_state = &reclaim_state; + p->reclaim_state = &reclaim_state; try_to_free_pages(classzone, gfp_mask, order); - current->reclaim_state = NULL; - current->flags &= ~PF_MEMALLOC; + p->reclaim_state = NULL; + p->flags &= ~PF_MEMALLOC; /* go through the zonelist yet one more time */ min = 1UL << order; @@ -658,7 +671,7 @@ nopage: if (!(gfp_mask & __GFP_NOWARN)) { printk("%s: page allocation failure." " order:%d, mode:0x%x\n", - current->comm, order, gfp_mask); + p->comm, order, gfp_mask); } return NULL; got_pg: -- cgit v1.2.3 From feaecce47220d2d8bf6f0d76e09dc623dbf991e0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:37:10 -0700 Subject: [PATCH] Fix setpgid and threads From: Jeremy Fitzhardinge I'm resending my patch to fix this problem. To recap: every task_struct has its own copy of the thread group's pgrp. Only the thread group leader is allowed to change the tgrp's pgrp, but it only updates its own copy of pgrp, while all the other threads in the tgrp use the old value they inherited on creation. This patch simply updates all the other thread's pgrp when the tgrp leader changes pgrp. Ulrich has already expressed reservations about this patch since it is (1) incomplete (it doesn't cover the case of other ids which have similar problems), (2) racy (it doesn't synchronize with other threads looking at the task pgrp, so they could see an inconsistent view) and (3) slow (it takes linear time with respect to the number of threads in the tgrp). My reaction is that (1) it fixes the actual bug I'm encountering in a real program. (2) doesn't really matter for pgrp, since it is mostly an issue with respect to the terminal job-control code (which is even more broken without this patch. Regarding (3), I think there are very few programs which have a large number of threads which change process group id on a regular basis (a heavily multi-threaded job-control shell?). Ulrich also said he has a (proposed?) much better fix, which I've been looking forward to. I'm submitting this patch as a stop-gap fix for a real bug, and perhaps to prompt the improved patch. An alternative fix, at least for pgrp, is to change all references to ->pgrp to group_leader->pgrp. This may be sufficient on its own, but it would be a reasonably intrusive patch (I count 95 instances in 32 files in the 2.6.0-test3-mm3 tree). --- arch/h8300/kernel/signal.c | 2 +- arch/m68k/kernel/signal.c | 2 +- arch/m68knommu/kernel/signal.c | 2 +- arch/mips/kernel/irixelf.c | 2 +- arch/mips/kernel/irixsig.c | 2 +- arch/mips/kernel/sysirix.c | 4 ++-- arch/sparc64/solaris/misc.c | 4 ++-- drivers/char/n_tty.c | 6 +++--- drivers/char/rocket.c | 2 +- drivers/char/tty_io.c | 10 +++++----- drivers/isdn/i4l/isdn_tty.c | 3 ++- fs/autofs/autofs_i.h | 2 +- fs/autofs/inode.c | 4 ++-- fs/autofs/root.c | 4 ++-- fs/autofs4/autofs_i.h | 2 +- fs/autofs4/inode.c | 4 ++-- fs/autofs4/root.c | 4 ++-- fs/binfmt_elf.c | 4 ++-- fs/coda/upcall.c | 2 +- fs/devfs/base.c | 6 +++--- fs/proc/array.c | 2 +- include/linux/sched.h | 9 +++++++-- kernel/exit.c | 24 ++++++++++++------------ kernel/fork.c | 2 +- kernel/pid.c | 4 ++-- kernel/signal.c | 4 ++-- kernel/sys.c | 17 +++++++++-------- 27 files changed, 70 insertions(+), 63 deletions(-) (limited to 'include/linux') diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index 8db25723b077..727b420fadca 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c @@ -593,7 +593,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) continue; /* FALLTHRU */ diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 54951a69f4cc..92c280c7016d 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -1082,7 +1082,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) continue; /* FALLTHRU */ diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index 4271a229b62c..d24df6f29517 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c @@ -841,7 +841,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) continue; /* FALLTHRU */ diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 31fbd57c7021..f925c6514aad 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -1130,7 +1130,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) prstatus.pr_sighold = current->blocked.sig[0]; psinfo.pr_pid = prstatus.pr_pid = current->pid; psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid; - psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp; + psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current); psinfo.pr_sid = prstatus.pr_sid = current->session; prstatus.pr_utime.tv_sec = CT_TO_SECS(current->utime); prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime); diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 85cc88d32b7d..9ed7b1e75a39 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -582,7 +582,7 @@ repeat: p = list_entry(_p,struct task_struct,sibling); if ((type == P_PID) && p->pid != pid) continue; - if ((type == P_PGID) && p->pgrp != pid) + if ((type == P_PGID) && process_group(p) != pid) continue; if ((p->exit_signal != SIGCHLD)) continue; diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 022aa036efef..cadafba927ac 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -803,11 +803,11 @@ asmlinkage int irix_setpgrp(int flags) printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags); #endif if(!flags) - error = current->pgrp; + error = process_group(current); else error = sys_setsid(); #ifdef DEBUG_PROCGRPS - printk("returning %d\n", current->pgrp); + printk("returning %d\n", process_group(current)); #endif return error; diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 024b74c9d8b5..ea7b2c439653 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -392,7 +392,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) switch (cmd) { case 0: /* getpgrp */ - return current->pgrp; + return process_group(current); case 1: /* setpgrp */ { int (*sys_setpgid)(pid_t,pid_t) = @@ -403,7 +403,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) ret = sys_setpgid(0, 0); if (ret) return ret; current->tty = NULL; - return current->pgrp; + return process_group(current); } case 2: /* getsid */ { diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 6cc938bbbf30..44d551ba1091 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -977,11 +977,11 @@ do_it_again: if (file->f_op->write != redirected_tty_write && current->tty == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); - else if (current->pgrp != tty->pgrp) { + else if (process_group(current) != tty->pgrp) { if (is_ignored(SIGTTIN) || - is_orphaned_pgrp(current->pgrp)) + is_orphaned_pgrp(process_group(current))) return -EIO; - kill_pg(current->pgrp, SIGTTIN, 1); + kill_pg(process_group(current), SIGTTIN, 1); return -ERESTARTSYS; } } diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 8f969928c68b..50fab08d460f 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -956,7 +956,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) * Info->count is now 1; so it's safe to sleep now. */ info->session = current->session; - info->pgrp = current->pgrp; + info->pgrp = process_group(current); if ((info->flags & ROCKET_INITIALIZED) == 0) { cp = &info->channel; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 8d1f8c6d3c23..bbd84871219e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -325,13 +325,13 @@ int tty_check_change(struct tty_struct * tty) printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); return 0; } - if (current->pgrp == tty->pgrp) + if (process_group(current) == tty->pgrp) return 0; if (is_ignored(SIGTTOU)) return 0; - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) return -EIO; - (void) kill_pg(current->pgrp,SIGTTOU,1); + (void) kill_pg(process_group(current), SIGTTOU, 1); return -ERESTARTSYS; } @@ -1406,7 +1406,7 @@ got_driver: task_unlock(current); current->tty_old_pgrp = 0; tty->session = current->session; - tty->pgrp = current->pgrp; + tty->pgrp = process_group(current); } return 0; } @@ -1580,7 +1580,7 @@ static int tiocsctty(struct tty_struct *tty, int arg) task_unlock(current); current->tty_old_pgrp = 0; tty->session = current->session; - tty->pgrp = current->pgrp; + tty->pgrp = process_group(current); return 0; } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 996e8c5a9612..390b0f484d26 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1989,7 +1989,8 @@ modem_write_profile(atemu * m) memcpy(m->pmsn, m->msn, ISDN_MSNLEN); memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); if ((get_isdn_dev())->profd) - kill_pg_info(SIGIO, SEND_SIG_PRIV, (get_isdn_dev())->profd->pgrp); + kill_pg_info(SIGIO, SEND_SIG_PRIV, + process_group((get_isdn_dev())->profd)); } static struct tty_operations modem_ops = { diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 412e4dcb9e40..6171431272dc 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -123,7 +123,7 @@ static inline struct autofs_sb_info *autofs_sbi(struct super_block *sb) filesystem without "magic".) */ static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { - return sbi->catatonic || current->pgrp == sbi->oz_pgrp; + return sbi->catatonic || process_group(current) == sbi->oz_pgrp; } /* Hash operations */ diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 76bb0d61dd91..398cade9442d 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -51,7 +51,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid *uid = current->uid; *gid = current->gid; - *pgrp = current->pgrp; + *pgrp = process_group(current); *minproto = *maxproto = AUTOFS_PROTO_VERSION; @@ -129,7 +129,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) sbi->magic = AUTOFS_SBI_MAGIC; sbi->catatonic = 0; sbi->exp_timeout = 0; - sbi->oz_pgrp = current->pgrp; + sbi->oz_pgrp = process_group(current); autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN); diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 546ac2f9af87..74ad37a84efc 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -213,7 +213,7 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr oz_mode = autofs_oz_mode(sbi); DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", - current->pid, current->pgrp, sbi->catatonic, oz_mode)); + current->pid, process_group(current), sbi->catatonic, oz_mode)); /* * Mark the dentry incomplete, but add it. This is needed so @@ -527,7 +527,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, { struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); - DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current))); if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 16a3ab2f6d05..0a4b95417122 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -113,7 +113,7 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry) filesystem without "magic".) */ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { - return sbi->catatonic || current->pgrp == sbi->oz_pgrp; + return sbi->catatonic || process_group(current) == sbi->oz_pgrp; } /* Does a dentry have some pending activity? */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 35647d8eca94..f7cb9de42d95 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -101,7 +101,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, *uid = current->uid; *gid = current->gid; - *pgrp = current->pgrp; + *pgrp = process_group(current); *minproto = AUTOFS_MIN_PROTO_VERSION; *maxproto = AUTOFS_MAX_PROTO_VERSION; @@ -192,7 +192,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) sbi->magic = AUTOFS_SBI_MAGIC; sbi->catatonic = 0; sbi->exp_timeout = 0; - sbi->oz_pgrp = current->pgrp; + sbi->oz_pgrp = process_group(current); sbi->sb = s; sbi->version = 0; sbi->queues = NULL; diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 49f9f4d3b406..971dfa29b387 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -255,7 +255,7 @@ static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dent lock_kernel(); oz_mode = autofs4_oz_mode(sbi); DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", - current->pid, current->pgrp, sbi->catatonic, oz_mode)); + current->pid, process_group(current), sbi->catatonic, oz_mode)); /* * Mark the dentry incomplete, but add it. This is needed so @@ -518,7 +518,7 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb); DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n", - cmd,arg,sbi,current->pgrp)); + cmd,arg,sbi,process_group(current))); if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index ffcef47900fd..dfdead4fcb63 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1077,7 +1077,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_sighold = p->blocked.sig[0]; prstatus->pr_pid = p->pid; prstatus->pr_ppid = p->parent->pid; - prstatus->pr_pgrp = p->pgrp; + prstatus->pr_pgrp = process_group(p); prstatus->pr_sid = p->session; jiffies_to_timeval(p->utime, &prstatus->pr_utime); jiffies_to_timeval(p->stime, &prstatus->pr_stime); @@ -1105,7 +1105,7 @@ static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_pid = p->pid; psinfo->pr_ppid = p->parent->pid; - psinfo->pr_pgrp = p->pgrp; + psinfo->pr_pgrp = process_group(p); psinfo->pr_sid = p->session; i = p->state ? ffz(~p->state) + 1 : 0; diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index a513a4b823a9..5bce9b860d52 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -54,7 +54,7 @@ static void *alloc_upcall(int opcode, int size) inp->ih.opcode = opcode; inp->ih.pid = current->pid; - inp->ih.pgid = current->pgrp; + inp->ih.pgid = process_group(current); #ifdef CODA_FS_OLD_API memset(&inp->ih.cred, 0, sizeof(struct coda_cred)); inp->ih.cred.cr_fsuid = current->fsuid; diff --git a/fs/devfs/base.c b/fs/devfs/base.c index dd03e0397cc2..73894d9af19c 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -1334,7 +1334,7 @@ static int is_devfsd_or_child (struct fs_info *fs_info) struct task_struct *p = current; if (p == fs_info->devfsd_task) return (TRUE); - if (p->pgrp == fs_info->devfsd_pgrp) return (TRUE); + if (process_group(p) == fs_info->devfsd_pgrp) return (TRUE); read_lock(&tasklist_lock); for ( ; p != &init_task; p = p->real_parent) { @@ -2744,8 +2744,8 @@ static int devfsd_ioctl (struct inode *inode, struct file *file, } fs_info->devfsd_task = current; spin_unlock (&lock); - fs_info->devfsd_pgrp = (current->pgrp == current->pid) ? - current->pgrp : 0; + fs_info->devfsd_pgrp = (process_group(current) == current->pid) ? + process_group(current) : 0; fs_info->devfsd_file = file; fs_info->devfsd_info = kmalloc (sizeof *fs_info->devfsd_info, GFP_KERNEL); diff --git a/fs/proc/array.c b/fs/proc/array.c index a7a3bdaac4ec..4b9ec914d60f 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -341,7 +341,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) task->comm, state, ppid, - task->pgrp, + process_group(task), task->session, tty_nr, tty_pgrp, diff --git a/include/linux/sched.h b/include/linux/sched.h index 3d9aba07d508..9878dbef500a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -362,7 +362,7 @@ struct task_struct { unsigned long personality; int did_exec:1; pid_t pid; - pid_t pgrp; + pid_t __pgrp; /* Accessed via process_group() */ pid_t tty_old_pgrp; pid_t session; pid_t tgid; @@ -377,7 +377,7 @@ struct task_struct { struct task_struct *parent; /* parent process */ struct list_head children; /* list of my children */ struct list_head sibling; /* linkage in my parent's children list */ - struct task_struct *group_leader; + struct task_struct *group_leader; /* threadgroup leader */ /* PID/PID hash table linkage. */ struct pid_link pids[PIDTYPE_MAX]; @@ -463,6 +463,11 @@ struct task_struct { siginfo_t *last_siginfo; /* For ptrace use. */ }; +static inline pid_t process_group(struct task_struct *tsk) +{ + return tsk->group_leader->__pgrp; +} + extern void __put_task_struct(struct task_struct *tsk); #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0) #define put_task_struct(tsk) \ diff --git a/kernel/exit.c b/kernel/exit.c index b6174f82adf9..c565fd69d559 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -152,7 +152,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task) || p->state >= TASK_ZOMBIE || p->real_parent->pid == 1) continue; - if (p->real_parent->pgrp != pgrp + if (process_group(p->real_parent) != pgrp && p->real_parent->session == p->session) { ret = 0; break; @@ -247,9 +247,9 @@ void __set_special_pids(pid_t session, pid_t pgrp) curr->session = session; attach_pid(curr, PIDTYPE_SID, session); } - if (curr->pgrp != pgrp) { + if (process_group(curr) != pgrp) { detach_pid(curr, PIDTYPE_PGID); - curr->pgrp = pgrp; + curr->group_leader->__pgrp = pgrp; attach_pid(curr, PIDTYPE_PGID, pgrp); } } @@ -508,9 +508,9 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) * than we are, and it was the only connection * outside, so the child pgrp is now orphaned. */ - if ((p->pgrp != father->pgrp) && + if ((process_group(p) != process_group(father)) && (p->session == father->session)) { - int pgrp = p->pgrp; + int pgrp = process_group(p); if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { __kill_pg_info(SIGHUP, (void *)1, pgrp); @@ -618,12 +618,12 @@ static void exit_notify(struct task_struct *tsk) t = tsk->real_parent; - if ((t->pgrp != tsk->pgrp) && + if ((process_group(t) != process_group(tsk)) && (t->session == tsk->session) && - will_become_orphaned_pgrp(tsk->pgrp, tsk) && - has_stopped_jobs(tsk->pgrp)) { - __kill_pg_info(SIGHUP, (void *)1, tsk->pgrp); - __kill_pg_info(SIGCONT, (void *)1, tsk->pgrp); + will_become_orphaned_pgrp(process_group(tsk), tsk) && + has_stopped_jobs(process_group(tsk))) { + __kill_pg_info(SIGHUP, (void *)1, process_group(tsk)); + __kill_pg_info(SIGCONT, (void *)1, process_group(tsk)); } /* Let father know we died @@ -813,10 +813,10 @@ static int eligible_child(pid_t pid, int options, task_t *p) if (p->pid != pid) return 0; } else if (!pid) { - if (p->pgrp != current->pgrp) + if (process_group(p) != process_group(current)) return 0; } else if (pid != -1) { - if (p->pgrp != -pid) + if (process_group(p) != -pid) return 0; } diff --git a/kernel/fork.c b/kernel/fork.c index 37d79b4e16e6..50535a16c71e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1004,7 +1004,7 @@ struct task_struct *copy_process(unsigned long clone_flags, attach_pid(p, PIDTYPE_PID, p->pid); if (thread_group_leader(p)) { attach_pid(p, PIDTYPE_TGID, p->tgid); - attach_pid(p, PIDTYPE_PGID, p->pgrp); + attach_pid(p, PIDTYPE_PGID, process_group(p)); attach_pid(p, PIDTYPE_SID, p->session); if (p->pid) __get_cpu_var(process_counts)++; diff --git a/kernel/pid.c b/kernel/pid.c index 00413e3967b9..713f54eaeda9 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -250,13 +250,13 @@ void switch_exec_pids(task_t *leader, task_t *thread) attach_pid(thread, PIDTYPE_PID, thread->pid); attach_pid(thread, PIDTYPE_TGID, thread->tgid); - attach_pid(thread, PIDTYPE_PGID, thread->pgrp); + attach_pid(thread, PIDTYPE_PGID, leader->__pgrp); attach_pid(thread, PIDTYPE_SID, thread->session); list_add_tail(&thread->tasks, &init_task.tasks); attach_pid(leader, PIDTYPE_PID, leader->pid); attach_pid(leader, PIDTYPE_TGID, leader->tgid); - attach_pid(leader, PIDTYPE_PGID, leader->pgrp); + attach_pid(leader, PIDTYPE_PGID, leader->__pgrp); attach_pid(leader, PIDTYPE_SID, leader->session); } diff --git a/kernel/signal.c b/kernel/signal.c index 72333be1fd42..852da1a009da 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1139,7 +1139,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) static int kill_something_info(int sig, struct siginfo *info, int pid) { if (!pid) { - return kill_pg_info(sig, info, current->pgrp); + return kill_pg_info(sig, info, process_group(current)); } else if (pid == -1) { int retval = 0, count = 0; struct task_struct * p; @@ -1798,7 +1798,7 @@ relock: /* signals can be posted during this window */ - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) goto relock; spin_lock_irq(¤t->sighand->siglock); diff --git a/kernel/sys.c b/kernel/sys.c index 02b5a12dfd59..9c6da1d16d9a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -290,7 +290,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval) break; case PRIO_PGRP: if (!who) - who = current->pgrp; + who = process_group(current); for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) error = set_one_prio(p, niceval, error); break; @@ -346,7 +346,7 @@ asmlinkage long sys_getpriority(int which, int who) break; case PRIO_PGRP: if (!who) - who = current->pgrp; + who = process_group(current); for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) { niceval = 20 - task_nice(p); if (niceval > retval) @@ -979,11 +979,12 @@ ok_pgid: if (err) goto out; - if (p->pgrp != pgid) { + if (process_group(p) != pgid) { detach_pid(p, PIDTYPE_PGID); - p->pgrp = pgid; + p->group_leader->__pgrp = pgid; attach_pid(p, PIDTYPE_PGID, pgid); } + err = 0; out: /* All paths lead to here, thus we are safe. -DaveM */ @@ -994,7 +995,7 @@ out: asmlinkage long sys_getpgid(pid_t pid) { if (!pid) { - return current->pgrp; + return process_group(current); } else { int retval; struct task_struct *p; @@ -1006,7 +1007,7 @@ asmlinkage long sys_getpgid(pid_t pid) if (p) { retval = security_task_getpgid(p); if (!retval) - retval = p->pgrp; + retval = process_group(p); } read_unlock(&tasklist_lock); return retval; @@ -1016,7 +1017,7 @@ asmlinkage long sys_getpgid(pid_t pid) asmlinkage long sys_getpgrp(void) { /* SMP - assuming writes are word atomic this is fine */ - return current->pgrp; + return process_group(current); } asmlinkage long sys_getsid(pid_t pid) @@ -1059,7 +1060,7 @@ asmlinkage long sys_setsid(void) __set_special_pids(current->pid, current->pid); current->tty = NULL; current->tty_old_pgrp = 0; - err = current->pgrp; + err = process_group(current); out: write_unlock_irq(&tasklist_lock); return err; -- cgit v1.2.3 From 644f9658fde684f3d8e9b158f945a8bf98731a57 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:37:43 -0700 Subject: [PATCH] NLS: Remove the nls modules for only alias From: OGAWA Hirofumi This does the following, 1) This removes the nls modules for only alias. For backward compatible, this adds ->alias, and ->alias provides alias of charset. 2) For autoloading the module by the alias, use MODULE_ALIAS mechanism. 3) From changelog of module-init-tools, looks like MODULE_ALIAS needs module-init-tools 0.9.10 or later. So change the "Documentation/Changes". --- Documentation/Changes | 2 +- fs/nls/Makefile | 13 +++++------ fs/nls/nls_base.c | 5 ++++- fs/nls/nls_big5.c | 59 -------------------------------------------------- fs/nls/nls_cp1255.c | 5 ++++- fs/nls/nls_cp874.c | 5 ++++- fs/nls/nls_cp932.c | 3 +++ fs/nls/nls_cp936.c | 3 +++ fs/nls/nls_cp949.c | 3 +++ fs/nls/nls_cp950.c | 3 +++ fs/nls/nls_euc-kr.c | 59 -------------------------------------------------- fs/nls/nls_gb2312.c | 59 -------------------------------------------------- fs/nls/nls_iso8859-8.c | 59 -------------------------------------------------- fs/nls/nls_sjis.c | 59 -------------------------------------------------- fs/nls/nls_tis-620.c | 59 -------------------------------------------------- include/linux/nls.h | 3 +++ 16 files changed, 34 insertions(+), 365 deletions(-) delete mode 100644 fs/nls/nls_big5.c delete mode 100644 fs/nls/nls_euc-kr.c delete mode 100644 fs/nls/nls_gb2312.c delete mode 100644 fs/nls/nls_iso8859-8.c delete mode 100644 fs/nls/nls_sjis.c delete mode 100644 fs/nls/nls_tis-620.c (limited to 'include/linux') diff --git a/Documentation/Changes b/Documentation/Changes index 6c3d414df1f5..458086bd7f04 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -52,7 +52,7 @@ o Gnu C 2.95.3 # gcc --version o Gnu make 3.78 # make --version o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version -o module-init-tools 0.9.9 # depmod -V +o module-init-tools 0.9.10 # depmod -V o e2fsprogs 1.29 # tune2fs o jfsutils 1.1.3 # fsck.jfs -V o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs diff --git a/fs/nls/Makefile b/fs/nls/Makefile index f56c8d4ce844..4548f2940327 100644 --- a/fs/nls/Makefile +++ b/fs/nls/Makefile @@ -19,14 +19,13 @@ obj-$(CONFIG_NLS_CODEPAGE_864) += nls_cp864.o obj-$(CONFIG_NLS_CODEPAGE_865) += nls_cp865.o obj-$(CONFIG_NLS_CODEPAGE_866) += nls_cp866.o obj-$(CONFIG_NLS_CODEPAGE_869) += nls_cp869.o -obj-$(CONFIG_NLS_CODEPAGE_874) += nls_cp874.o nls_tis-620.o -obj-$(CONFIG_NLS_CODEPAGE_932) += nls_cp932.o nls_sjis.o nls_euc-jp.o -obj-$(CONFIG_NLS_CODEPAGE_936) += nls_cp936.o nls_gb2312.o -obj-$(CONFIG_NLS_CODEPAGE_949) += nls_cp949.o nls_euc-kr.o -obj-$(CONFIG_NLS_CODEPAGE_950) += nls_cp950.o nls_big5.o +obj-$(CONFIG_NLS_CODEPAGE_874) += nls_cp874.o +obj-$(CONFIG_NLS_CODEPAGE_932) += nls_cp932.o nls_euc-jp.o +obj-$(CONFIG_NLS_CODEPAGE_936) += nls_cp936.o +obj-$(CONFIG_NLS_CODEPAGE_949) += nls_cp949.o +obj-$(CONFIG_NLS_CODEPAGE_950) += nls_cp950.o obj-$(CONFIG_NLS_CODEPAGE_1250) += nls_cp1250.o obj-$(CONFIG_NLS_CODEPAGE_1251) += nls_cp1251.o -obj-$(CONFIG_NLS_CODEPAGE_1255) += nls_cp1255.o obj-$(CONFIG_NLS_ISO8859_1) += nls_iso8859-1.o obj-$(CONFIG_NLS_ISO8859_2) += nls_iso8859-2.o obj-$(CONFIG_NLS_ISO8859_3) += nls_iso8859-3.o @@ -34,7 +33,7 @@ obj-$(CONFIG_NLS_ISO8859_4) += nls_iso8859-4.o obj-$(CONFIG_NLS_ISO8859_5) += nls_iso8859-5.o obj-$(CONFIG_NLS_ISO8859_6) += nls_iso8859-6.o obj-$(CONFIG_NLS_ISO8859_7) += nls_iso8859-7.o -obj-$(CONFIG_NLS_ISO8859_8) += nls_cp1255.o nls_iso8859-8.o +obj-$(CONFIG_NLS_ISO8859_8) += nls_cp1255.o obj-$(CONFIG_NLS_ISO8859_9) += nls_iso8859-9.o obj-$(CONFIG_NLS_ISO8859_10) += nls_iso8859-10.o obj-$(CONFIG_NLS_ISO8859_13) += nls_iso8859-13.o diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c index 972e46073072..d0904e1c94b2 100644 --- a/fs/nls/nls_base.c +++ b/fs/nls/nls_base.c @@ -203,9 +203,12 @@ static struct nls_table *find_nls(char *charset) { struct nls_table *nls; spin_lock(&nls_lock); - for (nls = tables; nls; nls = nls->next) + for (nls = tables; nls; nls = nls->next) { if (!strcmp(nls->charset, charset)) break; + if (nls->alias && !strcmp(nls->alias, charset)) + break; + } if (nls && !try_module_get(nls->owner)) nls = NULL; spin_unlock(&nls_lock); diff --git a/fs/nls/nls_big5.c b/fs/nls/nls_big5.c deleted file mode 100644 index ce8792b4bb3e..000000000000 --- a/fs/nls/nls_big5.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_big5.c - */ - -#include -#include -#include -#include -#include - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "big5", - .owner = THIS_MODULE, -}; - -static int __init init_nls_big5(void) -{ - p_nls = load_nls("cp950"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_big5(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_big5) -module_exit(exit_nls_big5) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_cp1255.c b/fs/nls/nls_cp1255.c index 479ef421f738..23eca4e62adf 100644 --- a/fs/nls/nls_cp1255.c +++ b/fs/nls/nls_cp1255.c @@ -360,6 +360,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) static struct nls_table table = { .charset = "cp1255", + .alias = "iso8859-8", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -380,6 +381,9 @@ static void __exit exit_nls_cp1255(void) module_init(init_nls_cp1255) module_exit(exit_nls_cp1255) +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(iso8859-8); + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically @@ -396,4 +400,3 @@ module_exit(exit_nls_cp1255) * c-continued-brace-offset: 0 * End: */ -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c index 34ae4cf7979c..00e2081dcdf2 100644 --- a/fs/nls/nls_cp874.c +++ b/fs/nls/nls_cp874.c @@ -251,6 +251,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) static struct nls_table table = { .charset = "cp874", + .alias = "tis-620", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -271,6 +272,9 @@ static void __exit exit_nls_cp874(void) module_init(init_nls_cp874) module_exit(exit_nls_cp874) +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(tis-620); + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically @@ -287,4 +291,3 @@ module_exit(exit_nls_cp874) * c-continued-brace-offset: 0 * End: */ -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c index a30961bccc34..8f6cfcd9d475 100644 --- a/fs/nls/nls_cp932.c +++ b/fs/nls/nls_cp932.c @@ -7885,6 +7885,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp932", + .alias = "sjis", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -7904,7 +7905,9 @@ static void __exit exit_nls_cp932(void) module_init(init_nls_cp932) module_exit(exit_nls_cp932) + MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(sjis); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/fs/nls/nls_cp936.c b/fs/nls/nls_cp936.c index 06a4dee6372d..13080ff14e94 100644 --- a/fs/nls/nls_cp936.c +++ b/fs/nls/nls_cp936.c @@ -11005,6 +11005,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp936", + .alias = "gb2312", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -11024,7 +11025,9 @@ static void __exit exit_nls_cp936(void) module_init(init_nls_cp936) module_exit(exit_nls_cp936) + MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(gb2312); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/fs/nls/nls_cp949.c b/fs/nls/nls_cp949.c index e1e4e9062b77..0323960e2b48 100644 --- a/fs/nls/nls_cp949.c +++ b/fs/nls/nls_cp949.c @@ -13922,6 +13922,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp949", + .alias = "euc-kr", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -13941,7 +13942,9 @@ static void __exit exit_nls_cp949(void) module_init(init_nls_cp949) module_exit(exit_nls_cp949) + MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(euc-kr); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/fs/nls/nls_cp950.c b/fs/nls/nls_cp950.c index 604fd4874be6..356401bf2f4f 100644 --- a/fs/nls/nls_cp950.c +++ b/fs/nls/nls_cp950.c @@ -9461,6 +9461,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp950", + .alias = "big5", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -9480,7 +9481,9 @@ static void __exit exit_nls_cp950(void) module_init(init_nls_cp950) module_exit(exit_nls_cp950) + MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(big5); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/fs/nls/nls_euc-kr.c b/fs/nls/nls_euc-kr.c deleted file mode 100644 index adbf5ffa3496..000000000000 --- a/fs/nls/nls_euc-kr.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_euc-kr.c - */ - -#include -#include -#include -#include -#include - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "euc-kr", - .owner = THIS_MODULE, -}; - -static int __init init_nls_euc_kr(void) -{ - p_nls = load_nls("cp949"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_euc_kr(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_euc_kr) -module_exit(exit_nls_euc_kr) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_gb2312.c b/fs/nls/nls_gb2312.c deleted file mode 100644 index 7d92be88c05c..000000000000 --- a/fs/nls/nls_gb2312.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_gb2312.c - */ - -#include -#include -#include -#include -#include - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "gb2312", - .owner = THIS_MODULE, -}; - -static int __init init_nls_gb2312(void) -{ - p_nls = load_nls("cp936"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_gb2312(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_gb2312) -module_exit(exit_nls_gb2312) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_iso8859-8.c b/fs/nls/nls_iso8859-8.c deleted file mode 100644 index 5f368b14066a..000000000000 --- a/fs/nls/nls_iso8859-8.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_iso8859-8.c - */ - -#include -#include -#include -#include -#include - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "iso8859-8", - .owner = THIS_MODULE, -}; - -static int __init init_nls_iso8859_8(void) -{ - p_nls = load_nls("cp1255"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_iso8859_8(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_iso8859_8) -module_exit(exit_nls_iso8859_8) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_sjis.c b/fs/nls/nls_sjis.c deleted file mode 100644 index d70a5305a87a..000000000000 --- a/fs/nls/nls_sjis.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_sjis.c - */ - -#include -#include -#include -#include -#include - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "sjis", - .owner = THIS_MODULE, -}; - -static int __init init_nls_sjis(void) -{ - p_nls = load_nls("cp932"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_sjis(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_sjis) -module_exit(exit_nls_sjis) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_tis-620.c b/fs/nls/nls_tis-620.c deleted file mode 100644 index 4fcea5e4dd36..000000000000 --- a/fs/nls/nls_tis-620.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_tis-620.c - */ - -#include -#include -#include -#include -#include - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "tis-620", - .owner = THIS_MODULE, -}; - -static int __init init_nls_tis_620(void) -{ - p_nls = load_nls("cp874"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_tis_620(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_tis_620) -module_exit(exit_nls_tis_620) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/include/linux/nls.h b/include/linux/nls.h index 2ab6466f8043..1c657d4f0cf3 100644 --- a/include/linux/nls.h +++ b/include/linux/nls.h @@ -8,6 +8,7 @@ typedef __u16 wchar_t; struct nls_table { char *charset; + char *alias; int (*uni2char) (wchar_t uni, unsigned char *out, int boundlen); int (*char2uni) (const unsigned char *rawstring, int boundlen, wchar_t *uni); @@ -32,5 +33,7 @@ extern int utf8_mbstowcs(wchar_t *, const __u8 *, int); extern int utf8_wctomb(__u8 *, wchar_t, int); extern int utf8_wcstombs(__u8 *, const wchar_t *, int); +#define MODULE_ALIAS_NLS(name) MODULE_ALIAS("nls_" __stringify(name)) + #endif /* _LINUX_NLS_H */ -- cgit v1.2.3 From f221af36348b0231dded895a5c8248660ff3bbc0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:38:00 -0700 Subject: [PATCH] scheduler infrastructure From: Ingo Molnar the attached scheduler patch (against test2-mm2) adds the scheduling infrastructure items discussed on lkml. I got good feedback - and while i dont expect it to solve all problems, it does solve a number of bad ones: - test_starve.c code from David Mosberger - thud.c making the system unusuable due to unfairness - fair/accurate sleep average based on a finegrained clock - audio skipping way too easily other changes in sched-test2-mm2-A3: - ia64 sched_clock() code, from David Mosberger. - migration thread startup without relying on implicit scheduling behavior. While the current 2.6 code is correct (due to the cpu-up code adding CPUs one by one), but it's also fragile - and this code cannot be carried over into the 2.4 backports. So adding this method would clean up the startup and would make it easier to have 2.4 backports. and here's the original changelog for the scheduler changes: - cycle accuracy (nanosec resolution) timekeeping within the scheduler. This fixes a number of audio artifacts (skipping) i've reproduced. I dont think we can get away without going cycle accuracy - reading the cycle counter adds some overhead, but it's acceptable. The first nanosec-accuracy patch was done by Mike Galbraith - this patch is different but similar in nature. I went further in also changing the sleep_avg to be of nanosec resolution. - more finegrained timeslices: there's now a timeslice 'sub unit' of 50 usecs (TIMESLICE_GRANULARITY) - CPU hogs on the same priority level will roundrobin with this unit. This change is intended to make gaming latencies shorter. - include scheduling latency in sleep bonus calculation. This change extends the sleep-average calculation to the period of time a task spends on the runqueue but doesnt get scheduled yet, right after wakeup. Note that tasks that were preempted (ie. not woken up) and are still on the runqueue do not get this benefit. This change closes one of the last hole in the dynamic priority estimation, it should result in interactive tasks getting more priority under heavy load. This change also fixes the test-starve.c testcase from David Mosberger. The TSC-based scheduler clock is disabled on ia32 NUMA platforms. (ie. platforms that have unsynched TSC for sure.) Those platforms should provide the proper code to rely on the TSC in a global way. (no such infrastructure exists at the moment - the monotonic TSC-based clock doesnt deal with TSC offsets either, as far as i can tell.) --- arch/i386/kernel/smpboot.c | 4 +- arch/i386/kernel/timers/timer_tsc.c | 24 ++++ fs/proc/array.c | 5 +- include/linux/sched.h | 5 +- kernel/fork.c | 2 +- kernel/sched.c | 222 +++++++++++++++++++++++++++--------- 6 files changed, 201 insertions(+), 61 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index a78d1cc88a1f..2d034f0374cc 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -915,13 +915,13 @@ static void smp_tune_scheduling (void) cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth; } - cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000; + cache_decay_ticks = (long)cacheflush_time/cpu_khz + 1; printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n", (long)cacheflush_time/(cpu_khz/1000), ((long)cacheflush_time*100/(cpu_khz/1000)) % 100); printk("task migration cache decay timeout: %ld msecs.\n", - (cache_decay_ticks + 1) * 1000 / HZ); + cache_decay_ticks); } /* diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index af912f4d2cf1..f8b3c918a955 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -127,6 +127,30 @@ static unsigned long long monotonic_clock_tsc(void) return base + cycles_2_ns(this_offset - last_offset); } +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + unsigned long long this_offset; + + /* + * In the NUMA case we dont use the TSC as they are not + * synchronized across all CPUs. + */ +#ifndef CONFIG_NUMA + if (unlikely(!cpu_has_tsc)) +#endif + return (unsigned long long)jiffies * (1000000000 / HZ); + + /* Read the Time Stamp Counter */ + rdtscll(this_offset); + + /* return the value in ns */ + return cycles_2_ns(this_offset); +} + + static void mark_offset_tsc(void) { unsigned long lost,delay; diff --git a/fs/proc/array.c b/fs/proc/array.c index 4b9ec914d60f..bf39eb5013b0 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -154,13 +154,16 @@ static inline char * task_state(struct task_struct *p, char *buffer) read_lock(&tasklist_lock); buffer += sprintf(buffer, "State:\t%s\n" + "SleepAVG:\t%lu%%\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", - get_task_state(p), p->tgid, + get_task_state(p), + (p->sleep_avg/1024)*100/(1000000000/1024), + p->tgid, p->pid, p->pid ? p->real_parent->pid : 0, p->pid && p->ptrace ? p->parent->pid : 0, p->uid, p->euid, p->suid, p->fsuid, diff --git a/include/linux/sched.h b/include/linux/sched.h index 9878dbef500a..d2d412d96bea 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -342,7 +342,8 @@ struct task_struct { prio_array_t *array; unsigned long sleep_avg; - unsigned long last_run; + unsigned long long timestamp; + int activated; unsigned long policy; cpumask_t cpus_allowed; @@ -506,6 +507,8 @@ static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask) } #endif +extern unsigned long long sched_clock(void); + #ifdef CONFIG_NUMA extern void sched_balance_exec(void); extern void node_nr_running_init(void); diff --git a/kernel/fork.c b/kernel/fork.c index 50535a16c71e..38badc50bebc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -925,7 +925,7 @@ struct task_struct *copy_process(unsigned long clone_flags, */ p->first_time_slice = 1; current->time_slice >>= 1; - p->last_run = jiffies; + p->timestamp = sched_clock(); if (!current->time_slice) { /* * This case is rare, it happens when the parent has only diff --git a/kernel/sched.c b/kernel/sched.c index 1c5802ceedae..966dfe516ec5 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -68,13 +68,15 @@ */ #define MIN_TIMESLICE ( 10 * HZ / 1000) #define MAX_TIMESLICE (200 * HZ / 1000) -#define CHILD_PENALTY 50 +#define TIMESLICE_GRANULARITY (HZ/40 ?: 1) +#define ON_RUNQUEUE_WEIGHT 30 +#define CHILD_PENALTY 95 #define PARENT_PENALTY 100 #define EXIT_WEIGHT 3 #define PRIO_BONUS_RATIO 25 #define INTERACTIVE_DELTA 2 -#define MAX_SLEEP_AVG (10*HZ) -#define STARVATION_LIMIT (10*HZ) +#define MAX_SLEEP_AVG (1*1000000000) +#define STARVATION_LIMIT HZ #define NODE_THRESHOLD 125 /* @@ -115,6 +117,11 @@ #define TASK_INTERACTIVE(p) \ ((p)->prio <= (p)->static_prio - DELTA(p)) +#define TASK_PREEMPTS_CURR(p, rq) \ + ((p)->prio < (rq)->curr->prio || \ + ((p)->prio == (rq)->curr->prio && \ + (p)->time_slice > (rq)->curr->time_slice * 2)) + /* * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ] * to time slice values. @@ -318,8 +325,8 @@ static int effective_prio(task_t *p) if (rt_task(p)) return p->prio; - bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 - - MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2; + bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*(p->sleep_avg/1024)/(MAX_SLEEP_AVG/1024)/100; + bonus -= MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2; prio = p->static_prio - bonus; if (prio < MAX_RT_PRIO) @@ -338,24 +345,24 @@ static inline void __activate_task(task_t *p, runqueue_t *rq) nr_running_inc(rq); } -/* - * activate_task - move a task to the runqueue and do priority recalculation - * - * Update all the scheduling statistics stuff. (sleep average - * calculation, priority modifiers, etc.) - */ -static inline void activate_task(task_t *p, runqueue_t *rq) +static void recalc_task_prio(task_t *p, unsigned long long now) { - long sleep_time = jiffies - p->last_run - 1; + unsigned long long __sleep_time = now - p->timestamp; + unsigned long sleep_time; + + if (__sleep_time > MAX_SLEEP_AVG) + sleep_time = MAX_SLEEP_AVG; + else + sleep_time = (unsigned long)__sleep_time; if (sleep_time > 0) { - int sleep_avg; + unsigned long long sleep_avg; /* * This code gives a bonus to interactive tasks. * * The boost works by updating the 'average sleep time' - * value here, based on ->last_run. The more time a task + * value here, based on ->timestamp. The more time a task * spends sleeping, the higher the average gets - and the * higher the priority boost gets as well. */ @@ -374,6 +381,37 @@ static inline void activate_task(task_t *p, runqueue_t *rq) p->prio = effective_prio(p); } } +} + +/* + * activate_task - move a task to the runqueue and do priority recalculation + * + * Update all the scheduling statistics stuff. (sleep average + * calculation, priority modifiers, etc.) + */ +static inline void activate_task(task_t *p, runqueue_t *rq) +{ + unsigned long long now = sched_clock(); + + recalc_task_prio(p, now); + + /* + * Tasks which were woken up by interrupts (ie. hw events) + * are most likely of interactive nature. So we give them + * the credit of extending their sleep time to the period + * of time they spend on the runqueue, waiting for execution + * on a CPU, first time around: + */ + if (in_interrupt()) + p->activated = 2; + else + /* + * Normal first-time wakeups get a credit too for on-runqueue time, + * but it will be weighted down: + */ + p->activated = 1; + p->timestamp = now; + __activate_task(p, rq); } @@ -500,7 +538,7 @@ repeat_lock_task: __activate_task(p, rq); else { activate_task(p, rq); - if (p->prio < rq->curr->prio) + if (TASK_PREEMPTS_CURR(p, rq)) resched_task(rq->curr); } success = 1; @@ -549,8 +587,8 @@ void wake_up_forked_process(task_t * p) * and children as well, to keep max-interactive tasks * from forking tasks that are max-interactive. */ - current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100; - p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100; + current->sleep_avg = current->sleep_avg / 100 * PARENT_PENALTY; + p->sleep_avg = p->sleep_avg / 100 * CHILD_PENALTY; p->prio = effective_prio(p); set_task_cpu(p, smp_processor_id()); @@ -591,8 +629,7 @@ void sched_exit(task_t * p) * the sleep_avg of the parent as well. */ if (p->sleep_avg < p->parent->sleep_avg) - p->parent->sleep_avg = (p->parent->sleep_avg * EXIT_WEIGHT + - p->sleep_avg) / (EXIT_WEIGHT + 1); + p->parent->sleep_avg = p->parent->sleep_avg / (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg / (EXIT_WEIGHT + 1); } /** @@ -994,13 +1031,8 @@ static inline void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t * Note that idle threads have a prio of MAX_PRIO, for this test * to be always true for them. */ - if (p->prio < this_rq->curr->prio) + if (TASK_PREEMPTS_CURR(p, this_rq)) set_need_resched(); - else { - if (p->prio == this_rq->curr->prio && - p->time_slice > this_rq->curr->time_slice) - set_need_resched(); - } } /* @@ -1017,12 +1049,14 @@ static void load_balance(runqueue_t *this_rq, int idle, cpumask_t cpumask) runqueue_t *busiest; prio_array_t *array; struct list_head *head, *curr; + unsigned long long now; task_t *tmp; busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance, cpumask); if (!busiest) goto out; + now = sched_clock(); /* * We first consider expired tasks. Those will likely not be * executed in the near future, and they are most likely to @@ -1063,7 +1097,7 @@ skip_queue: */ #define CAN_MIGRATE_TASK(p,rq,this_cpu) \ - ((idle || (jiffies - (p)->last_run > cache_decay_ticks)) && \ + ((idle || (((now - (p)->timestamp)>>10) > cache_decay_ticks)) &&\ !task_running(rq, p) && \ cpu_isset(this_cpu, (p)->cpus_allowed)) @@ -1180,8 +1214,7 @@ EXPORT_PER_CPU_SYMBOL(kstat); */ #define EXPIRED_STARVING(rq) \ (STARVATION_LIMIT && ((rq)->expired_timestamp && \ - (jiffies - (rq)->expired_timestamp >= \ - STARVATION_LIMIT * ((rq)->nr_running) + 1))) + (jiffies - (rq)->expired_timestamp >= STARVATION_LIMIT))) /* * This function gets called by the timer code, with HZ frequency. @@ -1231,14 +1264,11 @@ void scheduler_tick(int user_ticks, int sys_ticks) spin_lock(&rq->lock); /* * The task was running during this tick - update the - * time slice counter and the sleep average. Note: we - * do not update a thread's priority until it either - * goes to sleep or uses up its timeslice. This makes - * it possible for interactive tasks to use up their - * timeslices at their highest priority levels. + * time slice counter. Note: we do not update a thread's + * priority until it either goes to sleep or uses up its + * timeslice. This makes it possible for interactive tasks + * to use up their timeslices at their highest priority levels. */ - if (p->sleep_avg) - p->sleep_avg--; if (unlikely(rt_task(p))) { /* * RR tasks need a special form of timeslice management. @@ -1262,12 +1292,33 @@ void scheduler_tick(int user_ticks, int sys_ticks) p->time_slice = task_timeslice(p); p->first_time_slice = 0; + if (!rq->expired_timestamp) + rq->expired_timestamp = jiffies; if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) { - if (!rq->expired_timestamp) - rq->expired_timestamp = jiffies; enqueue_task(p, rq->expired); } else enqueue_task(p, rq->active); + } else { + /* + * Prevent a too long timeslice allowing a task to monopolize + * the CPU. We do this by splitting up the timeslice into + * smaller pieces. + * + * Note: this does not mean the task's timeslices expire or + * get lost in any way, they just might be preempted by + * another task of equal priority. (one with higher + * priority would have preempted this task already.) We + * requeue this task to the end of the list on this priority + * level, which is in essence a round-robin of tasks with + * equal priority. + */ + if (!((task_timeslice(p) - p->time_slice) % TIMESLICE_GRANULARITY) && + (p->array == rq->active)) { + dequeue_task(p, rq->active); + set_tsk_need_resched(p); + p->prio = effective_prio(p); + enqueue_task(p, rq->active); + } } out_unlock: spin_unlock(&rq->lock); @@ -1286,6 +1337,8 @@ asmlinkage void schedule(void) runqueue_t *rq; prio_array_t *array; struct list_head *queue; + unsigned long long now; + unsigned long run_time; int idx; /* @@ -1306,7 +1359,11 @@ need_resched: rq = this_rq(); release_kernel_lock(prev); - prev->last_run = jiffies; + now = sched_clock(); + if (likely(now - prev->timestamp < MAX_SLEEP_AVG)) + run_time = now - prev->timestamp; + else + run_time = MAX_SLEEP_AVG; spin_lock_irq(&rq->lock); /* @@ -1356,12 +1413,30 @@ pick_next_task: queue = array->queue + idx; next = list_entry(queue->next, task_t, run_list); + if (next->activated) { + unsigned long long delta = now - next->timestamp; + + if (next->activated == 1) + delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128; + + next->activated = 0; + array = next->array; + dequeue_task(next, array); + recalc_task_prio(next, next->timestamp + delta); + enqueue_task(next, array); + } switch_tasks: prefetch(next); clear_tsk_need_resched(prev); RCU_qsctr(task_cpu(prev))++; + prev->sleep_avg -= run_time; + if ((long)prev->sleep_avg < 0) + prev->sleep_avg = 0; + prev->timestamp = now; + if (likely(prev != next)) { + next->timestamp = now; rq->nr_switches++; rq->curr = next; @@ -1601,6 +1676,7 @@ void set_user_nice(task_t *p, long nice) unsigned long flags; prio_array_t *array; runqueue_t *rq; + int old_prio, new_prio, delta; if (TASK_NICE(p) == nice || nice < -20 || nice > 19) return; @@ -1609,6 +1685,12 @@ void set_user_nice(task_t *p, long nice) * the task might be in the middle of scheduling on another CPU. */ rq = task_rq_lock(p, &flags); + /* + * The RT priorities are set via setscheduler(), but we still + * allow the 'normal' nice value to be set - but as expected + * it wont have any effect on scheduling until the task is + * not SCHED_NORMAL: + */ if (rt_task(p)) { p->static_prio = NICE_TO_PRIO(nice); goto out_unlock; @@ -1616,16 +1698,20 @@ void set_user_nice(task_t *p, long nice) array = p->array; if (array) dequeue_task(p, array); + + old_prio = p->prio; + new_prio = NICE_TO_PRIO(nice); + delta = new_prio - old_prio; p->static_prio = NICE_TO_PRIO(nice); - p->prio = NICE_TO_PRIO(nice); + p->prio += delta; + if (array) { enqueue_task(p, array); /* - * If the task is running and lowered its priority, - * or increased its priority then reschedule its CPU: + * If the task increased its priority or is running and + * lowered its priority, then reschedule its CPU: */ - if ((NICE_TO_PRIO(nice) < p->static_prio) || - task_running(rq, p)) + if (delta < 0 || (delta > 0 && task_running(rq, p))) resched_task(rq->curr); } out_unlock: @@ -2382,6 +2468,12 @@ static void move_task_away(struct task_struct *p, int dest_cpu) local_irq_restore(flags); } +typedef struct { + int cpu; + struct completion startup_done; + task_t *task; +} migration_startup_t; + /* * migration_thread - this is a highprio system thread that performs * thread migration by bumping thread off CPU then 'pushing' onto @@ -2391,20 +2483,21 @@ static int migration_thread(void * data) { /* Marking "param" __user is ok, since we do a set_fs(KERNEL_DS); */ struct sched_param __user param = { .sched_priority = MAX_RT_PRIO-1 }; - int cpu = (long) data; + migration_startup_t *startup = data; + int cpu = startup->cpu; runqueue_t *rq; int ret; + startup->task = current; + complete(&startup->startup_done); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + + BUG_ON(smp_processor_id() != cpu); + daemonize("migration/%d", cpu); set_fs(KERNEL_DS); - /* - * Either we are running on the right CPU, or there's a a - * migration thread on this CPU, guaranteed (we're started - * serially). - */ - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - ret = setscheduler(0, SCHED_FIFO, ¶m); rq = this_rq(); @@ -2440,13 +2533,30 @@ static int migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) { + long cpu = (long) hcpu; + migration_startup_t startup; + switch (action) { case CPU_ONLINE: - printk("Starting migration thread for cpu %li\n", - (long)hcpu); - kernel_thread(migration_thread, hcpu, CLONE_KERNEL); - while (!cpu_rq((long)hcpu)->migration_thread) + + printk("Starting migration thread for cpu %li\n", cpu); + + startup.cpu = cpu; + startup.task = NULL; + init_completion(&startup.startup_done); + + kernel_thread(migration_thread, &startup, CLONE_KERNEL); + wait_for_completion(&startup.startup_done); + wait_task_inactive(startup.task); + + startup.task->thread_info->cpu = cpu; + startup.task->cpus_allowed = cpumask_of_cpu(cpu); + + wake_up_process(startup.task); + + while (!cpu_rq(cpu)->migration_thread) yield(); + break; } return NOTIFY_OK; -- cgit v1.2.3 From 2cf13d58dbc43af21ad54ccbf1081f0757818b71 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:38:24 -0700 Subject: [PATCH] CPU scheduler interactivity changes From: Con Kolivas Interactivity scheduler tweaks on top of Ingo's A3 interactivity patch. Interactive credit added to task struct to find truly interactive tasks and treat them differently. Extra #defines included as helpers for conversion to/from nanosecond timing, to work out an average timeslice for nice 0 tasks, and the effective dynamic priority bonuses that will be given to tasks. MAX_SLEEP_AVG modified to change dynamic priority by one for a nice 0 task sleeping or running for one full timeslice. CREDIT_LIMIT is the number of times a task earns sleep_avg over MAX_SLEEP_AVG before it is considered HIGH_CREDIT (truly interactive); and -CREDIT_LIMIT is LOW_CREDIT TIMESLICE GRANULARITY is modified to be more frequent for more interactivetasks (10 ms for top 2 dynamic priorities and then halving each priority belowthat) and less frequent per extra cpu. JUST_INTERACTIVE_SLEEP logic created to be a sleep_avg consistent with giving a task enough dynamic priority to remain on the active array. Task preemption of equal priority tasks is dropped as requeuing with TIMESLICE_GRANULARITY makes this unecessary. Dynamic priority bonus simplified. User tasks that sleep a long time and not waking from uninterruptible sleep are sought and categorised as idle. Their sleep avg is limited in it's rise to prevent them becoming high priority and suddenly turning into cpu hogs. Bonus for sleeping is proportionately higher the lower the dynamic priority of a task is; this allows for very rapid escalation to interactive status. Tasks that are LOW_CREDIT are limited in rise per sleep to one priority level. Non HIGH_CREDIT tasks waking from uninterruptible sleep are sought to detect cpu hogs waiting on I/O and their sleep_avg rise is limited to just interactive state to prevent cpu bound tasks from becoming interactive during I/O wait. Tasks that earn sleep_avg over MAX_SLEEP_AVG get interactive credits. On runqueue bonus is not given to non HIGH_CREDIT tasks waking from uninterruptible sleep. Forked tasks and their parents get sleep_avg limited to the minimum necessary to maintain their effective dynamic priority thus preventing repeated forking from being a way to get highly interactive, but not penalise them noticably otherwise. CAN_MIGRATE_TASK cleaned up and modified to work with nanosecond timestamps. Reverted Ingo's A3 Starvation limit change - it was making interactive tasks suffer more under increasing load. If a cpu is grossly overloaded and everyone is going to starve it may as well run interactive tasks preferentially. Task requeuing is limited to interactive tasks only (cpu bound tasks dont need low latency and derive benefit from longer timeslices), and they must have at least TIMESLICE_GRANULARITY remaining. HIGH_CREDIT tasks get penalised less sleep_avg the more interactive they are thus keeping them interactive for bursts but if they become sustained cpu hogs they will slide increasingly rapidly down the dynamic priority scale. Tasks that run out of sleep_avg, are still using up cpu time and are not high or low credit yet get penalised interactive credits to determine LOW_CREDIT tasks (cpu bound ones). --- include/linux/sched.h | 1 + kernel/sched.c | 252 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 189 insertions(+), 64 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index d2d412d96bea..1618ae7f42d4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -342,6 +342,7 @@ struct task_struct { prio_array_t *array; unsigned long sleep_avg; + long interactive_credit; unsigned long long timestamp; int activated; diff --git a/kernel/sched.c b/kernel/sched.c index 38fa1ac0f82b..875a7dcd2e55 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -14,6 +14,7 @@ * an array-switch method of distributing timeslices * and per-CPU runqueues. Cleanups and useful suggestions * by Davide Libenzi, preemptible kernel bits by Robert Love. + * 2003-09-03 Interactivity tuning by Con Kolivas. */ #include @@ -58,6 +59,14 @@ #define USER_PRIO(p) ((p)-MAX_RT_PRIO) #define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio) #define MAX_USER_PRIO (USER_PRIO(MAX_PRIO)) +#define AVG_TIMESLICE (MIN_TIMESLICE + ((MAX_TIMESLICE - MIN_TIMESLICE) *\ + (MAX_PRIO-1-NICE_TO_PRIO(0))/(MAX_USER_PRIO - 1))) + +/* + * Some helpers for converting nanosecond timing to jiffy resolution + */ +#define NS_TO_JIFFIES(TIME) ((TIME) / (1000000000 / HZ)) +#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ)) /* * These are the 'tuning knobs' of the scheduler: @@ -68,16 +77,18 @@ */ #define MIN_TIMESLICE ( 10 * HZ / 1000) #define MAX_TIMESLICE (200 * HZ / 1000) -#define TIMESLICE_GRANULARITY (HZ/40 ?: 1) #define ON_RUNQUEUE_WEIGHT 30 #define CHILD_PENALTY 95 #define PARENT_PENALTY 100 #define EXIT_WEIGHT 3 #define PRIO_BONUS_RATIO 25 +#define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100) #define INTERACTIVE_DELTA 2 -#define MAX_SLEEP_AVG (1*1000000000) -#define STARVATION_LIMIT HZ +#define MAX_SLEEP_AVG (AVG_TIMESLICE * MAX_BONUS) +#define STARVATION_LIMIT (MAX_SLEEP_AVG) +#define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG)) #define NODE_THRESHOLD 125 +#define CREDIT_LIMIT 100 /* * If a task is 'interactive' then we reinsert it in the active @@ -107,6 +118,19 @@ * too hard. */ +#define CURRENT_BONUS(p) \ + (NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \ + MAX_SLEEP_AVG) + +#ifdef CONFIG_SMP +#define TIMESLICE_GRANULARITY(p) (MIN_TIMESLICE * \ + (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \ + num_online_cpus()) +#else +#define TIMESLICE_GRANULARITY(p) (MIN_TIMESLICE * \ + (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1))) +#endif + #define SCALE(v1,v1_max,v2_max) \ (v1) * (v2_max) / (v1_max) @@ -117,10 +141,18 @@ #define TASK_INTERACTIVE(p) \ ((p)->prio <= (p)->static_prio - DELTA(p)) +#define JUST_INTERACTIVE_SLEEP(p) \ + (JIFFIES_TO_NS(MAX_SLEEP_AVG * \ + (MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1)) + +#define HIGH_CREDIT(p) \ + ((p)->interactive_credit > CREDIT_LIMIT) + +#define LOW_CREDIT(p) \ + ((p)->interactive_credit < -CREDIT_LIMIT) + #define TASK_PREEMPTS_CURR(p, rq) \ - ((p)->prio < (rq)->curr->prio || \ - ((p)->prio == (rq)->curr->prio && \ - (p)->time_slice > (rq)->curr->time_slice * 2)) + ((p)->prio < (rq)->curr->prio) /* * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ] @@ -325,8 +357,7 @@ static int effective_prio(task_t *p) if (rt_task(p)) return p->prio; - bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*(p->sleep_avg/1024)/(MAX_SLEEP_AVG/1024)/100; - bonus -= MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2; + bonus = CURRENT_BONUS(p) - MAX_BONUS / 2; prio = p->static_prio - bonus; if (prio < MAX_RT_PRIO) @@ -350,37 +381,75 @@ static void recalc_task_prio(task_t *p, unsigned long long now) unsigned long long __sleep_time = now - p->timestamp; unsigned long sleep_time; - if (__sleep_time > MAX_SLEEP_AVG) - sleep_time = MAX_SLEEP_AVG; + if (__sleep_time > NS_MAX_SLEEP_AVG) + sleep_time = NS_MAX_SLEEP_AVG; else sleep_time = (unsigned long)__sleep_time; - if (sleep_time > 0) { - unsigned long long sleep_avg; - + if (likely(sleep_time > 0)) { /* - * This code gives a bonus to interactive tasks. - * - * The boost works by updating the 'average sleep time' - * value here, based on ->timestamp. The more time a task - * spends sleeping, the higher the average gets - and the - * higher the priority boost gets as well. + * User tasks that sleep a long time are categorised as + * idle and will get just interactive status to stay active & + * prevent them suddenly becoming cpu hogs and starving + * other processes. */ - sleep_avg = p->sleep_avg + sleep_time; + if (p->mm && p->activated != -1 && + sleep_time > JUST_INTERACTIVE_SLEEP(p)){ + p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG - + AVG_TIMESLICE); + if (!HIGH_CREDIT(p)) + p->interactive_credit++; + } else { + /* + * The lower the sleep avg a task has the more + * rapidly it will rise with sleep time. + */ + sleep_time *= (MAX_BONUS - CURRENT_BONUS(p)) ? : 1; - /* - * 'Overflow' bonus ticks go to the waker as well, so the - * ticks are not lost. This has the effect of further - * boosting tasks that are related to maximum-interactive - * tasks. - */ - if (sleep_avg > MAX_SLEEP_AVG) - sleep_avg = MAX_SLEEP_AVG; - if (p->sleep_avg != sleep_avg) { - p->sleep_avg = sleep_avg; - p->prio = effective_prio(p); + /* + * Tasks with low interactive_credit are limited to + * one timeslice worth of sleep avg bonus. + */ + if (LOW_CREDIT(p) && + sleep_time > JIFFIES_TO_NS(task_timeslice(p))) + sleep_time = + JIFFIES_TO_NS(task_timeslice(p)); + + /* + * Non high_credit tasks waking from uninterruptible + * sleep are limited in their sleep_avg rise as they + * are likely to be cpu hogs waiting on I/O + */ + if (p->activated == -1 && !HIGH_CREDIT(p) && p->mm){ + if (p->sleep_avg >= JUST_INTERACTIVE_SLEEP(p)) + sleep_time = 0; + else if (p->sleep_avg + sleep_time >= + JUST_INTERACTIVE_SLEEP(p)){ + p->sleep_avg = + JUST_INTERACTIVE_SLEEP(p); + sleep_time = 0; + } + } + + /* + * This code gives a bonus to interactive tasks. + * + * The boost works by updating the 'average sleep time' + * value here, based on ->timestamp. The more time a task + * spends sleeping, the higher the average gets - and the + * higher the priority boost gets as well. + */ + p->sleep_avg += sleep_time; + + if (p->sleep_avg > NS_MAX_SLEEP_AVG){ + p->sleep_avg = NS_MAX_SLEEP_AVG; + if (!HIGH_CREDIT(p)) + p->interactive_credit++; + } } } + + p->prio = effective_prio(p); } /* @@ -396,20 +465,26 @@ static inline void activate_task(task_t *p, runqueue_t *rq) recalc_task_prio(p, now); /* - * Tasks which were woken up by interrupts (ie. hw events) - * are most likely of interactive nature. So we give them - * the credit of extending their sleep time to the period - * of time they spend on the runqueue, waiting for execution - * on a CPU, first time around: - */ - if (in_interrupt()) - p->activated = 2; - else - /* - * Normal first-time wakeups get a credit too for on-runqueue time, - * but it will be weighted down: + * This checks to make sure it's not an uninterruptible task + * that is now waking up. */ - p->activated = 1; + if (!p->activated){ + /* + * Tasks which were woken up by interrupts (ie. hw events) + * are most likely of interactive nature. So we give them + * the credit of extending their sleep time to the period + * of time they spend on the runqueue, waiting for execution + * on a CPU, first time around: + */ + if (in_interrupt()) + p->activated = 2; + else + /* + * Normal first-time wakeups get a credit too for on-runqueue + * time, but it will be weighted down: + */ + p->activated = 1; + } p->timestamp = now; __activate_task(p, rq); @@ -532,8 +607,14 @@ repeat_lock_task: task_rq_unlock(rq, &flags); goto repeat_lock_task; } - if (old_state == TASK_UNINTERRUPTIBLE) + if (old_state == TASK_UNINTERRUPTIBLE){ rq->nr_uninterruptible--; + /* + * Tasks on involuntary sleep don't earn + * sleep_avg beyond just interactive state. + */ + p->activated = -1; + } if (sync) __activate_task(p, rq); else { @@ -587,8 +668,14 @@ void wake_up_forked_process(task_t * p) * and children as well, to keep max-interactive tasks * from forking tasks that are max-interactive. */ - current->sleep_avg = current->sleep_avg / 100 * PARENT_PENALTY; - p->sleep_avg = p->sleep_avg / 100 * CHILD_PENALTY; + current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) * + PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); + + p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) * + CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); + + p->interactive_credit = 0; + p->prio = effective_prio(p); set_task_cpu(p, smp_processor_id()); @@ -629,7 +716,9 @@ void sched_exit(task_t * p) * the sleep_avg of the parent as well. */ if (p->sleep_avg < p->parent->sleep_avg) - p->parent->sleep_avg = p->parent->sleep_avg / (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg / (EXIT_WEIGHT + 1); + p->parent->sleep_avg = p->parent->sleep_avg / + (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg / + (EXIT_WEIGHT + 1); } /** @@ -1035,6 +1124,29 @@ static inline void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t set_need_resched(); } +/* + * Previously: + * + * #define CAN_MIGRATE_TASK(p,rq,this_cpu) \ + * ((!idle || (NS_TO_JIFFIES(now - (p)->timestamp) > \ + * cache_decay_ticks)) && !task_running(rq, p) && \ + * cpu_isset(this_cpu, (p)->cpus_allowed)) + */ + +static inline int +can_migrate_task(task_t *tsk, runqueue_t *rq, int this_cpu, int idle) +{ + unsigned long delta = sched_clock() - tsk->timestamp; + + if (!idle && (delta <= JIFFIES_TO_NS(cache_decay_ticks))) + return 0; + if (task_running(rq, tsk)) + return 0; + if (!cpu_isset(this_cpu, tsk->cpus_allowed)) + return 0; + return 1; +} + /* * Current runqueue is empty, or rebalance tick: if there is an * inbalance (current runqueue is too short) then pull from @@ -1049,14 +1161,12 @@ static void load_balance(runqueue_t *this_rq, int idle, cpumask_t cpumask) runqueue_t *busiest; prio_array_t *array; struct list_head *head, *curr; - unsigned long long now; task_t *tmp; busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance, cpumask); if (!busiest) goto out; - now = sched_clock(); /* * We only want to steal a number of tasks equal to 1/2 the imbalance, * otherwise we'll just shift the imbalance to the new queue: @@ -1102,14 +1212,9 @@ skip_queue: * 3) are cache-hot on their current CPU. */ -#define CAN_MIGRATE_TASK(p,rq,this_cpu) \ - ((idle || (((now - (p)->timestamp)>>10) > cache_decay_ticks)) &&\ - !task_running(rq, p) && \ - cpu_isset(this_cpu, (p)->cpus_allowed)) - curr = curr->prev; - if (!CAN_MIGRATE_TASK(tmp, busiest, this_cpu)) { + if (!can_migrate_task(tmp, busiest, this_cpu, idle)) { if (curr != head) goto skip_queue; idx++; @@ -1220,7 +1325,8 @@ EXPORT_PER_CPU_SYMBOL(kstat); */ #define EXPIRED_STARVING(rq) \ (STARVATION_LIMIT && ((rq)->expired_timestamp && \ - (jiffies - (rq)->expired_timestamp >= STARVATION_LIMIT))) + (jiffies - (rq)->expired_timestamp >= \ + STARVATION_LIMIT * ((rq)->nr_running) + 1))) /* * This function gets called by the timer code, with HZ frequency. @@ -1317,9 +1423,15 @@ void scheduler_tick(int user_ticks, int sys_ticks) * requeue this task to the end of the list on this priority * level, which is in essence a round-robin of tasks with * equal priority. + * + * This only applies to tasks in the interactive + * delta range with at least TIMESLICE_GRANULARITY to requeue. */ - if (!((task_timeslice(p) - p->time_slice) % TIMESLICE_GRANULARITY) && - (p->array == rq->active)) { + if (TASK_INTERACTIVE(p) && !((task_timeslice(p) - + p->time_slice) % TIMESLICE_GRANULARITY(p)) && + (p->time_slice >= TIMESLICE_GRANULARITY(p)) && + (p->array == rq->active)) { + dequeue_task(p, rq->active); set_tsk_need_resched(p); p->prio = effective_prio(p); @@ -1366,10 +1478,19 @@ need_resched: release_kernel_lock(prev); now = sched_clock(); - if (likely(now - prev->timestamp < MAX_SLEEP_AVG)) + if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG)) run_time = now - prev->timestamp; else - run_time = MAX_SLEEP_AVG; + run_time = NS_MAX_SLEEP_AVG; + + /* + * Tasks with interactive credits get charged less run_time + * at high sleep_avg to delay them losing their interactive + * status + */ + if (HIGH_CREDIT(prev)) + run_time /= (CURRENT_BONUS(prev) ? : 1); + spin_lock_irq(&rq->lock); /* @@ -1419,26 +1540,29 @@ pick_next_task: queue = array->queue + idx; next = list_entry(queue->next, task_t, run_list); - if (next->activated) { + if (next->activated > 0) { unsigned long long delta = now - next->timestamp; if (next->activated == 1) delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128; - next->activated = 0; array = next->array; dequeue_task(next, array); recalc_task_prio(next, next->timestamp + delta); enqueue_task(next, array); } + next->activated = 0; switch_tasks: prefetch(next); clear_tsk_need_resched(prev); RCU_qsctr(task_cpu(prev))++; prev->sleep_avg -= run_time; - if ((long)prev->sleep_avg < 0) + if ((long)prev->sleep_avg <= 0){ prev->sleep_avg = 0; + if (!(HIGH_CREDIT(prev) || LOW_CREDIT(prev))) + prev->interactive_credit--; + } prev->timestamp = now; if (likely(prev != next)) { -- cgit v1.2.3 From 853fee92c1a917787809c128d583e843f5bbbef4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:39:28 -0700 Subject: [PATCH] misc fixes - Remove dead declaration from elevator.h (Nick Piggin) - Fix the scheduler selection boot-time message. "Using anticipatory scheduling io scheduler" is not grammatical. - Remove last use of __SMP__ (Randy Dunlap) --- drivers/block/as-iosched.c | 2 +- fs/jbd/transaction.c | 3 --- include/linux/elevator.h | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index a54f8e9a358e..583d483680e8 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -1926,7 +1926,7 @@ elevator_t iosched_as = { .elevator_exit_fn = as_exit, .elevator_ktype = &as_ktype, - .elevator_name = "anticipatory scheduling", + .elevator_name = "anticipatory", }; EXPORT_SYMBOL(iosched_as); diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index cf9edd99e492..c19edbc42457 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1932,9 +1932,6 @@ void __journal_file_buffer(struct journal_head *jh, J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh)); assert_spin_locked(&transaction->t_journal->j_list_lock); -#ifdef __SMP__ - J_ASSERT (current->lock_depth >= 0); -#endif J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); J_ASSERT_JH(jh, jh->b_transaction == transaction || jh->b_transaction == 0); diff --git a/include/linux/elevator.h b/include/linux/elevator.h index e43d670c1371..cbd038b665e8 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -15,7 +15,6 @@ typedef int (elevator_queue_empty_fn) (request_queue_t *); typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); -typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *); typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); typedef int (elevator_may_queue_fn) (request_queue_t *, int); -- cgit v1.2.3 From e1d8d04df787eae098ef3fe2e421a1f5c148c8c8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:43:01 -0700 Subject: [PATCH] kill superflous kdev_t.h inclusions From: Christoph Hellwig now that kdev_t is gone very few places needs this still, the only header of those beeing fs.h --- include/linux/bio.h | 1 - include/linux/console.h | 1 - include/linux/devfs_fs_kernel.h | 1 - include/linux/swap.h | 1 - 4 files changed, 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/bio.h b/include/linux/bio.h index 6ad6d20d3778..0ac6a27ea0db 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -20,7 +20,6 @@ #ifndef __LINUX_BIO_H #define __LINUX_BIO_H -#include #include #include diff --git a/include/linux/console.h b/include/linux/console.h index 414ebe159d67..cdff9de7ee71 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -15,7 +15,6 @@ #define _LINUX_CONSOLE_H_ 1 #include -#include #include struct vc_data; diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index f12addd1daeb..16c78f54f427 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include diff --git a/include/linux/swap.h b/include/linux/swap.h index 147e5bf40cbf..1f3517e965f3 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -3,7 +3,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From 7b0db1f8ddbf3ec69c86357b0c6dfebcd0af05f6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 21 Sep 2003 01:43:10 -0700 Subject: [PATCH] move some more initializations out of drivers/char/mem.c From: Christoph Hellwig keeping init order the same.. --- drivers/char/Makefile | 2 +- drivers/char/ftape/lowlevel/ftape-init.c | 39 ++++++++++++-------------------- drivers/char/mem.c | 9 -------- drivers/char/misc.c | 3 ++- drivers/char/random.c | 12 ++++++---- drivers/char/tty_io.c | 4 +++- include/linux/ftape.h | 2 -- include/linux/miscdevice.h | 2 -- include/linux/random.h | 1 - include/linux/tty.h | 1 - 10 files changed, 29 insertions(+), 46 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/Makefile b/drivers/char/Makefile index aeac2fb7d641..b53d91f5c10d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -7,7 +7,7 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o +obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o consolemap_deftbl.o selection.o keyboard.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c index 9ffe3de655c0..8d5368a662dd 100644 --- a/drivers/char/ftape/lowlevel/ftape-init.c +++ b/drivers/char/ftape/lowlevel/ftape-init.c @@ -55,14 +55,24 @@ char ft_rev[] __initdata = "$Revision: 1.8 $"; char ft_dat[] __initdata = "$Date: 1997/11/06 00:38:08 $"; +#ifndef CONFIG_FT_NO_TRACE_AT_ALL +static int ft_tracing = -1; +#endif + + /* Called by modules package when installing the driver * or by kernel during the initialization phase */ -int __init ftape_init(void) +static int __init ftape_init(void) { TRACE_FUN(ft_t_flow); #ifdef MODULE +#ifndef CONFIG_FT_NO_TRACE_AT_ALL + if (ft_tracing != -1) { + ftape_tracing = ft_tracing; + } +#endif printk(KERN_INFO FTAPE_VERSION "\n"); if (TRACE_LEVEL >= ft_t_info) { printk( @@ -112,13 +122,6 @@ KERN_INFO "Compiled for Linux version %s\n", UTS_RELEASE); #endif TRACE_EXIT 0; } - -#ifdef MODULE - -#ifndef CONFIG_FT_NO_TRACE_AT_ALL -static int ft_tracing = -1; -#endif - #define FT_MOD_PARM(var,type,desc) \ MODULE_PARM(var,type); MODULE_PARM_DESC(var,desc) @@ -141,21 +144,7 @@ MODULE_DESCRIPTION( "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives."); MODULE_LICENSE("GPL"); -/* Called by modules package when installing the driver - */ -int init_module(void) -{ -#ifndef CONFIG_FT_NO_TRACE_AT_ALL - if (ft_tracing != -1) { - ftape_tracing = ft_tracing; - } -#endif - return ftape_init(); -} - -/* Called by modules package when removing the driver - */ -void cleanup_module(void) +static void __exit ftape_exit(void) { TRACE_FUN(ft_t_flow); @@ -166,4 +155,6 @@ void cleanup_module(void) printk(KERN_INFO "ftape: unloaded.\n"); TRACE_EXIT; } -#endif /* MODULE */ + +module_init(ftape_init); +module_exit(ftape_exit); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 82b44f1c1a13..3e32d60c8b1e 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -680,17 +680,8 @@ static int __init chr_dev_init(void) S_IFCHR | devlist[i].mode, devlist[i].name); } - rand_initialize(); #if defined (CONFIG_FB) fbmem_init(); -#endif - tty_init(); -#ifdef CONFIG_M68K_PRINTER - lp_m68k_init(); -#endif - misc_init(); -#ifdef CONFIG_FTAPE - ftape_init(); #endif return 0; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index e808cfa31236..8211052cecfe 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -277,7 +277,7 @@ int misc_deregister(struct miscdevice * misc) EXPORT_SYMBOL(misc_register); EXPORT_SYMBOL(misc_deregister); -int __init misc_init(void) +static int __init misc_init(void) { #ifdef CONFIG_PROC_FS struct proc_dir_entry *ent; @@ -320,3 +320,4 @@ int __init misc_init(void) } return 0; } +module_init(misc_init); diff --git a/drivers/char/random.c b/drivers/char/random.c index c36d2ea46b07..c782ff3622a8 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1493,16 +1493,16 @@ static void init_std_data(struct entropy_store *r) } } -void __init rand_initialize(void) +static int __init rand_initialize(void) { int i; if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state)) - return; /* Error, return */ + goto err; if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state)) - return; /* Error, return */ + goto err; if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state)) - return; /* Error, return */ + goto err; clear_entropy_store(random_state); clear_entropy_store(sec_random_state); init_std_data(random_state); @@ -1515,7 +1515,11 @@ void __init rand_initialize(void) memset(&mouse_timer_state, 0, sizeof(struct timer_rand_state)); memset(&extract_timer_state, 0, sizeof(struct timer_rand_state)); extract_timer_state.dont_count_entropy = 1; + return 0; +err: + return -1; } +module_init(rand_initialize); void rand_initialize_irq(int irq) { diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bbd84871219e..41935ac3e375 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2423,7 +2423,7 @@ static struct cdev vc0_cdev; * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ -void __init tty_init(void) +static int __init tty_init(void) { strcpy(tty_cdev.kobj.name, "dev.tty"); cdev_init(&tty_cdev, &tty_fops); @@ -2512,4 +2512,6 @@ void __init tty_init(void) #ifdef CONFIG_A2232 a2232board_init(); #endif + return 0; } +module_init(tty_init); diff --git a/include/linux/ftape.h b/include/linux/ftape.h index 99b3535a4e20..e21d4b442843 100644 --- a/include/linux/ftape.h +++ b/include/linux/ftape.h @@ -199,8 +199,6 @@ typedef union { #define ABS(a) ((a) < 0 ? -(a) : (a)) #define NR_ITEMS(x) (int)(sizeof(x)/ sizeof(*x)) -extern int ftape_init(void); - #endif /* __KERNEL__ */ #endif diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index d3af91351521..6b7f9c1fa5cd 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -36,8 +36,6 @@ #define TUN_MINOR 200 -extern int misc_init(void); - struct miscdevice { int minor; diff --git a/include/linux/random.h b/include/linux/random.h index ca0e460941a5..9ccb52fa0a01 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -42,7 +42,6 @@ struct rand_pool_info { #ifdef __KERNEL__ -extern void rand_initialize(void); extern void rand_initialize_irq(int irq); extern void batch_entropy_store(u32 a, u32 b, int num); diff --git a/include/linux/tty.h b/include/linux/tty.h index 205e27af55a2..c575197f00b3 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -351,7 +351,6 @@ extern void console_init(void); extern int lp_init(void); extern int pty_init(void); -extern void tty_init(void); extern int mxser_init(void); extern int moxa_init(void); extern int ip2_init(void); -- cgit v1.2.3