From a056ab8c7a00a0ffc52e9573bf01257004c2d08c Mon Sep 17 00:00:00 2001 From: Carlos Chinea Date: Fri, 16 Apr 2010 19:01:02 +0300 Subject: HSI: hsi: Introducing HSI framework Adds HSI framework in to the linux kernel. High Speed Synchronous Serial Interface (HSI) is a serial interface mainly used for connecting application engines (APE) with cellular modem engines (CMT) in cellular handsets. HSI provides multiplexing for up to 16 logical channels, low-latency and full duplex communication. Signed-off-by: Carlos Chinea Acked-by: Linus Walleij diff --git a/drivers/Kconfig b/drivers/Kconfig index b5e6f24..5289508 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig" source "drivers/spi/Kconfig" +source "drivers/hsi/Kconfig" + source "drivers/pps/Kconfig" source "drivers/ptp/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 1b31421..91077ac 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_TARGET_CORE) += target/ obj-$(CONFIG_MTD) += mtd/ obj-$(CONFIG_SPI) += spi/ +obj-y += hsi/ obj-y += net/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_FUSION) += message/ diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig new file mode 100644 index 0000000..937062e --- /dev/null +++ b/drivers/hsi/Kconfig @@ -0,0 +1,17 @@ +# +# HSI driver configuration +# +menuconfig HSI + tristate "HSI support" + ---help--- + The "High speed synchronous Serial Interface" is + synchronous serial interface used mainly to connect + application engines and cellular modems. + +if HSI + +config HSI_BOARDINFO + bool + default y + +endif # HSI diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile new file mode 100644 index 0000000..ed94a3a --- /dev/null +++ b/drivers/hsi/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for HSI +# +obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o +obj-$(CONFIG_HSI) += hsi.o diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c new file mode 100644 index 0000000..4e2d79b --- /dev/null +++ b/drivers/hsi/hsi.c @@ -0,0 +1,494 @@ +/* + * HSI core. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "hsi_core.h" + +static struct device_type hsi_ctrl = { + .name = "hsi_controller", +}; + +static struct device_type hsi_cl = { + .name = "hsi_client", +}; + +static struct device_type hsi_port = { + .name = "hsi_port", +}; + +static ssize_t modalias_show(struct device *dev, + struct device_attribute *a __maybe_unused, char *buf) +{ + return sprintf(buf, "hsi:%s\n", dev_name(dev)); +} + +static struct device_attribute hsi_bus_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + if (dev->type == &hsi_cl) + add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev)); + + return 0; +} + +static int hsi_bus_match(struct device *dev, struct device_driver *driver) +{ + return strcmp(dev_name(dev), driver->name) == 0; +} + +static struct bus_type hsi_bus_type = { + .name = "hsi", + .dev_attrs = hsi_bus_dev_attrs, + .match = hsi_bus_match, + .uevent = hsi_bus_uevent, +}; + +static void hsi_client_release(struct device *dev) +{ + kfree(to_hsi_client(dev)); +} + +static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info) +{ + struct hsi_client *cl; + unsigned long flags; + + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + if (!cl) + return; + cl->device.type = &hsi_cl; + cl->tx_cfg = info->tx_cfg; + cl->rx_cfg = info->rx_cfg; + cl->device.bus = &hsi_bus_type; + cl->device.parent = &port->device; + cl->device.release = hsi_client_release; + dev_set_name(&cl->device, info->name); + cl->device.platform_data = info->platform_data; + spin_lock_irqsave(&port->clock, flags); + list_add_tail(&cl->link, &port->clients); + spin_unlock_irqrestore(&port->clock, flags); + if (info->archdata) + cl->device.archdata = *info->archdata; + if (device_register(&cl->device) < 0) { + pr_err("hsi: failed to register client: %s\n", info->name); + kfree(cl); + } +} + +static void hsi_scan_board_info(struct hsi_controller *hsi) +{ + struct hsi_cl_info *cl_info; + struct hsi_port *p; + + list_for_each_entry(cl_info, &hsi_board_list, list) + if (cl_info->info.hsi_id == hsi->id) { + p = hsi_find_port_num(hsi, cl_info->info.port); + if (!p) + continue; + hsi_new_client(p, &cl_info->info); + } +} + +static int hsi_remove_client(struct device *dev, void *data __maybe_unused) +{ + struct hsi_client *cl = to_hsi_client(dev); + struct hsi_port *port = to_hsi_port(dev->parent); + unsigned long flags; + + spin_lock_irqsave(&port->clock, flags); + list_del(&cl->link); + spin_unlock_irqrestore(&port->clock, flags); + device_unregister(dev); + + return 0; +} + +static int hsi_remove_port(struct device *dev, void *data __maybe_unused) +{ + device_for_each_child(dev, NULL, hsi_remove_client); + device_unregister(dev); + + return 0; +} + +static void hsi_controller_release(struct device *dev __maybe_unused) +{ +} + +static void hsi_port_release(struct device *dev __maybe_unused) +{ +} + +/** + * hsi_unregister_controller - Unregister an HSI controller + * @hsi: The HSI controller to register + */ +void hsi_unregister_controller(struct hsi_controller *hsi) +{ + device_for_each_child(&hsi->device, NULL, hsi_remove_port); + device_unregister(&hsi->device); +} +EXPORT_SYMBOL_GPL(hsi_unregister_controller); + +/** + * hsi_register_controller - Register an HSI controller and its ports + * @hsi: The HSI controller to register + * + * Returns -errno on failure, 0 on success. + */ +int hsi_register_controller(struct hsi_controller *hsi) +{ + unsigned int i; + int err; + + hsi->device.type = &hsi_ctrl; + hsi->device.bus = &hsi_bus_type; + hsi->device.release = hsi_controller_release; + err = device_register(&hsi->device); + if (err < 0) + return err; + for (i = 0; i < hsi->num_ports; i++) { + hsi->port[i].device.parent = &hsi->device; + hsi->port[i].device.bus = &hsi_bus_type; + hsi->port[i].device.release = hsi_port_release; + hsi->port[i].device.type = &hsi_port; + INIT_LIST_HEAD(&hsi->port[i].clients); + spin_lock_init(&hsi->port[i].clock); + err = device_register(&hsi->port[i].device); + if (err < 0) + goto out; + } + /* Populate HSI bus with HSI clients */ + hsi_scan_board_info(hsi); + + return 0; +out: + hsi_unregister_controller(hsi); + + return err; +} +EXPORT_SYMBOL_GPL(hsi_register_controller); + +/** + * hsi_register_client_driver - Register an HSI client to the HSI bus + * @drv: HSI client driver to register + * + * Returns -errno on failure, 0 on success. + */ +int hsi_register_client_driver(struct hsi_client_driver *drv) +{ + drv->driver.bus = &hsi_bus_type; + + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(hsi_register_client_driver); + +static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused) +{ + return 0; +} + +static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) +{ + return 0; +} + +/** + * hsi_alloc_controller - Allocate an HSI controller and its ports + * @n_ports: Number of ports on the HSI controller + * @flags: Kernel allocation flags + * + * Return NULL on failure or a pointer to an hsi_controller on success. + */ +struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags) +{ + struct hsi_controller *hsi; + struct hsi_port *port; + unsigned int i; + + if (!n_ports) + return NULL; + + port = kzalloc(sizeof(*port)*n_ports, flags); + if (!port) + return NULL; + hsi = kzalloc(sizeof(*hsi), flags); + if (!hsi) + goto out; + for (i = 0; i < n_ports; i++) { + dev_set_name(&port[i].device, "port%d", i); + port[i].num = i; + port[i].async = hsi_dummy_msg; + port[i].setup = hsi_dummy_cl; + port[i].flush = hsi_dummy_cl; + port[i].start_tx = hsi_dummy_cl; + port[i].stop_tx = hsi_dummy_cl; + port[i].release = hsi_dummy_cl; + mutex_init(&port[i].lock); + } + hsi->num_ports = n_ports; + hsi->port = port; + + return hsi; +out: + kfree(port); + + return NULL; +} +EXPORT_SYMBOL_GPL(hsi_alloc_controller); + +/** + * hsi_free_controller - Free an HSI controller + * @hsi: Pointer to HSI controller + */ +void hsi_free_controller(struct hsi_controller *hsi) +{ + if (!hsi) + return; + + kfree(hsi->port); + kfree(hsi); +} +EXPORT_SYMBOL_GPL(hsi_free_controller); + +/** + * hsi_free_msg - Free an HSI message + * @msg: Pointer to the HSI message + * + * Client is responsible to free the buffers pointed by the scatterlists. + */ +void hsi_free_msg(struct hsi_msg *msg) +{ + if (!msg) + return; + sg_free_table(&msg->sgt); + kfree(msg); +} +EXPORT_SYMBOL_GPL(hsi_free_msg); + +/** + * hsi_alloc_msg - Allocate an HSI message + * @nents: Number of memory entries + * @flags: Kernel allocation flags + * + * nents can be 0. This mainly makes sense for read transfer. + * In that case, HSI drivers will call the complete callback when + * there is data to be read without consuming it. + * + * Return NULL on failure or a pointer to an hsi_msg on success. + */ +struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags) +{ + struct hsi_msg *msg; + int err; + + msg = kzalloc(sizeof(*msg), flags); + if (!msg) + return NULL; + + if (!nents) + return msg; + + err = sg_alloc_table(&msg->sgt, nents, flags); + if (unlikely(err)) { + kfree(msg); + msg = NULL; + } + + return msg; +} +EXPORT_SYMBOL_GPL(hsi_alloc_msg); + +/** + * hsi_async - Submit an HSI transfer to the controller + * @cl: HSI client sending the transfer + * @msg: The HSI transfer passed to controller + * + * The HSI message must have the channel, ttype, complete and destructor + * fields set beforehand. If nents > 0 then the client has to initialize + * also the scatterlists to point to the buffers to write to or read from. + * + * HSI controllers relay on pre-allocated buffers from their clients and they + * do not allocate buffers on their own. + * + * Once the HSI message transfer finishes, the HSI controller calls the + * complete callback with the status and actual_len fields of the HSI message + * updated. The complete callback can be called before returning from + * hsi_async. + * + * Returns -errno on failure or 0 on success + */ +int hsi_async(struct hsi_client *cl, struct hsi_msg *msg) +{ + struct hsi_port *port = hsi_get_port(cl); + + if (!hsi_port_claimed(cl)) + return -EACCES; + + WARN_ON_ONCE(!msg->destructor || !msg->complete); + msg->cl = cl; + + return port->async(msg); +} +EXPORT_SYMBOL_GPL(hsi_async); + +/** + * hsi_claim_port - Claim the HSI client's port + * @cl: HSI client that wants to claim its port + * @share: Flag to indicate if the client wants to share the port or not. + * + * Returns -errno on failure, 0 on success. + */ +int hsi_claim_port(struct hsi_client *cl, unsigned int share) +{ + struct hsi_port *port = hsi_get_port(cl); + int err = 0; + + mutex_lock(&port->lock); + if ((port->claimed) && (!port->shared || !share)) { + err = -EBUSY; + goto out; + } + if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) { + err = -ENODEV; + goto out; + } + port->claimed++; + port->shared = !!share; + cl->pclaimed = 1; +out: + mutex_unlock(&port->lock); + + return err; +} +EXPORT_SYMBOL_GPL(hsi_claim_port); + +/** + * hsi_release_port - Release the HSI client's port + * @cl: HSI client which previously claimed its port + */ +void hsi_release_port(struct hsi_client *cl) +{ + struct hsi_port *port = hsi_get_port(cl); + + mutex_lock(&port->lock); + /* Allow HW driver to do some cleanup */ + port->release(cl); + if (cl->pclaimed) + port->claimed--; + BUG_ON(port->claimed < 0); + cl->pclaimed = 0; + if (!port->claimed) + port->shared = 0; + module_put(to_hsi_controller(port->device.parent)->owner); + mutex_unlock(&port->lock); +} +EXPORT_SYMBOL_GPL(hsi_release_port); + +static int hsi_start_rx(struct hsi_client *cl, void *data __maybe_unused) +{ + if (cl->hsi_start_rx) + (*cl->hsi_start_rx)(cl); + + return 0; +} + +static int hsi_stop_rx(struct hsi_client *cl, void *data __maybe_unused) +{ + if (cl->hsi_stop_rx) + (*cl->hsi_stop_rx)(cl); + + return 0; +} + +static int hsi_port_for_each_client(struct hsi_port *port, void *data, + int (*fn)(struct hsi_client *cl, void *data)) +{ + struct hsi_client *cl; + + spin_lock(&port->clock); + list_for_each_entry(cl, &port->clients, link) { + spin_unlock(&port->clock); + (*fn)(cl, data); + spin_lock(&port->clock); + } + spin_unlock(&port->clock); + + return 0; +} + +/** + * hsi_event -Notifies clients about port events + * @port: Port where the event occurred + * @event: The event type + * + * Clients should not be concerned about wake line behavior. However, due + * to a race condition in HSI HW protocol, clients need to be notified + * about wake line changes, so they can implement a workaround for it. + * + * Events: + * HSI_EVENT_START_RX - Incoming wake line high + * HSI_EVENT_STOP_RX - Incoming wake line down + */ +void hsi_event(struct hsi_port *port, unsigned int event) +{ + int (*fn)(struct hsi_client *cl, void *data); + + switch (event) { + case HSI_EVENT_START_RX: + fn = hsi_start_rx; + break; + case HSI_EVENT_STOP_RX: + fn = hsi_stop_rx; + break; + default: + return; + } + hsi_port_for_each_client(port, NULL, fn); +} +EXPORT_SYMBOL_GPL(hsi_event); + +static int __init hsi_init(void) +{ + return bus_register(&hsi_bus_type); +} +postcore_initcall(hsi_init); + +static void __exit hsi_exit(void) +{ + bus_unregister(&hsi_bus_type); +} +module_exit(hsi_exit); + +MODULE_AUTHOR("Carlos Chinea "); +MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/hsi/hsi_boardinfo.c b/drivers/hsi/hsi_boardinfo.c new file mode 100644 index 0000000..e56bc6d --- /dev/null +++ b/drivers/hsi/hsi_boardinfo.c @@ -0,0 +1,62 @@ +/* + * HSI clients registration interface + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include "hsi_core.h" + +/* + * hsi_board_list is only used internally by the HSI framework. + * No one else is allowed to make use of it. + */ +LIST_HEAD(hsi_board_list); +EXPORT_SYMBOL_GPL(hsi_board_list); + +/** + * hsi_register_board_info - Register HSI clients information + * @info: Array of HSI clients on the board + * @len: Length of the array + * + * HSI clients are statically declared and registered on board files. + * + * HSI clients will be automatically registered to the HSI bus once the + * controller and the port where the clients wishes to attach are registered + * to it. + * + * Return -errno on failure, 0 on success. + */ +int __init hsi_register_board_info(struct hsi_board_info const *info, + unsigned int len) +{ + struct hsi_cl_info *cl_info; + + cl_info = kzalloc(sizeof(*cl_info) * len, GFP_KERNEL); + if (!cl_info) + return -ENOMEM; + + for (; len; len--, info++, cl_info++) { + cl_info->info = *info; + list_add_tail(&cl_info->list, &hsi_board_list); + } + + return 0; +} diff --git a/drivers/hsi/hsi_core.h b/drivers/hsi/hsi_core.h new file mode 100644 index 0000000..ab5c2fb --- /dev/null +++ b/drivers/hsi/hsi_core.h @@ -0,0 +1,35 @@ +/* + * HSI framework internal interfaces, + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __LINUX_HSI_CORE_H__ +#define __LINUX_HSI_CORE_H__ + +#include + +struct hsi_cl_info { + struct list_head list; + struct hsi_board_info info; +}; + +extern struct list_head hsi_board_list; + +#endif /* __LINUX_HSI_CORE_H__ */ diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h new file mode 100644 index 0000000..4b17806 --- /dev/null +++ b/include/linux/hsi/hsi.h @@ -0,0 +1,410 @@ +/* + * HSI core header file. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __LINUX_HSI_H__ +#define __LINUX_HSI_H__ + +#include +#include +#include +#include +#include +#include + +/* HSI message ttype */ +#define HSI_MSG_READ 0 +#define HSI_MSG_WRITE 1 + +/* HSI configuration values */ +enum { + HSI_MODE_STREAM = 1, + HSI_MODE_FRAME, +}; + +enum { + HSI_FLOW_SYNC, /* Synchronized flow */ + HSI_FLOW_PIPE, /* Pipelined flow */ +}; + +enum { + HSI_ARB_RR, /* Round-robin arbitration */ + HSI_ARB_PRIO, /* Channel priority arbitration */ +}; + +#define HSI_MAX_CHANNELS 16 + +/* HSI message status codes */ +enum { + HSI_STATUS_COMPLETED, /* Message transfer is completed */ + HSI_STATUS_PENDING, /* Message pending to be read/write (POLL) */ + HSI_STATUS_PROCEEDING, /* Message transfer is ongoing */ + HSI_STATUS_QUEUED, /* Message waiting to be served */ + HSI_STATUS_ERROR, /* Error when message transfer was ongoing */ +}; + +/* HSI port event codes */ +enum { + HSI_EVENT_START_RX, + HSI_EVENT_STOP_RX, +}; + +/** + * struct hsi_config - Configuration for RX/TX HSI modules + * @mode: Bit transmission mode (STREAM or FRAME) + * @channels: Number of channels to use [1..16] + * @speed: Max bit transmission speed (Kbit/s) + * @flow: RX flow type (SYNCHRONIZED or PIPELINE) + * @arb_mode: Arbitration mode for TX frame (Round robin, priority) + */ +struct hsi_config { + unsigned int mode; + unsigned int channels; + unsigned int speed; + union { + unsigned int flow; /* RX only */ + unsigned int arb_mode; /* TX only */ + }; +}; + +/** + * struct hsi_board_info - HSI client board info + * @name: Name for the HSI device + * @hsi_id: HSI controller id where the client sits + * @port: Port number in the controller where the client sits + * @tx_cfg: HSI TX configuration + * @rx_cfg: HSI RX configuration + * @platform_data: Platform related data + * @archdata: Architecture-dependent device data + */ +struct hsi_board_info { + const char *name; + unsigned int hsi_id; + unsigned int port; + struct hsi_config tx_cfg; + struct hsi_config rx_cfg; + void *platform_data; + struct dev_archdata *archdata; +}; + +#ifdef CONFIG_HSI_BOARDINFO +extern int hsi_register_board_info(struct hsi_board_info const *info, + unsigned int len); +#else +static inline int hsi_register_board_info(struct hsi_board_info const *info, + unsigned int len) +{ + return 0; +} +#endif /* CONFIG_HSI_BOARDINFO */ + +/** + * struct hsi_client - HSI client attached to an HSI port + * @device: Driver model representation of the device + * @tx_cfg: HSI TX configuration + * @rx_cfg: HSI RX configuration + * @hsi_start_rx: Called after incoming wake line goes high + * @hsi_stop_rx: Called after incoming wake line goes low + */ +struct hsi_client { + struct device device; + struct hsi_config tx_cfg; + struct hsi_config rx_cfg; + void (*hsi_start_rx)(struct hsi_client *cl); + void (*hsi_stop_rx)(struct hsi_client *cl); + /* private: */ + unsigned int pclaimed:1; + struct list_head link; +}; + +#define to_hsi_client(dev) container_of(dev, struct hsi_client, device) + +static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data) +{ + dev_set_drvdata(&cl->device, data); +} + +static inline void *hsi_client_drvdata(struct hsi_client *cl) +{ + return dev_get_drvdata(&cl->device); +} + +/** + * struct hsi_client_driver - Driver associated to an HSI client + * @driver: Driver model representation of the driver + */ +struct hsi_client_driver { + struct device_driver driver; +}; + +#define to_hsi_client_driver(drv) container_of(drv, struct hsi_client_driver,\ + driver) + +int hsi_register_client_driver(struct hsi_client_driver *drv); + +static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv) +{ + driver_unregister(&drv->driver); +} + +/** + * struct hsi_msg - HSI message descriptor + * @link: Free to use by the current descriptor owner + * @cl: HSI device client that issues the transfer + * @sgt: Head of the scatterlist array + * @context: Client context data associated to the transfer + * @complete: Transfer completion callback + * @destructor: Destructor to free resources when flushing + * @status: Status of the transfer when completed + * @actual_len: Actual length of data transfered on completion + * @channel: Channel were to TX/RX the message + * @ttype: Transfer type (TX if set, RX otherwise) + * @break_frame: if true HSI will send/receive a break frame. Data buffers are + * ignored in the request. + */ +struct hsi_msg { + struct list_head link; + struct hsi_client *cl; + struct sg_table sgt; + void *context; + + void (*complete)(struct hsi_msg *msg); + void (*destructor)(struct hsi_msg *msg); + + int status; + unsigned int actual_len; + unsigned int channel; + unsigned int ttype:1; + unsigned int break_frame:1; +}; + +struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags); +void hsi_free_msg(struct hsi_msg *msg); + +/** + * struct hsi_port - HSI port device + * @device: Driver model representation of the device + * @tx_cfg: Current TX path configuration + * @rx_cfg: Current RX path configuration + * @num: Port number + * @shared: Set when port can be shared by different clients + * @claimed: Reference count of clients which claimed the port + * @lock: Serialize port claim + * @async: Asynchronous transfer callback + * @setup: Callback to set the HSI client configuration + * @flush: Callback to clean the HW state and destroy all pending transfers + * @start_tx: Callback to inform that a client wants to TX data + * @stop_tx: Callback to inform that a client no longer wishes to TX data + * @release: Callback to inform that a client no longer uses the port + * @clients: List of hsi_clients using the port. + * @clock: Lock to serialize access to the clients list. + */ +struct hsi_port { + struct device device; + struct hsi_config tx_cfg; + struct hsi_config rx_cfg; + unsigned int num; + unsigned int shared:1; + int claimed; + struct mutex lock; + int (*async)(struct hsi_msg *msg); + int (*setup)(struct hsi_client *cl); + int (*flush)(struct hsi_client *cl); + int (*start_tx)(struct hsi_client *cl); + int (*stop_tx)(struct hsi_client *cl); + int (*release)(struct hsi_client *cl); + struct list_head clients; + spinlock_t clock; +}; + +#define to_hsi_port(dev) container_of(dev, struct hsi_port, device) +#define hsi_get_port(cl) to_hsi_port((cl)->device.parent) + +void hsi_event(struct hsi_port *port, unsigned int event); +int hsi_claim_port(struct hsi_client *cl, unsigned int share); +void hsi_release_port(struct hsi_client *cl); + +static inline int hsi_port_claimed(struct hsi_client *cl) +{ + return cl->pclaimed; +} + +static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data) +{ + dev_set_drvdata(&port->device, data); +} + +static inline void *hsi_port_drvdata(struct hsi_port *port) +{ + return dev_get_drvdata(&port->device); +} + +/** + * struct hsi_controller - HSI controller device + * @device: Driver model representation of the device + * @owner: Pointer to the module owning the controller + * @id: HSI controller ID + * @num_ports: Number of ports in the HSI controller + * @port: Array of HSI ports + */ +struct hsi_controller { + struct device device; + struct module *owner; + unsigned int id; + unsigned int num_ports; + struct hsi_port *port; +}; + +#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device) + +struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags); +void hsi_free_controller(struct hsi_controller *hsi); +int hsi_register_controller(struct hsi_controller *hsi); +void hsi_unregister_controller(struct hsi_controller *hsi); + +static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi, + void *data) +{ + dev_set_drvdata(&hsi->device, data); +} + +static inline void *hsi_controller_drvdata(struct hsi_controller *hsi) +{ + return dev_get_drvdata(&hsi->device); +} + +static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi, + unsigned int num) +{ + return (num < hsi->num_ports) ? &hsi->port[num] : NULL; +} + +/* + * API for HSI clients + */ +int hsi_async(struct hsi_client *cl, struct hsi_msg *msg); + +/** + * hsi_id - Get HSI controller ID associated to a client + * @cl: Pointer to a HSI client + * + * Return the controller id where the client is attached to + */ +static inline unsigned int hsi_id(struct hsi_client *cl) +{ + return to_hsi_controller(cl->device.parent->parent)->id; +} + +/** + * hsi_port_id - Gets the port number a client is attached to + * @cl: Pointer to HSI client + * + * Return the port number associated to the client + */ +static inline unsigned int hsi_port_id(struct hsi_client *cl) +{ + return to_hsi_port(cl->device.parent)->num; +} + +/** + * hsi_setup - Configure the client's port + * @cl: Pointer to the HSI client + * + * When sharing ports, clients should either relay on a single + * client setup or have the same setup for all of them. + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_setup(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->setup(cl); +} + +/** + * hsi_flush - Flush all pending transactions on the client's port + * @cl: Pointer to the HSI client + * + * This function will destroy all pending hsi_msg in the port and reset + * the HW port so it is ready to receive and transmit from a clean state. + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_flush(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->flush(cl); +} + +/** + * hsi_async_read - Submit a read transfer + * @cl: Pointer to the HSI client + * @msg: HSI message descriptor of the transfer + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg) +{ + msg->ttype = HSI_MSG_READ; + return hsi_async(cl, msg); +} + +/** + * hsi_async_write - Submit a write transfer + * @cl: Pointer to the HSI client + * @msg: HSI message descriptor of the transfer + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg) +{ + msg->ttype = HSI_MSG_WRITE; + return hsi_async(cl, msg); +} + +/** + * hsi_start_tx - Signal the port that the client wants to start a TX + * @cl: Pointer to the HSI client + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_start_tx(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->start_tx(cl); +} + +/** + * hsi_stop_tx - Signal the port that the client no longer wants to transmit + * @cl: Pointer to the HSI client + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_stop_tx(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->stop_tx(cl); +} +#endif /* __LINUX_HSI_H__ */ -- cgit v0.10.2 From 4e69fc22753fcce1d9275b5517ef3646ffeffcf4 Mon Sep 17 00:00:00 2001 From: Andras Domokos Date: Thu, 30 Sep 2010 17:18:53 +0300 Subject: HSI: hsi_char: Add HSI char device driver Add HSI char device driver to the kernel. Signed-off-by: Andras Domokos Signed-off-by: Carlos Chinea diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c new file mode 100644 index 0000000..88a050d --- /dev/null +++ b/drivers/hsi/clients/hsi_char.c @@ -0,0 +1,802 @@ +/* + * HSI character device driver, implements the character device + * interface. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Andras Domokos + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HSC_DEVS 16 /* Num of channels */ +#define HSC_MSGS 4 + +#define HSC_RXBREAK 0 + +#define HSC_ID_BITS 6 +#define HSC_PORT_ID_BITS 4 +#define HSC_ID_MASK 3 +#define HSC_PORT_ID_MASK 3 +#define HSC_CH_MASK 0xf + +/* + * We support up to 4 controllers that can have up to 4 + * ports, which should currently be more than enough. + */ +#define HSC_BASEMINOR(id, port_id) \ + ((((id) & HSC_ID_MASK) << HSC_ID_BITS) | \ + (((port_id) & HSC_PORT_ID_MASK) << HSC_PORT_ID_BITS)) + +enum { + HSC_CH_OPEN, + HSC_CH_READ, + HSC_CH_WRITE, + HSC_CH_WLINE, +}; + +enum { + HSC_RX, + HSC_TX, +}; + +struct hsc_client_data; +/** + * struct hsc_channel - hsi_char internal channel data + * @ch: channel number + * @flags: Keeps state of the channel (open/close, reading, writing) + * @free_msgs_list: List of free HSI messages/requests + * @rx_msgs_queue: List of pending RX requests + * @tx_msgs_queue: List of pending TX requests + * @lock: Serialize access to the lists + * @cl: reference to the associated hsi_client + * @cl_data: reference to the client data that this channels belongs to + * @rx_wait: RX requests wait queue + * @tx_wait: TX requests wait queue + */ +struct hsc_channel { + unsigned int ch; + unsigned long flags; + struct list_head free_msgs_list; + struct list_head rx_msgs_queue; + struct list_head tx_msgs_queue; + spinlock_t lock; + struct hsi_client *cl; + struct hsc_client_data *cl_data; + wait_queue_head_t rx_wait; + wait_queue_head_t tx_wait; +}; + +/** + * struct hsc_client_data - hsi_char internal client data + * @cdev: Characther device associated to the hsi_client + * @lock: Lock to serialize open/close access + * @flags: Keeps track of port state (rx hwbreak armed) + * @usecnt: Use count for claiming the HSI port (mutex protected) + * @cl: Referece to the HSI client + * @channels: Array of channels accessible by the client + */ +struct hsc_client_data { + struct cdev cdev; + struct mutex lock; + unsigned long flags; + unsigned int usecnt; + struct hsi_client *cl; + struct hsc_channel channels[HSC_DEVS]; +}; + +/* Stores the major number dynamically allocated for hsi_char */ +static unsigned int hsc_major; +/* Maximum buffer size that hsi_char will accept from userspace */ +static unsigned int max_data_size = 0x1000; +module_param(max_data_size, uint, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)"); + +static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg, + struct list_head *queue) +{ + unsigned long flags; + + spin_lock_irqsave(&channel->lock, flags); + list_add_tail(&msg->link, queue); + spin_unlock_irqrestore(&channel->lock, flags); +} + +static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel, + struct list_head *queue) +{ + struct hsi_msg *msg = NULL; + unsigned long flags; + + spin_lock_irqsave(&channel->lock, flags); + + if (list_empty(queue)) + goto out; + + msg = list_first_entry(queue, struct hsi_msg, link); + list_del(&msg->link); +out: + spin_unlock_irqrestore(&channel->lock, flags); + + return msg; +} + +static inline void hsc_msg_free(struct hsi_msg *msg) +{ + kfree(sg_virt(msg->sgt.sgl)); + hsi_free_msg(msg); +} + +static void hsc_free_list(struct list_head *list) +{ + struct hsi_msg *msg, *tmp; + + list_for_each_entry_safe(msg, tmp, list, link) { + list_del(&msg->link); + hsc_msg_free(msg); + } +} + +static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l) +{ + unsigned long flags; + LIST_HEAD(list); + + spin_lock_irqsave(&channel->lock, flags); + list_splice_init(l, &list); + spin_unlock_irqrestore(&channel->lock, flags); + + hsc_free_list(&list); +} + +static inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size) +{ + struct hsi_msg *msg; + void *buf; + + msg = hsi_alloc_msg(1, GFP_KERNEL); + if (!msg) + goto out; + buf = kmalloc(alloc_size, GFP_KERNEL); + if (!buf) { + hsi_free_msg(msg); + goto out; + } + sg_init_one(msg->sgt.sgl, buf, alloc_size); + /* Ignore false positive, due to sg pointer handling */ + kmemleak_ignore(buf); + + return msg; +out: + return NULL; +} + +static inline int hsc_msgs_alloc(struct hsc_channel *channel) +{ + struct hsi_msg *msg; + int i; + + for (i = 0; i < HSC_MSGS; i++) { + msg = hsc_msg_alloc(max_data_size); + if (!msg) + goto out; + msg->channel = channel->ch; + list_add_tail(&msg->link, &channel->free_msgs_list); + } + + return 0; +out: + hsc_free_list(&channel->free_msgs_list); + + return -ENOMEM; +} + +static inline unsigned int hsc_msg_len_get(struct hsi_msg *msg) +{ + return msg->sgt.sgl->length; +} + +static inline void hsc_msg_len_set(struct hsi_msg *msg, unsigned int len) +{ + msg->sgt.sgl->length = len; +} + +static void hsc_rx_completed(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + struct hsc_channel *channel = cl_data->channels + msg->channel; + + if (test_bit(HSC_CH_READ, &channel->flags)) { + hsc_add_tail(channel, msg, &channel->rx_msgs_queue); + wake_up(&channel->rx_wait); + } else { + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +} + +static void hsc_rx_msg_destructor(struct hsi_msg *msg) +{ + msg->status = HSI_STATUS_ERROR; + hsc_msg_len_set(msg, 0); + hsc_rx_completed(msg); +} + +static void hsc_tx_completed(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + struct hsc_channel *channel = cl_data->channels + msg->channel; + + if (test_bit(HSC_CH_WRITE, &channel->flags)) { + hsc_add_tail(channel, msg, &channel->tx_msgs_queue); + wake_up(&channel->tx_wait); + } else { + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +} + +static void hsc_tx_msg_destructor(struct hsi_msg *msg) +{ + msg->status = HSI_STATUS_ERROR; + hsc_msg_len_set(msg, 0); + hsc_tx_completed(msg); +} + +static void hsc_break_req_destructor(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + + hsi_free_msg(msg); + clear_bit(HSC_RXBREAK, &cl_data->flags); +} + +static void hsc_break_received(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + struct hsc_channel *channel = cl_data->channels; + int i, ret; + + /* Broadcast HWBREAK on all channels */ + for (i = 0; i < HSC_DEVS; i++, channel++) { + struct hsi_msg *msg2; + + if (!test_bit(HSC_CH_READ, &channel->flags)) + continue; + msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list); + if (!msg2) + continue; + clear_bit(HSC_CH_READ, &channel->flags); + hsc_msg_len_set(msg2, 0); + msg2->status = HSI_STATUS_COMPLETED; + hsc_add_tail(channel, msg2, &channel->rx_msgs_queue); + wake_up(&channel->rx_wait); + } + hsi_flush(msg->cl); + ret = hsi_async_read(msg->cl, msg); + if (ret < 0) + hsc_break_req_destructor(msg); +} + +static int hsc_break_request(struct hsi_client *cl) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(cl); + struct hsi_msg *msg; + int ret; + + if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags)) + return -EBUSY; + + msg = hsi_alloc_msg(0, GFP_KERNEL); + if (!msg) { + clear_bit(HSC_RXBREAK, &cl_data->flags); + return -ENOMEM; + } + msg->break_frame = 1; + msg->complete = hsc_break_received; + msg->destructor = hsc_break_req_destructor; + ret = hsi_async_read(cl, msg); + if (ret < 0) + hsc_break_req_destructor(msg); + + return ret; +} + +static int hsc_break_send(struct hsi_client *cl) +{ + struct hsi_msg *msg; + int ret; + + msg = hsi_alloc_msg(0, GFP_ATOMIC); + if (!msg) + return -ENOMEM; + msg->break_frame = 1; + msg->complete = hsi_free_msg; + msg->destructor = hsi_free_msg; + ret = hsi_async_write(cl, msg); + if (ret < 0) + hsi_free_msg(msg); + + return ret; +} + +static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc) +{ + struct hsi_config tmp; + int ret; + + if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME)) + return -EINVAL; + if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS)) + return -EINVAL; + if (rxc->channels & (rxc->channels - 1)) + return -EINVAL; + if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE)) + return -EINVAL; + tmp = cl->rx_cfg; + cl->rx_cfg.mode = rxc->mode; + cl->rx_cfg.channels = rxc->channels; + cl->rx_cfg.flow = rxc->flow; + ret = hsi_setup(cl); + if (ret < 0) { + cl->rx_cfg = tmp; + return ret; + } + if (rxc->mode == HSI_MODE_FRAME) + hsc_break_request(cl); + + return ret; +} + +static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc) +{ + rxc->mode = cl->rx_cfg.mode; + rxc->channels = cl->rx_cfg.channels; + rxc->flow = cl->rx_cfg.flow; +} + +static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc) +{ + struct hsi_config tmp; + int ret; + + if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME)) + return -EINVAL; + if ((txc->channels == 0) || (txc->channels > HSC_DEVS)) + return -EINVAL; + if (txc->channels & (txc->channels - 1)) + return -EINVAL; + if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO)) + return -EINVAL; + tmp = cl->tx_cfg; + cl->tx_cfg.mode = txc->mode; + cl->tx_cfg.channels = txc->channels; + cl->tx_cfg.speed = txc->speed; + cl->tx_cfg.arb_mode = txc->arb_mode; + ret = hsi_setup(cl); + if (ret < 0) { + cl->tx_cfg = tmp; + return ret; + } + + return ret; +} + +static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc) +{ + txc->mode = cl->tx_cfg.mode; + txc->channels = cl->tx_cfg.channels; + txc->speed = cl->tx_cfg.speed; + txc->arb_mode = cl->tx_cfg.arb_mode; +} + +static ssize_t hsc_read(struct file *file, char __user *buf, size_t len, + loff_t *ppos __maybe_unused) +{ + struct hsc_channel *channel = file->private_data; + struct hsi_msg *msg; + ssize_t ret; + + if (len == 0) + return 0; + if (!IS_ALIGNED(len, sizeof(u32))) + return -EINVAL; + if (len > max_data_size) + len = max_data_size; + if (channel->ch >= channel->cl->rx_cfg.channels) + return -ECHRNG; + if (test_and_set_bit(HSC_CH_READ, &channel->flags)) + return -EBUSY; + msg = hsc_get_first_msg(channel, &channel->free_msgs_list); + if (!msg) { + ret = -ENOSPC; + goto out; + } + hsc_msg_len_set(msg, len); + msg->complete = hsc_rx_completed; + msg->destructor = hsc_rx_msg_destructor; + ret = hsi_async_read(channel->cl, msg); + if (ret < 0) { + hsc_add_tail(channel, msg, &channel->free_msgs_list); + goto out; + } + + ret = wait_event_interruptible(channel->rx_wait, + !list_empty(&channel->rx_msgs_queue)); + if (ret < 0) { + clear_bit(HSC_CH_READ, &channel->flags); + hsi_flush(channel->cl); + return -EINTR; + } + + msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue); + if (msg) { + if (msg->status != HSI_STATUS_ERROR) { + ret = copy_to_user((void __user *)buf, + sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg)); + if (ret) + ret = -EFAULT; + else + ret = hsc_msg_len_get(msg); + } else { + ret = -EIO; + } + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +out: + clear_bit(HSC_CH_READ, &channel->flags); + + return ret; +} + +static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len, + loff_t *ppos __maybe_unused) +{ + struct hsc_channel *channel = file->private_data; + struct hsi_msg *msg; + ssize_t ret; + + if ((len == 0) || !IS_ALIGNED(len, sizeof(u32))) + return -EINVAL; + if (len > max_data_size) + len = max_data_size; + if (channel->ch >= channel->cl->tx_cfg.channels) + return -ECHRNG; + if (test_and_set_bit(HSC_CH_WRITE, &channel->flags)) + return -EBUSY; + msg = hsc_get_first_msg(channel, &channel->free_msgs_list); + if (!msg) { + clear_bit(HSC_CH_WRITE, &channel->flags); + return -ENOSPC; + } + if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) { + ret = -EFAULT; + goto out; + } + hsc_msg_len_set(msg, len); + msg->complete = hsc_tx_completed; + msg->destructor = hsc_tx_msg_destructor; + ret = hsi_async_write(channel->cl, msg); + if (ret < 0) + goto out; + + ret = wait_event_interruptible(channel->tx_wait, + !list_empty(&channel->tx_msgs_queue)); + if (ret < 0) { + clear_bit(HSC_CH_WRITE, &channel->flags); + hsi_flush(channel->cl); + return -EINTR; + } + + msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue); + if (msg) { + if (msg->status == HSI_STATUS_ERROR) + ret = -EIO; + else + ret = hsc_msg_len_get(msg); + + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +out: + clear_bit(HSC_CH_WRITE, &channel->flags); + + return ret; +} + +static long hsc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct hsc_channel *channel = file->private_data; + unsigned int state; + struct hsc_rx_config rxc; + struct hsc_tx_config txc; + long ret = 0; + + switch (cmd) { + case HSC_RESET: + hsi_flush(channel->cl); + break; + case HSC_SET_PM: + if (copy_from_user(&state, (void __user *)arg, sizeof(state))) + return -EFAULT; + if (state == HSC_PM_DISABLE) { + if (test_and_set_bit(HSC_CH_WLINE, &channel->flags)) + return -EINVAL; + ret = hsi_start_tx(channel->cl); + } else if (state == HSC_PM_ENABLE) { + if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags)) + return -EINVAL; + ret = hsi_stop_tx(channel->cl); + } else { + ret = -EINVAL; + } + break; + case HSC_SEND_BREAK: + return hsc_break_send(channel->cl); + case HSC_SET_RX: + if (copy_from_user(&rxc, (void __user *)arg, sizeof(rxc))) + return -EFAULT; + return hsc_rx_set(channel->cl, &rxc); + case HSC_GET_RX: + hsc_rx_get(channel->cl, &rxc); + if (copy_to_user((void __user *)arg, &rxc, sizeof(rxc))) + return -EFAULT; + break; + case HSC_SET_TX: + if (copy_from_user(&txc, (void __user *)arg, sizeof(txc))) + return -EFAULT; + return hsc_tx_set(channel->cl, &txc); + case HSC_GET_TX: + hsc_tx_get(channel->cl, &txc); + if (copy_to_user((void __user *)arg, &txc, sizeof(txc))) + return -EFAULT; + break; + default: + return -ENOIOCTLCMD; + } + + return ret; +} + +static inline void __hsc_port_release(struct hsc_client_data *cl_data) +{ + BUG_ON(cl_data->usecnt == 0); + + if (--cl_data->usecnt == 0) { + hsi_flush(cl_data->cl); + hsi_release_port(cl_data->cl); + } +} + +static int hsc_open(struct inode *inode, struct file *file) +{ + struct hsc_client_data *cl_data; + struct hsc_channel *channel; + int ret = 0; + + pr_debug("open, minor = %d\n", iminor(inode)); + + cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev); + mutex_lock(&cl_data->lock); + channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK); + + if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) { + ret = -EBUSY; + goto out; + } + /* + * Check if we have already claimed the port associated to the HSI + * client. If not then try to claim it, else increase its refcount + */ + if (cl_data->usecnt == 0) { + ret = hsi_claim_port(cl_data->cl, 0); + if (ret < 0) + goto out; + hsi_setup(cl_data->cl); + } + cl_data->usecnt++; + + ret = hsc_msgs_alloc(channel); + if (ret < 0) { + __hsc_port_release(cl_data); + goto out; + } + + file->private_data = channel; + mutex_unlock(&cl_data->lock); + + return ret; +out: + mutex_unlock(&cl_data->lock); + + return ret; +} + +static int hsc_release(struct inode *inode __maybe_unused, struct file *file) +{ + struct hsc_channel *channel = file->private_data; + struct hsc_client_data *cl_data = channel->cl_data; + + mutex_lock(&cl_data->lock); + file->private_data = NULL; + if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags)) + hsi_stop_tx(channel->cl); + __hsc_port_release(cl_data); + hsc_reset_list(channel, &channel->rx_msgs_queue); + hsc_reset_list(channel, &channel->tx_msgs_queue); + hsc_reset_list(channel, &channel->free_msgs_list); + clear_bit(HSC_CH_READ, &channel->flags); + clear_bit(HSC_CH_WRITE, &channel->flags); + clear_bit(HSC_CH_OPEN, &channel->flags); + wake_up(&channel->rx_wait); + wake_up(&channel->tx_wait); + mutex_unlock(&cl_data->lock); + + return 0; +} + +static const struct file_operations hsc_fops = { + .owner = THIS_MODULE, + .read = hsc_read, + .write = hsc_write, + .unlocked_ioctl = hsc_ioctl, + .open = hsc_open, + .release = hsc_release, +}; + +static void __devinit hsc_channel_init(struct hsc_channel *channel) +{ + init_waitqueue_head(&channel->rx_wait); + init_waitqueue_head(&channel->tx_wait); + spin_lock_init(&channel->lock); + INIT_LIST_HEAD(&channel->free_msgs_list); + INIT_LIST_HEAD(&channel->rx_msgs_queue); + INIT_LIST_HEAD(&channel->tx_msgs_queue); +} + +static int __devinit hsc_probe(struct device *dev) +{ + const char devname[] = "hsi_char"; + struct hsc_client_data *cl_data; + struct hsc_channel *channel; + struct hsi_client *cl = to_hsi_client(dev); + unsigned int hsc_baseminor; + dev_t hsc_dev; + int ret; + int i; + + cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL); + if (!cl_data) { + dev_err(dev, "Could not allocate hsc_client_data\n"); + return -ENOMEM; + } + hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl)); + if (!hsc_major) { + ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor, + HSC_DEVS, devname); + if (ret > 0) + hsc_major = MAJOR(hsc_dev); + } else { + hsc_dev = MKDEV(hsc_major, hsc_baseminor); + ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname); + } + if (ret < 0) { + dev_err(dev, "Device %s allocation failed %d\n", + hsc_major ? "minor" : "major", ret); + goto out1; + } + mutex_init(&cl_data->lock); + hsi_client_set_drvdata(cl, cl_data); + cdev_init(&cl_data->cdev, &hsc_fops); + cl_data->cdev.owner = THIS_MODULE; + cl_data->cl = cl; + for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) { + hsc_channel_init(channel); + channel->ch = i; + channel->cl = cl; + channel->cl_data = cl_data; + } + + /* 1 hsi client -> N char devices (one for each channel) */ + ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS); + if (ret) { + dev_err(dev, "Could not add char device %d\n", ret); + goto out2; + } + + return 0; +out2: + unregister_chrdev_region(hsc_dev, HSC_DEVS); +out1: + kfree(cl_data); + + return ret; +} + +static int __devexit hsc_remove(struct device *dev) +{ + struct hsi_client *cl = to_hsi_client(dev); + struct hsc_client_data *cl_data = hsi_client_drvdata(cl); + dev_t hsc_dev = cl_data->cdev.dev; + + cdev_del(&cl_data->cdev); + unregister_chrdev_region(hsc_dev, HSC_DEVS); + hsi_client_set_drvdata(cl, NULL); + kfree(cl_data); + + return 0; +} + +static struct hsi_client_driver hsc_driver = { + .driver = { + .name = "hsi_char", + .owner = THIS_MODULE, + .probe = hsc_probe, + .remove = __devexit_p(hsc_remove), + }, +}; + +static int __init hsc_init(void) +{ + int ret; + + if ((max_data_size < 4) || (max_data_size > 0x10000) || + (max_data_size & (max_data_size - 1))) { + pr_err("Invalid max read/write data size"); + return -EINVAL; + } + + ret = hsi_register_client_driver(&hsc_driver); + if (ret) { + pr_err("Error while registering HSI/SSI driver %d", ret); + return ret; + } + + pr_info("HSI/SSI char device loaded\n"); + + return 0; +} +module_init(hsc_init); + +static void __exit hsc_exit(void) +{ + hsi_unregister_client_driver(&hsc_driver); + pr_info("HSI char device removed\n"); +} +module_exit(hsc_exit); + +MODULE_AUTHOR("Andras Domokos "); +MODULE_ALIAS("hsi:hsi_char"); +MODULE_DESCRIPTION("HSI character device"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/hsi/hsi_char.h b/include/linux/hsi/hsi_char.h new file mode 100644 index 0000000..76160b4 --- /dev/null +++ b/include/linux/hsi/hsi_char.h @@ -0,0 +1,63 @@ +/* + * Part of the HSI character device driver. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Andras Domokos + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + + +#ifndef __HSI_CHAR_H +#define __HSI_CHAR_H + +#define HSI_CHAR_MAGIC 'k' +#define HSC_IOW(num, dtype) _IOW(HSI_CHAR_MAGIC, num, dtype) +#define HSC_IOR(num, dtype) _IOR(HSI_CHAR_MAGIC, num, dtype) +#define HSC_IOWR(num, dtype) _IOWR(HSI_CHAR_MAGIC, num, dtype) +#define HSC_IO(num) _IO(HSI_CHAR_MAGIC, num) + +#define HSC_RESET HSC_IO(16) +#define HSC_SET_PM HSC_IO(17) +#define HSC_SEND_BREAK HSC_IO(18) +#define HSC_SET_RX HSC_IOW(19, struct hsc_rx_config) +#define HSC_GET_RX HSC_IOW(20, struct hsc_rx_config) +#define HSC_SET_TX HSC_IOW(21, struct hsc_tx_config) +#define HSC_GET_TX HSC_IOW(22, struct hsc_tx_config) + +#define HSC_PM_DISABLE 0 +#define HSC_PM_ENABLE 1 + +#define HSC_MODE_STREAM 1 +#define HSC_MODE_FRAME 2 +#define HSC_FLOW_SYNC 0 +#define HSC_ARB_RR 0 +#define HSC_ARB_PRIO 1 + +struct hsc_rx_config { + uint32_t mode; + uint32_t flow; + uint32_t channels; +}; + +struct hsc_tx_config { + uint32_t mode; + uint32_t channels; + uint32_t speed; + uint32_t arb_mode; +}; + +#endif /* __HSI_CHAR_H */ -- cgit v0.10.2 From f9e402016de91c2444e46ecfd706880969b1ae9e Mon Sep 17 00:00:00 2001 From: Andras Domokos Date: Wed, 21 Apr 2010 12:04:21 +0300 Subject: HSI: hsi_char: Add HSI char device kernel configuration Add HSI character device kernel configuration Signed-off-by: Andras Domokos Signed-off-by: Carlos Chinea diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig index 937062e..d94e38d 100644 --- a/drivers/hsi/Kconfig +++ b/drivers/hsi/Kconfig @@ -14,4 +14,6 @@ config HSI_BOARDINFO bool default y +source "drivers/hsi/clients/Kconfig" + endif # HSI diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile index ed94a3a..9d5d33f 100644 --- a/drivers/hsi/Makefile +++ b/drivers/hsi/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o obj-$(CONFIG_HSI) += hsi.o +obj-y += clients/ diff --git a/drivers/hsi/clients/Kconfig b/drivers/hsi/clients/Kconfig new file mode 100644 index 0000000..3bacd27 --- /dev/null +++ b/drivers/hsi/clients/Kconfig @@ -0,0 +1,13 @@ +# +# HSI clients configuration +# + +comment "HSI clients" + +config HSI_CHAR + tristate "HSI/SSI character driver" + depends on HSI + ---help--- + If you say Y here, you will enable the HSI/SSI character driver. + This driver provides a simple character device interface for + serial communication with the cellular modem over HSI/SSI bus. diff --git a/drivers/hsi/clients/Makefile b/drivers/hsi/clients/Makefile new file mode 100644 index 0000000..327c0e2 --- /dev/null +++ b/drivers/hsi/clients/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for HSI clients +# + +obj-$(CONFIG_HSI_CHAR) += hsi_char.o diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 619b565..3171939 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -3,6 +3,7 @@ header-y += can/ header-y += caif/ header-y += dvb/ header-y += hdlc/ +header-y += hsi/ header-y += isdn/ header-y += mmc/ header-y += nfsd/ diff --git a/include/linux/hsi/Kbuild b/include/linux/hsi/Kbuild new file mode 100644 index 0000000..271a770 --- /dev/null +++ b/include/linux/hsi/Kbuild @@ -0,0 +1 @@ +header-y += hsi_char.h -- cgit v0.10.2 From a4ac73a701288f633fbf2369ffaae4841aa295b3 Mon Sep 17 00:00:00 2001 From: Carlos Chinea Date: Thu, 29 Apr 2010 13:19:06 +0300 Subject: HSI: Add HSI API documentation Add an entry for HSI in the device-drivers section of the kernel documentation. Signed-off-by: Carlos Chinea diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index b638e50..5f70f73 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -437,4 +437,21 @@ X!Idrivers/video/console/fonts.c !Edrivers/i2c/i2c-core.c + + High Speed Synchronous Serial Interface (HSI) + + + High Speed Synchronous Serial Interface (HSI) is a + serial interface mainly used for connecting application + engines (APE) with cellular modem engines (CMT) in cellular + handsets. + + HSI provides multiplexing for up to 16 logical channels, + low-latency and full duplex communication. + + +!Iinclude/linux/hsi/hsi.h +!Edrivers/hsi/hsi.c + + -- cgit v0.10.2 From 43139a61fc68f4b0af7327a0e63f340a7c81c69a Mon Sep 17 00:00:00 2001 From: Andras Domokos Date: Thu, 6 May 2010 15:10:47 +0300 Subject: HSI: hsi_char: Update ioctl-number.txt Added ioctl range for HSI char devices to the documentation Signed-off-by: Andras Domokos Signed-off-by: Carlos Chinea diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 54078ed..af76fde 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -223,6 +223,7 @@ Code Seq#(hex) Include File Comments 'j' 00-3F linux/joystick.h 'k' 00-0F linux/spi/spidev.h conflict! 'k' 00-05 video/kyro.h conflict! +'k' 10-17 linux/hsi/hsi_char.h HSI character device 'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system 'l' 40-7F linux/udf_fs_i.h in development: -- cgit v0.10.2 From 387ca5bf4fe2297c93869b6f639afa8d849fb877 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 12 Mar 2012 04:29:58 -0600 Subject: ARM: OMAP: hwmod: Use sysc_fields->srst_shift and get rid of hardcoded SYSC_TYPE2_SOFTRESET_MASK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is useful when we have broken type2 compliant IPs' where the softreset shift is not the same as SYSC_TYPE2_SOFTRESET_SHIFT and hence is overridden using sysc_fields->srst_shift. We have at least one such instance now with onchip keypad on OMAP5 which has a different softreset shift as compared to other type2 IPs'. Signed-off-by: Rajendra Nayak Cc: Paul Walmsley Cc: Benoit Cousson Cc: Balaji TK Tested-by: Sourav Poddar Acked-by: Benoît Cousson Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index eba6cd3..f9b9bb9 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1395,7 +1395,7 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name) */ static int _ocp_softreset(struct omap_hwmod *oh) { - u32 v; + u32 v, softrst_mask; int c = 0; int ret = 0; @@ -1427,11 +1427,13 @@ static int _ocp_softreset(struct omap_hwmod *oh) oh->class->sysc->syss_offs) & SYSS_RESETDONE_MASK), MAX_MODULE_SOFTRESET_WAIT, c); - else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) + else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { + softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift); omap_test_timeout(!(omap_hwmod_read(oh, oh->class->sysc->sysc_offs) - & SYSC_TYPE2_SOFTRESET_MASK), + & softrst_mask), MAX_MODULE_SOFTRESET_WAIT, c); + } if (c == MAX_MODULE_SOFTRESET_WAIT) pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", -- cgit v0.10.2 From 553e322282655f213d131903ce7019aa25880273 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 12 Mar 2012 04:30:02 -0600 Subject: ARM: OMAP4: prm: fix interrupt register offsets Previous code used wrong instance for the interrupt register access. Use the right one which is OCP_SOCKET. Signed-off-by: Tero Kristo Cc: Paul Walmsley Reviewed-by: Santosh Shilimkar Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index a1d6154..fbc597f 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -146,8 +146,9 @@ static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs) u32 mask, st; /* XXX read mask from RAM? */ - mask = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, irqen_offs); - st = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, irqst_offs); + mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, + irqen_offs); + st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs); return mask & st; } @@ -179,7 +180,7 @@ void omap44xx_prm_read_pending_irqs(unsigned long *events) */ void omap44xx_prm_ocp_barrier(void) { - omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_REVISION_PRM_OFFSET); } @@ -197,19 +198,19 @@ void omap44xx_prm_ocp_barrier(void) void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask) { saved_mask[0] = - omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_PRM_IRQSTATUS_MPU_OFFSET); saved_mask[1] = - omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET); - omap4_prm_write_inst_reg(0, OMAP4430_PRM_DEVICE_INST, + omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_PRM_IRQENABLE_MPU_OFFSET); - omap4_prm_write_inst_reg(0, OMAP4430_PRM_DEVICE_INST, + omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_PRM_IRQENABLE_MPU_2_OFFSET); /* OCP barrier */ - omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_REVISION_PRM_OFFSET); } @@ -225,9 +226,9 @@ void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask) */ void omap44xx_prm_restore_irqen(u32 *saved_mask) { - omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_DEVICE_INST, + omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_PRM_IRQENABLE_MPU_OFFSET); - omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_DEVICE_INST, + omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_OCP_SOCKET_INST, OMAP4_PRM_IRQENABLE_MPU_2_OFFSET); } -- cgit v0.10.2 From c29f40ca19b8ca284a2d1415e26b802bc9b2fb67 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 6 Mar 2012 07:52:38 +0000 Subject: ixgbe: Fix issues with SR-IOV loopback when flow control is disabled This patch allows us to avoid a Tx hang when SR-IOV is enabled. This hang can be triggered by sending small packets at a rate that was triggering Rx missed errors from the adapter while the internal Tx switch and at least one VF are enabled. This was all due to the fact that under heavy stress the Rx FIFO never drained below the flow control high water mark. This resulted in the Tx FIFO being head of line blocked due to the fact that it relies on the flow control high water mark to determine when it is acceptable for the Tx to place a packet in the Rx FIFO. The resolution for this is to set the FCRTH value to the RXPBSIZE - 32 so that even if the ring is almost completely full we can still place Tx packets on the Rx ring and drop incoming Rx traffic if we do not have sufficient space available in the Rx FIFO. Signed-off-by: Alexander Duyck Tested-by: Sibai Li Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 383b941..7d81bee 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -2011,13 +2011,20 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num) IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); - fcrth = hw->fc.high_water[packetbuf_num] << 10; fcrtl = hw->fc.low_water << 10; if (hw->fc.current_mode & ixgbe_fc_tx_pause) { + fcrth = hw->fc.high_water[packetbuf_num] << 10; fcrth |= IXGBE_FCRTH_FCEN; if (hw->fc.send_xon) fcrtl |= IXGBE_FCRTL_XONE; + } else { + /* + * If Tx flow control is disabled, set our high water mark + * to Rx FIFO size minus 32 in order prevent Tx switch + * loopback from stalling on DMA. + */ + fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)) - 32; } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth); -- cgit v0.10.2 From 0646819cd31786f4b024d0056f73adf460be40aa Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 16 Mar 2012 00:18:49 +0000 Subject: net: do not do gso for CHECKSUM_UNNECESSARY in netif_needs_gso This is related to fixing the bug of dropping FCoE frames when disabling tx ip checksum by 'ethtool -K ethx tx off'. The FCoE protocol stack driver would use CHECKSUM_UNNECESSARY on tx path instead of CHECKSUM_PARTIAL (as indicated in the 2/2 of this series). To do so, netif_needs_gso() has to be changed here to not do gso for both CHECKSUM_PARTIAL and CHECKSUM_UNNECESSARY. Ref. to original discussion thread: http://patchwork.ozlabs.org/patch/146567/ Signed-off-by: Yi Zou Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0eac07c..c1b2b5f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2636,7 +2636,8 @@ static inline int netif_needs_gso(struct sk_buff *skb, netdev_features_t features) { return skb_is_gso(skb) && (!skb_gso_ok(skb, features) || - unlikely(skb->ip_summed != CHECKSUM_PARTIAL)); + unlikely((skb->ip_summed != CHECKSUM_PARTIAL) && + (skb->ip_summed != CHECKSUM_UNNECESSARY))); } static inline void netif_set_gso_max_size(struct net_device *dev, -- cgit v0.10.2 From c98291ee1ceac03912e24b3219fa6e7dc0d52f5e Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 16 Mar 2012 00:18:54 +0000 Subject: fcoe: use CHECKSUM_UNNECESSARY instead of CHECKSUM_PARTIAL on tx Fix a bug when using 'ethtool -K ethx tx off' to turn off tx ip checksum, FCoE CRC offload should not be impacte. The skb_checksum_help() is needed only if it's not FCoE traffic for ip checksum, regardless of ethtool toggling the tx ip checksum on or off. Instead of using CHECKSUM_PARTIAL, we will use CHECKSUM_UNNECESSARY as a proper indication to avoid sw ip checksum on FCoE frames. Ref. to original discussion thread: http://patchwork.ozlabs.org/patch/146567/ CC: "James E.J. Bottomley" CC: Robert Love Signed-off-by: Yi Zou Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index e959960..c164890 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1498,7 +1498,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) /* crc offload */ if (likely(lport->crc_offload)) { - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_UNNECESSARY; skb->csum_start = skb_headroom(skb); skb->csum_offset = skb->len; crc = 0; -- cgit v0.10.2 From 68523f4233de5f233478dde0a63047b4efb710b8 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 12 Mar 2012 20:34:45 +0530 Subject: ARM: OMAP4: Workaround the OCP synchronisation issue with 32K synctimer. On OMAP4, recently a synchronisation bug is discovered by hardware team, which leads to incorrect timer value read from 32K sync timer IP when the IP is comming out of idle. The issue is due to the synchronization methodology used in the SYNCTIMER IP. The value of the counter register in 32kHz domain is synchronized to the OCP domain register only at count up event, and if the OCP clock is switched off, the OCP register gets out of synch until the first count up event after the clock is switched back -at the next falling edge of the 32kHz clock. Further investigation revealed that it applies to gptimer1 and watchdog timer2 as well which may run on 32KHz. This patch fixes the issue for all the applicable modules. The BUG has not made it yet to the OMAP errata list and it is applicable to OMAP1/2/3/4/5. OMAP1/2/3 it is taken care indirectly by autodeps. By enabling static depedency of wakeup clockdomain with MPU, as soon as MPU is woken up from lowpower state(idle) or whenever MPU is active, PRCM forces the OCP clock to be running and allow the counter value to be updated properly in the OCP clock domain. The bug is going to fixed in future OMAP versions. Reported-Tested-by: dave.long@linaro.org [dave.long@linaro.org: Reported the oprofile time stamp issue with synctimer and helped to test this patch] Signed-off-by: Santosh Shilimkar Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index c264ef7..974f7ea 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -196,7 +196,7 @@ static void omap_default_idle(void) static int __init omap4_pm_init(void) { int ret; - struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm; + struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm, *l4wkup; struct clockdomain *ducati_clkdm, *l3_2_clkdm, *l4_per_clkdm; if (!cpu_is_omap44xx()) @@ -220,14 +220,19 @@ static int __init omap4_pm_init(void) * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as * expected. The hardware recommendation is to enable static * dependencies for these to avoid system lock ups or random crashes. + * The L4 wakeup depedency is added to workaround the OCP sync hardware + * BUG with 32K synctimer which lead to incorrect timer value read + * from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which + * are part of L4 wakeup clockdomain. */ mpuss_clkdm = clkdm_lookup("mpuss_clkdm"); emif_clkdm = clkdm_lookup("l3_emif_clkdm"); l3_1_clkdm = clkdm_lookup("l3_1_clkdm"); l3_2_clkdm = clkdm_lookup("l3_2_clkdm"); l4_per_clkdm = clkdm_lookup("l4_per_clkdm"); + l4wkup = clkdm_lookup("l4_wkup_clkdm"); ducati_clkdm = clkdm_lookup("ducati_clkdm"); - if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || + if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || (!l4wkup) || (!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per_clkdm)) goto err2; @@ -235,6 +240,7 @@ static int __init omap4_pm_init(void) ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm); ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm); ret |= clkdm_add_wkdep(mpuss_clkdm, l4_per_clkdm); + ret |= clkdm_add_wkdep(mpuss_clkdm, l4wkup); ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm); ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm); if (ret) { -- cgit v0.10.2 From ce229c5d79c03f09d4612dd2bcbff532fdc24e80 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Sat, 17 Mar 2012 18:22:47 -0700 Subject: arm: omap3: pm34xx.c: Fix omap3_pm_init() error out paths It appears that the error paths were overlooked when the omap3_pm_init() routine had the prcm chain handler code added. Fix this by adding a goto target and reordering the error handling code. Also fix how the irq argument for free_irq() is determined. Signed-off-by: Mark A. Greer Acked-by: Tero Kristo Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index fc69875..c598d26 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -817,13 +817,13 @@ static int __init omap3_pm_init(void) if (ret) { pr_err("pm: Failed to request pm_io irq\n"); - goto err1; + goto err2; } ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { printk(KERN_ERR "Failed to setup powerdomains\n"); - goto err2; + goto err3; } (void) clkdm_for_each(clkdms_setup, NULL); @@ -831,7 +831,8 @@ static int __init omap3_pm_init(void) mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); if (mpu_pwrdm == NULL) { printk(KERN_ERR "Failed to get mpu_pwrdm\n"); - goto err2; + ret = -EINVAL; + goto err3; } neon_pwrdm = pwrdm_lookup("neon_pwrdm"); @@ -879,14 +880,17 @@ static int __init omap3_pm_init(void) } omap3_save_scratchpad_contents(); -err1: return ret; -err2: - free_irq(INT_34XX_PRCM_MPU_IRQ, NULL); + +err3: list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) { list_del(&pwrst->node); kfree(pwrst); } + free_irq(omap_prcm_event_to_irq("io"), omap3_pm_init); +err2: + free_irq(omap_prcm_event_to_irq("wkup"), NULL); +err1: return ret; } -- cgit v0.10.2 From 981798569b090543453baccbc0657fbcea311668 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Sat, 17 Mar 2012 18:22:48 -0700 Subject: arm: omap3: pm34xx.c: Replace printk() with appropriate pr_*() Currently, pm34xx.c has a mix of printk() and pr_*() statements so replace the printk() statements with the equivalent pr_*() statements. Signed-off-by: Mark A. Greer Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index c598d26..6aeacf6 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -166,8 +166,7 @@ static void omap3_save_secure_ram_context(void) pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state); /* Following is for error tracking, it should not happen */ if (ret) { - printk(KERN_ERR "save_secure_sram() returns %08x\n", - ret); + pr_err("save_secure_sram() returns %08x\n", ret); while (1) ; } @@ -307,7 +306,7 @@ void omap_sram_idle(void) break; default: /* Invalid state */ - printk(KERN_ERR "Invalid mpu state in sram_idle\n"); + pr_err("Invalid mpu state in sram_idle\n"); return; } @@ -463,18 +462,17 @@ restore: list_for_each_entry(pwrst, &pwrst_list, node) { state = pwrdm_read_prev_pwrst(pwrst->pwrdm); if (state > pwrst->next_state) { - printk(KERN_INFO "Powerdomain (%s) didn't enter " - "target state %d\n", + pr_info("Powerdomain (%s) didn't enter " + "target state %d\n", pwrst->pwrdm->name, pwrst->next_state); ret = -1; } omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); } if (ret) - printk(KERN_ERR "Could not enter target state in pm_suspend\n"); + pr_err("Could not enter target state in pm_suspend\n"); else - printk(KERN_INFO "Successfully put all powerdomains " - "to target state\n"); + pr_info("Successfully put all powerdomains to target state\n"); return ret; } @@ -822,7 +820,7 @@ static int __init omap3_pm_init(void) ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { - printk(KERN_ERR "Failed to setup powerdomains\n"); + pr_err("Failed to setup powerdomains\n"); goto err3; } @@ -830,7 +828,7 @@ static int __init omap3_pm_init(void) mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); if (mpu_pwrdm == NULL) { - printk(KERN_ERR "Failed to get mpu_pwrdm\n"); + pr_err("Failed to get mpu_pwrdm\n"); ret = -EINVAL; goto err3; } @@ -865,8 +863,8 @@ static int __init omap3_pm_init(void) omap3_secure_ram_storage = kmalloc(0x803F, GFP_KERNEL); if (!omap3_secure_ram_storage) - printk(KERN_ERR "Memory allocation failed when" - "allocating for secure sram context\n"); + pr_err("Memory allocation failed when " + "allocating for secure sram context\n"); local_irq_disable(); local_fiq_disable(); -- cgit v0.10.2 From 9fa2df6b90786301b175e264f5fa9846aba81a65 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Fri, 16 Mar 2012 11:19:09 -0500 Subject: ARM: OMAP2+: OPP: allow OPP enumeration to continue if device is not present On platforms such as OMAP3, certain variants may not have IVA, SGX or some specific component. We currently have a check to aid fixing wrong population of OPP entries for issues such as typos. This however causes a conflict with valid requirement where the SoC variant does not actually have the module present. So, reduce the severity of the print to a debug statement and skip registering that specific OPP, but continue down the list. Reported-by: Steve Sakoman Reported-by: Maximilian Schwerin Acked-by: Steve Sakoman Tested-by: Maximilian Schwerin Signed-off-by: Nishanth Menon Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index 9262a6b..de6d464 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -64,10 +64,10 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, } oh = omap_hwmod_lookup(opp_def->hwmod_name); if (!oh || !oh->od) { - pr_warn("%s: no hwmod or odev for %s, [%d] " + pr_debug("%s: no hwmod or odev for %s, [%d] " "cannot add OPPs.\n", __func__, opp_def->hwmod_name, i); - return -EINVAL; + continue; } dev = &oh->od->pdev->dev; -- cgit v0.10.2 From 4ba7c3c3c6567210bf46b1ab3d089134170c2762 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 22 Mar 2012 09:23:37 +0800 Subject: ARM: OMAP3+: fix oops triggered in omap_prcm_register_chain_handler(v1) This patch fixes the oops below[1]. Obviously, the count of "struct irq_chip_generic" instances to be allocated and setup should be irq_setup->nr_regs instead of irq_setup->nr_regs plus one, so just fix the iterator to avoid the oops. [1], oops log. [ 1.790242] Unable to handle kernel NULL pointer dereference at virtual address 00000004 [ 1.798632] pgd = c0004000 [ 1.801638] [00000004] *pgd=00000000 [ 1.805400] Internal error: Oops: 805 [#1] PREEMPT SMP THUMB2 [ 1.811381] Modules linked in: [ 1.814601] CPU: 1 Not tainted (3.3.0-next-20120320+ #733) [ 1.820683] PC is at irq_setup_generic_chip+0x6a/0x84 [ 1.825951] LR is at irq_get_irq_data+0x7/0x8 [ 1.830508] pc : [] lr : [] psr: 20000133 [ 1.830512] sp : ee04ff58 ip : 00000000 fp : 00000000 [ 1.842461] r10: 00000000 r9 : 00000000 r8 : 00000800 [ 1.847905] r7 : c064e260 r6 : 000001dc r5 : 00000001 r4 : ee0accc0 [ 1.854687] r3 : 00000002 r2 : 00000800 r1 : 000001dc r0 : 00000000 [ 1.861472] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA Thumb Segment kernel [ 1.869234] Control: 50c5387d Table: 8000404a DAC: 00000015 [ 1.875215] Process swapper/0 (pid: 1, stack limit = 0xee04e2f8) [ 1.881463] Stack: (0xee04ff58 to 0xee050000) [ 1.886017] ff40: c061b668 00000008 [ 1.894497] ff60: c0682090 ee0accc0 00000003 c001c637 00000000 00000000 00000201 00000000 [ 1.902976] ff80: 00000004 c0473820 c0473800 c0459e8d c0680ac0 c000866d 00000004 00000004 [ 1.911455] ffa0: ee04ffa8 00000004 c047381c 00000004 c0473820 c0473800 c0680ac0 00000082 [ 1.919934] ffc0: c0489694 c045265f 00000004 00000004 c0452135 c000d105 00000033 00000000 [ 1.928413] ffe0: c04525b5 c000d111 00000033 00000000 00000000 c000d111 aaaaaaaa aaaaaaaa [ 1.936912] [] (irq_setup_generic_chip+0x6a/0x84) from [] (omap_prcm_register_chain_handler+0x147/0x1a0) [ 1.948516] [] (omap_prcm_register_chain_handler+0x147/0x1a0) from [] (do_one_initcall+0x65/0xf4) [ 1.959500] [] (do_one_initcall+0x65/0xf4) from [] (kernel_init+0xab/0x138) [ 1.968529] [] (kernel_init+0xab/0x138) from [] (kernel_thread_exit+0x1/0x6) [ 1.977632] Code: f7ff f9d1 6b23 1af3 (6043) 086d [ 1.982684] ---[ end trace 1b75b31a2719ed1c ]--- [ 1.987526] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b Acked-by: Tero Kristo Signed-off-by: Ming Lei Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index 860118a..de58b8b 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -291,7 +291,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup) goto err; } - for (i = 0; i <= irq_setup->nr_regs; i++) { + for (i = 0; i < irq_setup->nr_regs; i++) { gc = irq_alloc_generic_chip("PRCM", 1, irq_setup->base_irq + i * 32, prm_base, handle_level_irq); -- cgit v0.10.2 From 51579137c500362018b5341f5dca47807ed558aa Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 24 Mar 2012 09:37:30 +0800 Subject: regulator: tps6586x: Fix list minimal voltage setting for LDO0 According to the datasheet, LDO0 has minimal voltage 1.2V rather than 1.25V. Table 3-39. VLDO0[2:0] Settings VLDOx[2:0] VOUT (V) VLDOx[2:0] VOUT (V) 000 1.20 100 2.70 001 1.50 101 2.85 010 1.80 110 3.10 011 2.50 111 3.30 Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 29b615c..cfc1f16 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -79,6 +79,11 @@ static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev, unsigned selector) { struct tps6586x_regulator *info = rdev_get_drvdata(rdev); + int rid = rdev_get_id(rdev); + + /* LDO0 has minimal voltage 1.2V rather than 1.25V */ + if ((rid == TPS6586X_ID_LDO_0) && (selector == 0)) + return (info->voltages[0] - 50) * 1000; return info->voltages[selector] * 1000; } -- cgit v0.10.2 From f3d229c68bb47170f04f81e51c9ed5d4286cebdb Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 7 Mar 2012 23:45:44 +0000 Subject: netfilter: xt_LOG: don't use xchg() for simple assignment At least on ia64 the (bogus) use of xchg() here results in the compiler warning about an unused expression result. As only an assignment is intended here, convert it to such. Signed-off-by: Jan Beulich Acked-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso diff --git a/include/net/netfilter/xt_log.h b/include/net/netfilter/xt_log.h index 7e1544e..9d9756c 100644 --- a/include/net/netfilter/xt_log.h +++ b/include/net/netfilter/xt_log.h @@ -47,7 +47,7 @@ static void sb_close(struct sbuff *m) if (likely(m != &emergency)) kfree(m); else { - xchg(&emergency_ptr, m); + emergency_ptr = m; local_bh_enable(); } } -- cgit v0.10.2 From 09bf14b901f2c1908b6a72fe934457acdd1fa430 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 15:53:05 +0800 Subject: regulator: Fix set and get current limit for wm831x_buckv WM831X_DC1_HC_THR_MASK is 0x0070. We need to do proper shift for setting and getting current limit. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 4904a40..3044001 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -386,7 +386,8 @@ static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev, if (i == ARRAY_SIZE(wm831x_dcdc_ilim)) return -EINVAL; - return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK, i); + return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK, + i << WM831X_DC1_HC_THR_SHIFT); } static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) @@ -400,7 +401,8 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) if (val < 0) return val; - return wm831x_dcdc_ilim[val & WM831X_DC1_HC_THR_MASK]; + val = (val & WM831X_DC1_HC_THR_MASK) >> WM831X_DC1_HC_THR_SHIFT; + return wm831x_dcdc_ilim[val]; } static struct regulator_ops wm831x_buckv_ops = { -- cgit v0.10.2 From 5777d9b34aec841429ddade56403b3f53a821a1d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 15 Mar 2012 12:49:09 +0800 Subject: regulator: Fix unbalanced lock/unlock in mc13892_regulator_probe error path We do not hold a lock while registering regulator, thus should not call unlock if regulator_register fails. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index e8cfc99..845aa22 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -552,7 +552,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) mc13xxx_lock(mc13892); ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); if (ret) - goto err_free; + goto err_unlock; /* enable switch auto mode */ if ((val & 0x0000FFFF) == 0x45d0) { @@ -562,7 +562,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) MC13892_SWITCHERS4_SW1MODE_AUTO | MC13892_SWITCHERS4_SW2MODE_AUTO); if (ret) - goto err_free; + goto err_unlock; ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5, MC13892_SWITCHERS5_SW3MODE_M | @@ -570,7 +570,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) MC13892_SWITCHERS5_SW3MODE_AUTO | MC13892_SWITCHERS5_SW4MODE_AUTO); if (ret) - goto err_free; + goto err_unlock; } mc13xxx_unlock(mc13892); @@ -612,10 +612,10 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) err: while (--i >= 0) regulator_unregister(priv->regulators[i]); + return ret; -err_free: +err_unlock: mc13xxx_unlock(mc13892); - return ret; } -- cgit v0.10.2 From eb4168158f79237498e4d3ddcef6e9436db15a4a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 06:25:05 +0800 Subject: regulator: Fix restoring pmic.dcdcx_hib_mode settings in wm8350_dcdc_set_suspend_enable What we want is to restore wm8350->pmic.dcdcx_hib_mode settings to WM8350_DCDCx_LOW_POWER registers. Current code also clears all other bits of WM8350_DCDCx_LOW_POWER registers which is wrong. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index ab1e183..1c54821 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -495,25 +495,25 @@ static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev) val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER) & ~WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER, - wm8350->pmic.dcdc1_hib_mode); + val | wm8350->pmic.dcdc1_hib_mode); break; case WM8350_DCDC_3: val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER) & ~WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER, - wm8350->pmic.dcdc3_hib_mode); + val | wm8350->pmic.dcdc3_hib_mode); break; case WM8350_DCDC_4: val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER) & ~WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER, - wm8350->pmic.dcdc4_hib_mode); + val | wm8350->pmic.dcdc4_hib_mode); break; case WM8350_DCDC_6: val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER) & ~WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER, - wm8350->pmic.dcdc6_hib_mode); + val | wm8350->pmic.dcdc6_hib_mode); break; case WM8350_DCDC_2: case WM8350_DCDC_5: -- cgit v0.10.2 From 9300928692f835f76f5604b3b51c3085977edf68 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 23 Mar 2012 06:27:10 +0800 Subject: regulator: Do proper shift to set correct bit for DC[2|5]_HIB_MODE setting DC[2|5]_HIB_MODE is BIT 12 of DCDC[2|5] Control register. WM8350_DC2_HIB_MODE_ACTIVE/WM8350_DC2_HIB_MODE_DISABLE are defined as 1/0. Thus we need to left shift WM8350_DC2_HIB_MODE_SHIFT bits. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 1c54821..ff34654 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -575,13 +575,13 @@ static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev) val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL) & ~WM8350_DC2_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val | - WM8350_DC2_HIB_MODE_ACTIVE); + (WM8350_DC2_HIB_MODE_ACTIVE << WM8350_DC2_HIB_MODE_SHIFT)); break; case WM8350_DCDC_5: val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL) - & ~WM8350_DC2_HIB_MODE_MASK; + & ~WM8350_DC5_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val | - WM8350_DC5_HIB_MODE_ACTIVE); + (WM8350_DC5_HIB_MODE_ACTIVE << WM8350_DC5_HIB_MODE_SHIFT)); break; default: return -EINVAL; @@ -600,13 +600,13 @@ static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev) val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL) & ~WM8350_DC2_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val | - WM8350_DC2_HIB_MODE_DISABLE); + (WM8350_DC2_HIB_MODE_DISABLE << WM8350_DC2_HIB_MODE_SHIFT)); break; case WM8350_DCDC_5: val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL) - & ~WM8350_DC2_HIB_MODE_MASK; + & ~WM8350_DC5_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val | - WM8350_DC2_HIB_MODE_DISABLE); + (WM8350_DC5_HIB_MODE_DISABLE << WM8350_DC5_HIB_MODE_SHIFT)); break; default: return -EINVAL; -- cgit v0.10.2 From 5276e16bb6f35412583518d6f04651dd9dc114be Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 14 Jan 2012 17:38:55 +0100 Subject: netfilter: ipset: avoid use of kernel-only types When using the xt_set.h header in userspace, one will get these gcc reports: ipset/ip_set.h:184:1: error: unknown type name "u16" In file included from libxt_SET.c:21:0: netfilter/xt_set.h:61:2: error: unknown type name "u32" netfilter/xt_set.h:62:2: error: unknown type name "u32" Signed-off-by: Jan Engelhardt Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h index c0405ac..e3a9978 100644 --- a/include/linux/netfilter/xt_set.h +++ b/include/linux/netfilter/xt_set.h @@ -58,8 +58,8 @@ struct xt_set_info_target_v1 { struct xt_set_info_target_v2 { struct xt_set_info add_set; struct xt_set_info del_set; - u32 flags; - u32 timeout; + __u32 flags; + __u32 timeout; }; #endif /*_XT_SET_H*/ -- cgit v0.10.2 From 883a649b737cdbe3ede7e50f3f939fd706ed5c4e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 13 Mar 2012 16:11:27 +0100 Subject: iwlegacy: do not nulify il->vif on reset This il->vif is dereferenced in different part of iwlegacy code, so do not nullify it. This should fix random crashes observed in companion with microcode errors i.e. crash in il3945_config_ap(). Additionally this should address also WARNING: at drivers/net/wireless/iwlegacy/common.c:4656 il_mac_remove_interface at least one of the possible reasons of that warning. Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 0c12093..faec404 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -2673,8 +2673,6 @@ il3945_bg_restart(struct work_struct *data) if (test_and_clear_bit(S_FW_ERROR, &il->status)) { mutex_lock(&il->mutex); - /* FIXME: vif can be dereferenced */ - il->vif = NULL; il->is_open = 0; mutex_unlock(&il->mutex); il3945_down(il); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 7b54dbb..b88bb27 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5651,8 +5651,6 @@ il4965_bg_restart(struct work_struct *data) if (test_and_clear_bit(S_FW_ERROR, &il->status)) { mutex_lock(&il->mutex); - /* FIXME: do we dereference vif without mutex locked ? */ - il->vif = NULL; il->is_open = 0; __il4965_down(il); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index e5ac047..6a692a5 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4508,6 +4508,7 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct il_priv *il = hw->priv; int err; + bool reset; mutex_lock(&il->mutex); D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); @@ -4518,7 +4519,12 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto out; } - if (il->vif) { + /* + * We do not support multiple virtual interfaces, but on hardware reset + * we have to add the same interface again. + */ + reset = (il->vif == vif); + if (il->vif && !reset) { err = -EOPNOTSUPP; goto out; } @@ -4528,8 +4534,11 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) err = il_set_mode(il); if (err) { - il->vif = NULL; - il->iw_mode = NL80211_IFTYPE_STATION; + IL_WARN("Fail to set mode %d\n", vif->type); + if (!reset) { + il->vif = NULL; + il->iw_mode = NL80211_IFTYPE_STATION; + } } out: -- cgit v0.10.2 From 2ee0a07028d2cde6e131b73f029dae2b93c50f3a Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 15 Mar 2012 06:08:04 +0530 Subject: ath9k: fix max noise floor threshold Currently the maximum noise floor limit is set as too high (-60dB). The assumption of having a higher threshold limit is that it would help de-sensitize the receiver (reduce phy errors) from continuous interference. But when we have a bursty interference where there are collisions and then free air time and if the receiver is desensitized too much, it will miss the normal packets too. Lets make use of chips specific min, nom and max limits always. This patch helps to improve the connection stability in congested networks. Cc: stable@vger.kernel.org Cc: Paul Stewart Tested-by: Gary Morain Signed-off-by: Madhan Jaganathan Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 2f4b48e..e5cceb0 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -20,7 +20,6 @@ /* Common calibration code */ -#define ATH9K_NF_TOO_HIGH -60 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) { @@ -346,10 +345,10 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) "NF calibrated [%s] [chain %d] is %d\n", (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); - if (nf[i] > ATH9K_NF_TOO_HIGH) { + if (nf[i] > limit->max) { ath_dbg(common, CALIBRATE, "NF[%d] (%d) > MAX (%d), correcting to MAX\n", - i, nf[i], ATH9K_NF_TOO_HIGH); + i, nf[i], limit->max); nf[i] = limit->max; } else if (nf[i] < limit->min) { ath_dbg(common, CALIBRATE, -- cgit v0.10.2 From e92109be7a6a04808c3ed586475ba1e5ea56ecbd Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 15 Mar 2012 11:42:49 +0100 Subject: iwlegacy: fix BSSID setting Current commit 0775f9f90cdaf40fbf69b3192b3dddb2b3436f45 "mac80211: remove spurious BSSID change flag" exposed bug on iwlegacy, that we do not set BSSID address correctly and then device was not able to receive frames after successful associate. On the way fix scan canceling comment. Apparently ->post_associate() do cancel scan itself, but scan cancel on BSS_CHANGED_BSSID is needed. I'm not sure why, but when I removed it, I had frequent auth failures: wlan4: send auth to 54:e6:fc:98:63:fe (try 1/3) wlan4: send auth to 54:e6:fc:98:63:fe (try 2/3) wlan4: send auth to 54:e6:fc:98:63:fe (try 3/3) wlan4: authentication with 54:e6:fc:98:63:fe timed out Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 6a692a5..eaf24945 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -5288,9 +5288,9 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, D_MAC80211("BSSID %pM\n", bss_conf->bssid); /* - * If there is currently a HW scan going on in the - * background then we need to cancel it else the RXON - * below/in post_associate will fail. + * If there is currently a HW scan going on in the background, + * then we need to cancel it, otherwise sometimes we are not + * able to authenticate (FIXME: why ?) */ if (il_scan_cancel_timeout(il, 100)) { D_MAC80211("leave - scan abort failed\n"); @@ -5299,14 +5299,10 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } /* mac80211 only sets assoc when in STATION mode */ - if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { - memcpy(il->staging.bssid_addr, bss_conf->bssid, - ETH_ALEN); + memcpy(il->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); - /* currently needed in a few places */ - memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); - } else - il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + /* FIXME: currently needed in a few places */ + memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); } /* -- cgit v0.10.2 From 66266b3ab4871958ed6a1e43f502cadaf3becfc8 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 15 Mar 2012 13:25:41 -0400 Subject: cfg80211: allow CFG80211_SIGNAL_TYPE_UNSPEC in station_info The station_info struct had demanded dBm signal values, but the cfg80211 wireless extensions implementation was also accepting "unspecified" (i.e. RSSI) unit values while the nl80211 code was completely unaware of them. Resolve this by formally allowing the "unspecified" units while making nl80211 ignore them. Signed-off-by: John W. Linville Reviewed-by: Johannes Berg diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 69b7ad3..5ccac72 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -619,8 +619,10 @@ struct sta_bss_parameters { * @llid: mesh local link id * @plid: mesh peer link id * @plink_state: mesh peer link state - * @signal: signal strength of last received packet in dBm - * @signal_avg: signal strength average in dBm + * @signal: the signal strength, type depends on the wiphy's signal_type + NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. + * @signal_avg: avg signal strength, type depends on the wiphy's signal_type + NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. * @txrate: current unicast bitrate from this station * @rxrate: current unicast bitrate to this station * @rx_packets: packets received from this station diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4c1eb94..e49da27 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2386,7 +2386,9 @@ nla_put_failure: } static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, - int flags, struct net_device *dev, + int flags, + struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo) { void *hdr; @@ -2425,12 +2427,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, if (sinfo->filled & STATION_INFO_PLINK_STATE) NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, sinfo->plink_state); - if (sinfo->filled & STATION_INFO_SIGNAL) - NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, - sinfo->signal); - if (sinfo->filled & STATION_INFO_SIGNAL_AVG) - NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, - sinfo->signal_avg); + switch (rdev->wiphy.signal_type) { + case CFG80211_SIGNAL_TYPE_MBM: + if (sinfo->filled & STATION_INFO_SIGNAL) + NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, + sinfo->signal); + if (sinfo->filled & STATION_INFO_SIGNAL_AVG) + NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, + sinfo->signal_avg); + break; + default: + break; + } if (sinfo->filled & STATION_INFO_TX_BITRATE) { if (!nl80211_put_sta_rate(msg, &sinfo->txrate, NL80211_STA_INFO_TX_BITRATE)) @@ -2523,7 +2531,7 @@ static int nl80211_dump_station(struct sk_buff *skb, if (nl80211_send_station(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - netdev, mac_addr, + dev, netdev, mac_addr, &sinfo) < 0) goto out; @@ -2568,7 +2576,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) return -ENOMEM; if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, - dev, mac_addr, &sinfo) < 0) { + rdev, dev, mac_addr, &sinfo) < 0) { nlmsg_free(msg); return -ENOBUFS; } @@ -7596,7 +7604,8 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, if (!msg) return; - if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) { + if (nl80211_send_station(msg, 0, 0, 0, + rdev, dev, mac_addr, sinfo) < 0) { nlmsg_free(msg); return; } -- cgit v0.10.2 From 195ca3b122c02cf21ce64f211d9474600da80e80 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 15 Mar 2012 23:05:28 +0530 Subject: ath9k: reduce listen time period When we have downlink traffic alone and the station is going thru bgscan, the client is out of operating channel for around 1000ms which is too long. The mac80211 decides when to switch back to oper channel based on tx queue, bad latency and listen time. As the station does not have tx traffic, the bgscan can easily affect downlink throughput. By reducing the listen time, it helps the associated AP to retain the downstream rate. Cc: Paul Stewart Tested-by: Gary Morain Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 60159f4..cb00645 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -680,7 +680,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; - hw->max_listen_interval = 10; + hw->max_listen_interval = 1; hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); -- cgit v0.10.2 From b5447ff92b5169eab843a76d83e98d0cd7b7f5b6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 15 Mar 2012 13:43:29 -0700 Subject: ath9k: fix a memory leak in ath_rx_tasklet() commit 0d95521ea7 (ath9k: use split rx buffers to get rid of order-1 skb allocations) added in memory leak in error path. sc->rx.frag should be cleared after the pskb_expand_head() call, or else we jump to requeue_drop_frag and leak an skb. Signed-off-by: Eric Dumazet Cc: Jouni Malinen Cc: Felix Fietkau Cc: John W. Linville Cc: Trond Wuellner Cc: Grant Grundler Cc: Paul Stewart Cc: David Miller Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index f4ae3ba..1c4583c 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1913,13 +1913,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if (sc->rx.frag) { int space = skb->len - skb_tailroom(hdr_skb); - sc->rx.frag = NULL; - if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { dev_kfree_skb(skb); goto requeue_drop_frag; } + sc->rx.frag = NULL; + skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len), skb->len); dev_kfree_skb_any(skb); -- cgit v0.10.2 From b603c03e9534b9bec19ebf8c42bf217fd875ee65 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 18 Mar 2012 14:08:50 +0200 Subject: mac80211: remove outdated comment The on-oper-channel optimization was reverted, so remove the outdated comment as well. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b581a24..1633648 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -102,9 +102,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) might_sleep(); - /* If this off-channel logic ever changes, ieee80211_on_oper_channel - * may need to change as well. - */ offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; if (local->scan_channel) { chan = local->scan_channel; -- cgit v0.10.2 From b9fc106108f3faf2e4430c3bd5721677c3d6a4a1 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 19 Mar 2012 09:39:45 +0100 Subject: rt2x00: rt2800usb: schedule txdone work on timeout This is fix for my current commit ed61e2b02027935520d1be884fac0b2ffce8379a "rt2x00: rt2800usb: rework txdone code" We should schedule txdone work on timeout, otherwise if newer get tx status from hardware, we will never report tx status to mac80211 and eventually never wakeup tx queue. Reported-by: Jakub Kicinski Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index cd490ab..f97f846 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -163,7 +163,13 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, /* Reschedule urb to read TX status again instantly */ return true; - } else if (rt2800usb_txstatus_pending(rt2x00dev)) { + } + + /* Check if there is any entry that timedout waiting on TX status */ + if (rt2800usb_txstatus_timeout(rt2x00dev)) + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + + if (rt2800usb_txstatus_pending(rt2x00dev)) { /* Read register after 250 us */ hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000), HRTIMER_MODE_REL); -- cgit v0.10.2 From 4e808a38fdcaeeeddbc05942623279ebe7c02373 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 19 Mar 2012 15:59:41 +0100 Subject: rt2x00: rt2800usb: fix status register reread logic Another good catch from Jakub Kicinski. This patch fixes my recent commit: ed61e2b02027935520d1be884fac0b2ffce8379a "rt2x00: rt2800usb: rework txdone code" We should reread status register only when nobody else start already reading status i.e. test_and_set_bit(TX_STATUS_READING, flags) return 0. Reported-by: Jakub Kicinski Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index f97f846..001735f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -184,7 +184,7 @@ stop_reading: * here again if status reading is needed. */ if (rt2800usb_txstatus_pending(rt2x00dev) && - test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) + !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) return true; else return false; -- cgit v0.10.2 From d72308bff5c2fa207949a5925b020bce74495e33 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 19 Mar 2012 16:00:26 +0100 Subject: mac80211: fix possible tid_rx->reorder_timer use after free Is possible that we will arm the tid_rx->reorder_timer after del_timer_sync() in ___ieee80211_stop_rx_ba_session(). We need to stop timer after RCU grace period finish, so move it to ieee80211_free_tid_rx(). Timer will not be armed again, as rcu_dereference(sta->ampdu_mlme.tid_rx[tid]) will return NULL. Debug object detected problem with the following warning: ODEBUG: free active (active state 0) object type: timer_list hint: sta_rx_agg_reorder_timer_expired+0x0/0xf0 [mac80211] Bug report (with all warning messages): https://bugzilla.redhat.com/show_bug.cgi?id=804007 Reported-by: "jan p. springer" Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 1068f66..64d3ce5 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -49,6 +49,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) container_of(h, struct tid_ampdu_rx, rcu_head); int i; + del_timer_sync(&tid_rx->reorder_timer); + for (i = 0; i < tid_rx->buf_size; i++) dev_kfree_skb(tid_rx->reorder_buf[i]); kfree(tid_rx->reorder_buf); @@ -91,7 +93,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, tid, WLAN_BACK_RECIPIENT, reason); del_timer_sync(&tid_rx->session_timer); - del_timer_sync(&tid_rx->reorder_timer); call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); } -- cgit v0.10.2 From 46470e5bb03c5aa685160dbaa45c013fb3997788 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Tue, 20 Mar 2012 10:48:40 -0400 Subject: ath5k: drop self from MAINTAINERS I simply don't have any hobby hacking time after family time and non-kernel-related job time, so I resume status as part-time mailing list lurker. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 92f9924..0ddc77fe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1247,7 +1247,6 @@ ATHEROS ATH5K WIRELESS DRIVER M: Jiri Slaby M: Nick Kossifidis M: "Luis R. Rodriguez" -M: Bob Copeland L: linux-wireless@vger.kernel.org L: ath5k-devel@lists.ath5k.org W: http://wireless.kernel.org/en/users/Drivers/ath5k -- cgit v0.10.2 From 643c61e119459e9d750087b7b34be94491efebf9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 26 Mar 2012 09:59:48 -0500 Subject: rtlwifi: rtl8192ce: rtl8192cu: rtl8192de: Fix low-gain setting when scanning In https://bugzilla.redhat.com/show_bug.cgi?id=770207, slowdowns of driver rtl8192ce are reported. One fix (commit a9b89e2) has already been applied, and it helped, but the maximum RX speed would still drop to 1 Mbps. As in the previous fix, the initial gain was determined to be the problem; however, the problem arises from a setting of the gain when scans are started. Driver rtl8192de also has the same code structure - this one is fixed as well. Reported-and-Tested-by: Ivan Pesin Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 1eec3a0..4c01624 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -1893,7 +1893,7 @@ void rtl92c_phy_set_io(struct ieee80211_hw *hw) break; case IO_CMD_PAUSE_DM_BY_SCAN: rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue; - dm_digtable.cur_igvalue = 0x17; + dm_digtable.cur_igvalue = 0x37; rtl92c_dm_write_dig(hw); break; default: diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 34591eeb..28fc5fb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -3077,7 +3077,7 @@ static void rtl92d_phy_set_io(struct ieee80211_hw *hw) break; case IO_CMD_PAUSE_DM_BY_SCAN: rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue; - de_digtable.cur_igvalue = 0x17; + de_digtable.cur_igvalue = 0x37; rtl92d_dm_write_dig(hw); break; default: -- cgit v0.10.2 From f2791d733a2f06997b573d1a3cfde21e6f529826 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 26 Mar 2012 22:46:52 +0200 Subject: PM / Runtime: don't forget to wake up waitqueue on failure This patch (as1535) fixes a bug in the runtime PM core. When a runtime suspend attempt completes, whether successfully or not, the device's power.wait_queue is supposed to be signalled. But this doesn't happen in the failure pathway of rpm_suspend() when another autosuspend attempt is rescheduled. As a result, a task can get stuck indefinitely on the wait queue (I have seen this happen in testing). The patch fixes the problem by moving the wake_up_all() call up near the start of the failure code. Signed-off-by: Alan Stern CC: Signed-off-by: Rafael J. Wysocki diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 541f821..bd0f394 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -532,6 +532,8 @@ static int rpm_suspend(struct device *dev, int rpmflags) dev->power.suspend_time = ktime_set(0, 0); dev->power.max_time_suspended_ns = -1; dev->power.deferred_resume = false; + wake_up_all(&dev->power.wait_queue); + if (retval == -EAGAIN || retval == -EBUSY) { dev->power.runtime_error = 0; @@ -547,7 +549,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) } else { pm_runtime_cancel_pending(dev); } - wake_up_all(&dev->power.wait_queue); goto out; } -- cgit v0.10.2 From 52f5509fe8ccb607ff9b84ad618f244262336475 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 20 Mar 2012 18:10:01 +0000 Subject: e1000: fix vlan processing regression This patch fixes a regression introduced by commit "e1000: do vlan cleanup (799d531)". Apparently some e1000 chips (not mine) are sensitive about the order of setting vlan filter and vlan stripping/inserting functionality. So this patch changes the order so it's the same as before vlan cleanup. Reported-by: Ben Greear Signed-off-by: Jiri Pirko Tested-by: Ben Greear Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 0e9aec8..bcba9cf 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -164,6 +164,8 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, static bool e1000_vlan_used(struct e1000_adapter *adapter); static void e1000_vlan_mode(struct net_device *netdev, netdev_features_t features); +static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, + bool filter_on); static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid); static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); static void e1000_restore_vlan(struct e1000_adapter *adapter); @@ -1214,7 +1216,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (err) goto err_register; - e1000_vlan_mode(netdev, netdev->features); + e1000_vlan_filter_on_off(adapter, false); /* print bus type/speed/width info */ e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n", @@ -4770,6 +4772,22 @@ static bool e1000_vlan_used(struct e1000_adapter *adapter) return false; } +static void __e1000_vlan_mode(struct e1000_adapter *adapter, + netdev_features_t features) +{ + struct e1000_hw *hw = &adapter->hw; + u32 ctrl; + + ctrl = er32(CTRL); + if (features & NETIF_F_HW_VLAN_RX) { + /* enable VLAN tag insert/strip */ + ctrl |= E1000_CTRL_VME; + } else { + /* disable VLAN tag insert/strip */ + ctrl &= ~E1000_CTRL_VME; + } + ew32(CTRL, ctrl); +} static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, bool filter_on) { @@ -4779,6 +4797,7 @@ static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, if (!test_bit(__E1000_DOWN, &adapter->flags)) e1000_irq_disable(adapter); + __e1000_vlan_mode(adapter, adapter->netdev->features); if (filter_on) { /* enable VLAN receive filtering */ rctl = er32(RCTL); @@ -4799,24 +4818,14 @@ static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, } static void e1000_vlan_mode(struct net_device *netdev, - netdev_features_t features) + netdev_features_t features) { struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 ctrl; if (!test_bit(__E1000_DOWN, &adapter->flags)) e1000_irq_disable(adapter); - ctrl = er32(CTRL); - if (features & NETIF_F_HW_VLAN_RX) { - /* enable VLAN tag insert/strip */ - ctrl |= E1000_CTRL_VME; - } else { - /* disable VLAN tag insert/strip */ - ctrl &= ~E1000_CTRL_VME; - } - ew32(CTRL, ctrl); + __e1000_vlan_mode(adapter, features); if (!test_bit(__E1000_DOWN, &adapter->flags)) e1000_irq_enable(adapter); -- cgit v0.10.2 From 4eee6a3a04e8bb53fbe7de0f64d0524d3fbe3f80 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 26 Mar 2012 09:01:30 +0000 Subject: wimax: i2400m - prevent a possible kernel bug due to missing fw_name string This happened on a machine with a custom hotplug script calling nameif, probably due to slow firmware loading. At the time nameif uses ethtool to gather interface information, i2400m->fw_name is zero and so a null pointer dereference occurs from within i2400m_get_drvinfo(). Signed-off-by: Phil Sutter Signed-off-by: David S. Miller diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 63e4b70..1d76ae8 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -597,7 +597,8 @@ static void i2400m_get_drvinfo(struct net_device *net_dev, struct i2400m *i2400m = net_dev_to_i2400m(net_dev); strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); - strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1); + strncpy(info->fw_version, + i2400m->fw_name ? : "", sizeof(info->fw_version) - 1); if (net_dev->dev.parent) strncpy(info->bus_info, dev_name(net_dev->dev.parent), sizeof(info->bus_info) - 1); -- cgit v0.10.2 From b7440892802be38e6eeb0a17897deeb85476eff4 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 26 Mar 2012 09:01:31 +0000 Subject: wimax: i2400m-usb - use a private struct ethtool_ops This way the USB variant of the driver uses usb_make_path in order to provide bus-info compatible to other USB drivers (like e.g. asix.c). Signed-off-by: Phil Sutter Signed-off-by: David S. Miller diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 2c1b8b6..29b1e03 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -339,6 +339,23 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) return result; } +static void i2400mu_get_drvinfo(struct net_device *net_dev, + struct ethtool_drvinfo *info) +{ + struct i2400m *i2400m = net_dev_to_i2400m(net_dev); + struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); + struct usb_device *udev = i2400mu->usb_dev; + + strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); + strncpy(info->fw_version, + i2400m->fw_name ? : "", sizeof(info->fw_version) - 1); + usb_make_path(udev, info->bus_info, sizeof(info->bus_info)); +} + +static const struct ethtool_ops i2400mu_ethtool_ops = { + .get_drvinfo = i2400mu_get_drvinfo, + .get_link = ethtool_op_get_link, +}; static void i2400mu_netdev_setup(struct net_device *net_dev) @@ -347,6 +364,7 @@ void i2400mu_netdev_setup(struct net_device *net_dev) struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); i2400mu_init(i2400mu); i2400m_netdev_setup(net_dev); + net_dev->ethtool_ops = &i2400mu_ethtool_ops; } -- cgit v0.10.2 From f0e81fecd4f83de7854262c8a6b3af19dfa99bf9 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Sun, 25 Mar 2012 18:59:51 +0000 Subject: net: sh_eth: Add support SH7734 Add define of SH7734 register and sh_eth_reset_hw_crc function. V3: Rebase net/HEAD. V2: Do not split line of #if defined. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index 9755b49..3fb2355 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -7,7 +7,8 @@ config SH_ETH depends on SUPERH && \ (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ - CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757) + CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ + CPU_SUBTYPE_SH7757) select CRC32 select NET_CORE select MII @@ -16,4 +17,4 @@ config SH_ETH ---help--- Renesas SuperH Ethernet device driver. This driver supporting CPUs are: - - SH7710, SH7712, SH7763, SH7619, SH7724, and SH7757. + - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757. diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 8615961..8bdf070 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1,8 +1,8 @@ /* * SuperH Ethernet device driver * - * Copyright (C) 2006-2008 Nobuhiro Iwamatsu - * Copyright (C) 2008-2009 Renesas Solutions Corp. + * Copyright (C) 2006-2012 Nobuhiro Iwamatsu + * Copyright (C) 2008-2012 Renesas Solutions Corp. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "sh_eth.h" @@ -279,8 +280,9 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) return &sh_eth_my_cpu_data; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7763) +#elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) #define SH_ETH_HAS_TSU 1 +static void sh_eth_reset_hw_crc(struct net_device *ndev); static void sh_eth_chip_reset(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -314,6 +316,9 @@ static void sh_eth_reset(struct net_device *ndev) sh_eth_write(ndev, 0x0, RDFAR); sh_eth_write(ndev, 0x0, RDFXR); sh_eth_write(ndev, 0x0, RDFFR); + + /* Reset HW CRC register */ + sh_eth_reset_hw_crc(ndev); } static void sh_eth_set_duplex(struct net_device *ndev) @@ -370,8 +375,17 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .no_trimd = 1, .no_ade = 1, .tsu = 1, +#if defined(CONFIG_CPU_SUBTYPE_SH7734) + .hw_crc = 1, +#endif }; +static void sh_eth_reset_hw_crc(struct net_device *ndev) +{ + if (sh_eth_my_cpu_data.hw_crc) + sh_eth_write(ndev, 0x0, CSMR); +} + #elif defined(CONFIG_CPU_SUBTYPE_SH7619) #define SH_ETH_RESET_DEFAULT 1 static struct sh_eth_cpu_data sh_eth_my_cpu_data = { diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 57dc262..e66de18 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -1,8 +1,8 @@ /* * SuperH Ethernet device driver * - * Copyright (C) 2006-2008 Nobuhiro Iwamatsu - * Copyright (C) 2008-2011 Renesas Solutions Corp. + * Copyright (C) 2006-2012 Nobuhiro Iwamatsu + * Copyright (C) 2008-2012 Renesas Solutions Corp. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -98,6 +98,8 @@ enum { CEECR, MAFCR, RTRATE, + CSMR, + RMII_MII, /* TSU Absolute address */ ARSTR, @@ -172,6 +174,7 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = { [RMCR] = 0x0458, [RPADIR] = 0x0460, [FCFTR] = 0x0468, + [CSMR] = 0x04E4, [ECMR] = 0x0500, [ECSR] = 0x0510, @@ -200,6 +203,7 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = { [CERCR] = 0x0768, [CEECR] = 0x0770, [MAFCR] = 0x0778, + [RMII_MII] = 0x0790, [ARSTR] = 0x0000, [TSU_CTRST] = 0x0004, @@ -377,7 +381,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = { /* * Register's bits */ -#ifdef CONFIG_CPU_SUBTYPE_SH7763 +#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) /* EDSR */ enum EDSR_BIT { EDSR_ENT = 0x01, EDSR_ENR = 0x02, @@ -751,6 +755,7 @@ struct sh_eth_cpu_data { unsigned rpadir:1; /* E-DMAC have RPADIR */ unsigned no_trimd:1; /* E-DMAC DO NOT have TRIMD */ unsigned no_ade:1; /* E-DMAC DO NOT have ADE bit in EESR */ + unsigned hw_crc:1; /* E-DMAC have CSMR */ }; struct sh_eth_private { -- cgit v0.10.2 From a2daf263107ba3eb6db33931881731fa51c95045 Mon Sep 17 00:00:00 2001 From: Guan Xin Date: Mon, 26 Mar 2012 04:11:46 +0000 Subject: USB: Add Motorola Rokr E6 Id to the USBNet driver "zaurus" Added Vendor/Device Id of Motorola Rokr E6 (22b8:6027) so it can be recognized by the "zaurus" USBNet driver. Applies to Linux 3.2.13 and 2.6.39.4. Signed-off-by: Guan Xin Signed-off-by: David S. Miller diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index c3197ce..34db195 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -337,6 +337,11 @@ static const struct usb_device_id products [] = { .driver_info = ZAURUS_PXA_INFO, }, { + /* Motorola Rokr E6 */ + USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &bogus_mdlm_info, +}, { /* Motorola MOTOMAGX phones */ USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), -- cgit v0.10.2 From 452427b015b1b0cbbef7b6207908726837d39d57 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 26 Mar 2012 20:47:07 +0000 Subject: bnx2x: previous driver unload revised The flow in which the bnx2x driver starts after a previous driver has been terminated in an 'unclean' manner has several bugs and FW risks, which makes it possible for the driver to fail after boot-from-SAN or kdump. This patch contains a revised flow which performs a safer initialization, solving the possible crash scenarios. Notice this patch contains lines with over 80 characters, as it keeps print-strings in a single line. Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index e37161f..2c9ee55 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1173,6 +1173,13 @@ enum { }; +struct bnx2x_prev_path_list { + u8 bus; + u8 slot; + u8 path; + struct list_head list; +}; + struct bnx2x { /* Fields used in the tx and intr/napi performance paths * are grouped together in the beginning of the structure diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index f1f3ca6..44556b7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1721,6 +1721,29 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp) } while (0) #endif +bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err) +{ + /* build FW version dword */ + u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) + + (BCM_5710_FW_MINOR_VERSION << 8) + + (BCM_5710_FW_REVISION_VERSION << 16) + + (BCM_5710_FW_ENGINEERING_VERSION << 24); + + /* read loaded FW from chip */ + u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM); + + DP(NETIF_MSG_IFUP, "loaded fw %x, my fw %x\n", loaded_fw, my_fw); + + if (loaded_fw != my_fw) { + if (is_err) + BNX2X_ERR("bnx2x with FW %x was already loaded, which mismatches my %x FW. aborting\n", + loaded_fw, my_fw); + return false; + } + + return true; +} + /* must be called with rtnl_lock */ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) { @@ -1815,23 +1838,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP && load_code != FW_MSG_CODE_DRV_LOAD_COMMON) { - /* build FW version dword */ - u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) + - (BCM_5710_FW_MINOR_VERSION << 8) + - (BCM_5710_FW_REVISION_VERSION << 16) + - (BCM_5710_FW_ENGINEERING_VERSION << 24); - - /* read loaded FW from chip */ - u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM); - - DP(BNX2X_MSG_SP, "loaded fw %x, my fw %x", - loaded_fw, my_fw); - /* abort nic load if version mismatch */ - if (my_fw != loaded_fw) { - BNX2X_ERR("bnx2x with FW %x already loaded, " - "which mismatches my %x FW. aborting", - loaded_fw, my_fw); + if (!bnx2x_test_firmware_version(bp, true)) { rc = -EBUSY; LOAD_ERROR_EXIT(bp, load_error2); } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 8b16338..5c27454 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -431,6 +431,9 @@ void bnx2x_panic_dump(struct bnx2x *bp); void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl); +/* validate currect fw is loaded */ +bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err); + /* dev_close main block */ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 5d71b7d..dbff591 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h @@ -1251,6 +1251,9 @@ struct drv_func_mb { #define DRV_MSG_CODE_LINK_STATUS_CHANGED 0x01000000 + #define DRV_MSG_CODE_INITIATE_FLR 0x02000000 + #define REQ_BC_VER_4_INITIATE_FLR 0x00070213 + #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000 #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000 #define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index beb4cdb..efa557b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -35,7 +35,6 @@ #define ETH_MAX_PACKET_SIZE 1500 #define ETH_MAX_JUMBO_PACKET_SIZE 9600 #define MDIO_ACCESS_TIMEOUT 1000 -#define BMAC_CONTROL_RX_ENABLE 2 #define WC_LANE_MAX 4 #define I2C_SWITCH_WIDTH 2 #define I2C_BSC0 0 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index 7ba557a..763535e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h @@ -89,6 +89,8 @@ #define PFC_BRB_FULL_LB_XON_THRESHOLD 250 #define MAXVAL(a, b) (((a) > (b)) ? (a) : (b)) + +#define BMAC_CONTROL_RX_ENABLE 2 /***********************************************************/ /* Structs */ /***********************************************************/ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f7f9aa8..e077d25 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -211,6 +212,10 @@ static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = { MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl); +/* Global resources for unloading a previously loaded device */ +#define BNX2X_PREV_WAIT_NEEDED 1 +static DEFINE_SEMAPHORE(bnx2x_prev_sem); +static LIST_HEAD(bnx2x_prev_list); /**************************************************************************** * General service functions ****************************************************************************/ @@ -8812,109 +8817,371 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp) bnx2x_undi_int_disable_e1h(bp); } -static void __devinit bnx2x_undi_unload(struct bnx2x *bp) +static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp) { - u32 val; + u32 val, base_addr, offset, mask, reset_reg; + bool mac_stopped = false; + u8 port = BP_PORT(bp); - /* possibly another driver is trying to reset the chip */ - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); + reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); - /* check if doorbell queue is reset */ - if (REG_RD(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET) - & MISC_REGISTERS_RESET_REG_1_RST_DORQ) { + if (!CHIP_IS_E3(bp)) { + val = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port * 4); + mask = MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port; + if ((mask & reset_reg) && val) { + u32 wb_data[2]; + BNX2X_DEV_INFO("Disable bmac Rx\n"); + base_addr = BP_PORT(bp) ? NIG_REG_INGRESS_BMAC1_MEM + : NIG_REG_INGRESS_BMAC0_MEM; + offset = CHIP_IS_E2(bp) ? BIGMAC2_REGISTER_BMAC_CONTROL + : BIGMAC_REGISTER_BMAC_CONTROL; - /* - * Check if it is the UNDI driver + /* + * use rd/wr since we cannot use dmae. This is safe + * since MCP won't access the bus due to the request + * to unload, and no function on the path can be + * loaded at this time. + */ + wb_data[0] = REG_RD(bp, base_addr + offset); + wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); + wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; + REG_WR(bp, base_addr + offset, wb_data[0]); + REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); + + } + BNX2X_DEV_INFO("Disable emac Rx\n"); + REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); + + mac_stopped = true; + } else { + if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { + BNX2X_DEV_INFO("Disable xmac Rx\n"); + base_addr = BP_PORT(bp) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; + val = REG_RD(bp, base_addr + XMAC_REG_PFC_CTRL_HI); + REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, + val & ~(1 << 1)); + REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, + val | (1 << 1)); + REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); + mac_stopped = true; + } + mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; + if (mask & reset_reg) { + BNX2X_DEV_INFO("Disable umac Rx\n"); + base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; + REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); + mac_stopped = true; + } + } + + if (mac_stopped) + msleep(20); + +} + +#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4)) +#define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff) +#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff) +#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq)) + +static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, + u8 inc) +{ + u16 rcq, bd; + u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port)); + + rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc; + bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc; + + tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd); + REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg); + + BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n", + port, bd, rcq); +} + +static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp) +{ + u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); + if (!rc) { + BNX2X_ERR("MCP response failure, aborting\n"); + return -EBUSY; + } + + return 0; +} + +static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp) +{ + struct bnx2x_prev_path_list *tmp_list; + int rc = false; + + if (down_trylock(&bnx2x_prev_sem)) + return false; + + list_for_each_entry(tmp_list, &bnx2x_prev_list, list) { + if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot && + bp->pdev->bus->number == tmp_list->bus && + BP_PATH(bp) == tmp_list->path) { + rc = true; + BNX2X_DEV_INFO("Path %d was already cleaned from previous drivers\n", + BP_PATH(bp)); + break; + } + } + + up(&bnx2x_prev_sem); + + return rc; +} + +static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp) +{ + struct bnx2x_prev_path_list *tmp_list; + int rc; + + tmp_list = (struct bnx2x_prev_path_list *) + kmalloc(sizeof(struct bnx2x_prev_path_list), GFP_KERNEL); + if (!tmp_list) { + BNX2X_ERR("Failed to allocate 'bnx2x_prev_path_list'\n"); + return -ENOMEM; + } + + tmp_list->bus = bp->pdev->bus->number; + tmp_list->slot = PCI_SLOT(bp->pdev->devfn); + tmp_list->path = BP_PATH(bp); + + rc = down_interruptible(&bnx2x_prev_sem); + if (rc) { + BNX2X_ERR("Received %d when tried to take lock\n", rc); + kfree(tmp_list); + } else { + BNX2X_DEV_INFO("Marked path [%d] - finished previous unload\n", + BP_PATH(bp)); + list_add(&tmp_list->list, &bnx2x_prev_list); + up(&bnx2x_prev_sem); + } + + return rc; +} + +static bool __devinit bnx2x_can_flr(struct bnx2x *bp) +{ + int pos; + u32 cap; + struct pci_dev *dev = bp->pdev; + + pos = pci_pcie_cap(dev); + if (!pos) + return false; + + pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap); + if (!(cap & PCI_EXP_DEVCAP_FLR)) + return false; + + return true; +} + +static int __devinit bnx2x_do_flr(struct bnx2x *bp) +{ + int i, pos; + u16 status; + struct pci_dev *dev = bp->pdev; + + /* probe the capability first */ + if (bnx2x_can_flr(bp)) + return -ENOTTY; + + pos = pci_pcie_cap(dev); + if (!pos) + return -ENOTTY; + + /* Wait for Transaction Pending bit clean */ + for (i = 0; i < 4; i++) { + if (i) + msleep((1 << (i - 1)) * 100); + + pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status); + if (!(status & PCI_EXP_DEVSTA_TRPND)) + goto clear; + } + + dev_err(&dev->dev, + "transaction is not cleared; proceeding with reset anyway\n"); + +clear: + if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { + BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n", + bp->common.bc_ver); + return -EINVAL; + } + + bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0); + + return 0; +} + +static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp) +{ + int rc; + + BNX2X_DEV_INFO("Uncommon unload Flow\n"); + + /* Test if previous unload process was already finished for this path */ + if (bnx2x_prev_is_path_marked(bp)) + return bnx2x_prev_mcp_done(bp); + + /* If function has FLR capabilities, and existing FW version matches + * the one required, then FLR will be sufficient to clean any residue + * left by previous driver + */ + if (bnx2x_test_firmware_version(bp, false) && bnx2x_can_flr(bp)) + return bnx2x_do_flr(bp); + + /* Close the MCP request, return failure*/ + rc = bnx2x_prev_mcp_done(bp); + if (!rc) + rc = BNX2X_PREV_WAIT_NEEDED; + + return rc; +} + +static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) +{ + u32 reset_reg, tmp_reg = 0, rc; + /* It is possible a previous function received 'common' answer, + * but hasn't loaded yet, therefore creating a scenario of + * multiple functions receiving 'common' on the same path. + */ + BNX2X_DEV_INFO("Common unload Flow\n"); + + if (bnx2x_prev_is_path_marked(bp)) + return bnx2x_prev_mcp_done(bp); + + reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1); + + /* Reset should be performed after BRB is emptied */ + if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) { + u32 timer_count = 1000; + bool prev_undi = false; + + /* Close the MAC Rx to prevent BRB from filling up */ + bnx2x_prev_unload_close_mac(bp); + + /* Check if the UNDI driver was previously loaded * UNDI driver initializes CID offset for normal bell to 0x7 */ - val = REG_RD(bp, DORQ_REG_NORM_CID_OFST); - if (val == 0x7) { - u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; - /* save our pf_num */ - int orig_pf_num = bp->pf_num; - int port; - u32 swap_en, swap_val, value; - - /* clear the UNDI indication */ - REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); - - BNX2X_DEV_INFO("UNDI is active! reset device\n"); - - /* try unload UNDI on port 0 */ - bp->pf_num = 0; - bp->fw_seq = - (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) & - DRV_MSG_SEQ_NUMBER_MASK); - reset_code = bnx2x_fw_command(bp, reset_code, 0); - - /* if UNDI is loaded on the other port */ - if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) { - - /* send "DONE" for previous unload */ - bnx2x_fw_command(bp, - DRV_MSG_CODE_UNLOAD_DONE, 0); - - /* unload UNDI on port 1 */ - bp->pf_num = 1; - bp->fw_seq = - (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) & - DRV_MSG_SEQ_NUMBER_MASK); - reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; - - bnx2x_fw_command(bp, reset_code, 0); + reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1); + if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_DORQ) { + tmp_reg = REG_RD(bp, DORQ_REG_NORM_CID_OFST); + if (tmp_reg == 0x7) { + BNX2X_DEV_INFO("UNDI previously loaded\n"); + prev_undi = true; + /* clear the UNDI indication */ + REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); } + } + /* wait until BRB is empty */ + tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS); + while (timer_count) { + u32 prev_brb = tmp_reg; - bnx2x_undi_int_disable(bp); - port = BP_PORT(bp); - - /* close input traffic and wait for it */ - /* Do not rcv packets to BRB */ - REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK : - NIG_REG_LLH0_BRB1_DRV_MASK), 0x0); - /* Do not direct rcv packets that are not for MCP to - * the BRB */ - REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP : - NIG_REG_LLH0_BRB1_NOT_MCP), 0x0); - /* clear AEU */ - REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : - MISC_REG_AEU_MASK_ATTN_FUNC_0), 0); - msleep(10); - - /* save NIG port swap info */ - swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); - swap_en = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); - /* reset device */ - REG_WR(bp, - GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, - 0xd3ffffff); - - value = 0x1400; - if (CHIP_IS_E3(bp)) { - value |= MISC_REGISTERS_RESET_REG_2_MSTAT0; - value |= MISC_REGISTERS_RESET_REG_2_MSTAT1; - } + tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS); + if (!tmp_reg) + break; - REG_WR(bp, - GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, - value); + BNX2X_DEV_INFO("BRB still has 0x%08x\n", tmp_reg); - /* take the NIG out of reset and restore swap values */ - REG_WR(bp, - GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, - MISC_REGISTERS_RESET_REG_1_RST_NIG); - REG_WR(bp, NIG_REG_PORT_SWAP, swap_val); - REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en); + /* reset timer as long as BRB actually gets emptied */ + if (prev_brb > tmp_reg) + timer_count = 1000; + else + timer_count--; - /* send unload done to the MCP */ - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); + /* If UNDI resides in memory, manually increment it */ + if (prev_undi) + bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1); - /* restore our func and fw_seq */ - bp->pf_num = orig_pf_num; + udelay(10); } + + if (!timer_count) + BNX2X_ERR("Failed to empty BRB, hope for the best\n"); + } - /* now it's safe to release the lock */ - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); + /* No packets are in the pipeline, path is ready for reset */ + bnx2x_reset_common(bp); + + rc = bnx2x_prev_mark_path(bp); + if (rc) { + bnx2x_prev_mcp_done(bp); + return rc; + } + + return bnx2x_prev_mcp_done(bp); +} + +static int __devinit bnx2x_prev_unload(struct bnx2x *bp) +{ + int time_counter = 10; + u32 rc, fw, hw_lock_reg, hw_lock_val; + BNX2X_DEV_INFO("Entering Previous Unload Flow\n"); + + /* Release previously held locks */ + hw_lock_reg = (BP_FUNC(bp) <= 5) ? + (MISC_REG_DRIVER_CONTROL_1 + BP_FUNC(bp) * 8) : + (MISC_REG_DRIVER_CONTROL_7 + (BP_FUNC(bp) - 6) * 8); + + hw_lock_val = (REG_RD(bp, hw_lock_reg)); + if (hw_lock_val) { + if (hw_lock_val & HW_LOCK_RESOURCE_NVRAM) { + BNX2X_DEV_INFO("Release Previously held NVRAM lock\n"); + REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB, + (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << BP_PORT(bp))); + } + + BNX2X_DEV_INFO("Release Previously held hw lock\n"); + REG_WR(bp, hw_lock_reg, 0xffffffff); + } else + BNX2X_DEV_INFO("No need to release hw/nvram locks\n"); + + if (MCPR_ACCESS_LOCK_LOCK & REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK)) { + BNX2X_DEV_INFO("Release previously held alr\n"); + REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0); + } + + + do { + /* Lock MCP using an unload request */ + fw = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS, 0); + if (!fw) { + BNX2X_ERR("MCP response failure, aborting\n"); + rc = -EBUSY; + break; + } + + if (fw == FW_MSG_CODE_DRV_UNLOAD_COMMON) { + rc = bnx2x_prev_unload_common(bp); + break; + } + + /* non-common reply from MCP night require looping */ + rc = bnx2x_prev_unload_uncommon(bp); + if (rc != BNX2X_PREV_WAIT_NEEDED) + break; + + msleep(20); + } while (--time_counter); + + if (!time_counter || rc) { + BNX2X_ERR("Failed unloading previous driver, aborting\n"); + rc = -EBUSY; + } + + BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc); + + return rc; } static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) @@ -10100,8 +10367,16 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) func = BP_FUNC(bp); /* need to reset chip if undi was active */ - if (!BP_NOMCP(bp)) - bnx2x_undi_unload(bp); + if (!BP_NOMCP(bp)) { + /* init fw_seq */ + bp->fw_seq = + SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & + DRV_MSG_SEQ_NUMBER_MASK; + BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); + + bnx2x_prev_unload(bp); + } + if (CHIP_REV_IS_FPGA(bp)) dev_err(&bp->pdev->dev, "FPGA detected\n"); @@ -11431,9 +11706,18 @@ static int __init bnx2x_init(void) static void __exit bnx2x_cleanup(void) { + struct list_head *pos, *q; pci_unregister_driver(&bnx2x_pci_driver); destroy_workqueue(bnx2x_wq); + + /* Free globablly allocated resources */ + list_for_each_safe(pos, q, &bnx2x_prev_list) { + struct bnx2x_prev_path_list *tmp = + list_entry(pos, struct bnx2x_prev_path_list, list); + list_del(pos); + kfree(tmp); + } } void bnx2x_notify_link_changed(struct bnx2x *bp) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index fd7fb45..ab0a250 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -987,6 +987,7 @@ * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */ #define IGU_REG_WRITE_DONE_PENDING 0x130480 #define MCP_A_REG_MCPR_SCRATCH 0x3a0000 +#define MCP_REG_MCPR_ACCESS_LOCK 0x8009c #define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c #define MCP_REG_MCPR_GP_INPUTS 0x800c0 #define MCP_REG_MCPR_GP_OENABLE 0x800c8 @@ -1686,6 +1687,7 @@ [10] rst_dbg; [11] rst_misc_core; [12] rst_dbue (UART); [13] Pci_resetmdio_n; [14] rst_emac0_hard_core; [15] rst_emac1_hard_core; 16] rst_pxp_rq_rd_wr; 31:17] reserved */ +#define MISC_REG_RESET_REG_1 0xa580 #define MISC_REG_RESET_REG_2 0xa590 /* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is shared with the driver resides */ @@ -5606,6 +5608,7 @@ /* [RC 32] Parity register #0 read clear */ #define XSEM_REG_XSEM_PRTY_STS_CLR_0 0x280128 #define XSEM_REG_XSEM_PRTY_STS_CLR_1 0x280138 +#define MCPR_ACCESS_LOCK_LOCK (1L<<31) #define MCPR_NVM_ACCESS_ENABLE_EN (1L<<0) #define MCPR_NVM_ACCESS_ENABLE_WR_EN (1L<<1) #define MCPR_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0) @@ -5732,6 +5735,7 @@ #define MISC_REGISTERS_GPIO_PORT_SHIFT 4 #define MISC_REGISTERS_GPIO_SET_POS 8 #define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588 +#define MISC_REGISTERS_RESET_REG_1_RST_BRB1 (0x1<<0) #define MISC_REGISTERS_RESET_REG_1_RST_DORQ (0x1<<19) #define MISC_REGISTERS_RESET_REG_1_RST_HC (0x1<<29) #define MISC_REGISTERS_RESET_REG_1_RST_NIG (0x1<<7) -- cgit v0.10.2 From c54e9bd38a06babf94fd45e5f1df9a1109e12818 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Mon, 26 Mar 2012 21:08:55 +0000 Subject: bnx2x: fix vector traveling while looking for an empty entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the bug that may prevent from mac to be configured, while there is an empty slot for it. Reported-by: Maciej Żenczykowski Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 3f52fad..5135733 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -3847,7 +3847,7 @@ static bool bnx2x_credit_pool_get_entry( continue; /* If we've got here we are going to find a free entry */ - for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0; + for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0; i < BIT_VEC64_ELEM_SZ; idx++, i++) if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) { -- cgit v0.10.2 From 819a100846295461bc0f1bfcb8e5ab11c1bc4cdb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 26 Mar 2012 21:20:48 +0000 Subject: mISDN: array underflow in open_bchannel() There are two channels here. User space starts counting channels at one but in the kernel we start at zero. If the user passes in a zero channel that's invalid and could lead to memory corruption. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index 05ed4d0c..c0b8c96 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -891,7 +891,7 @@ open_bchannel(struct fritzcard *fc, struct channel_req *rq) { struct bchannel *bch; - if (rq->adr.channel > 2) + if (rq->adr.channel == 0 || rq->adr.channel > 2) return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index d055ae7..e2c83a2 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -1962,7 +1962,7 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq) { struct bchannel *bch; - if (rq->adr.channel > 2) + if (rq->adr.channel == 0 || rq->adr.channel > 2) return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 6023387..8cde2a0 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -486,7 +486,7 @@ open_bchannel(struct hfcsusb *hw, struct channel_req *rq) { struct bchannel *bch; - if (rq->adr.channel > 2) + if (rq->adr.channel == 0 || rq->adr.channel > 2) return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index b47e9be..884369f 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -1506,7 +1506,7 @@ open_bchannel(struct ipac_hw *ipac, struct channel_req *rq) { struct bchannel *bch; - if (rq->adr.channel > 2) + if (rq->adr.channel == 0 || rq->adr.channel > 2) return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index 10446ab..9a6da6e 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -1670,7 +1670,7 @@ isar_open(struct isar_hw *isar, struct channel_req *rq) { struct bchannel *bch; - if (rq->adr.channel > 2) + if (rq->adr.channel == 0 || rq->adr.channel > 2) return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index dd6de9f..c726e09 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -860,7 +860,7 @@ open_bchannel(struct tiger_hw *card, struct channel_req *rq) { struct bchannel *bch; - if (rq->adr.channel > 2) + if (rq->adr.channel == 0 || rq->adr.channel > 2) return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 7f1e7ba..2183357 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -1015,7 +1015,7 @@ open_bchannel(struct w6692_hw *card, struct channel_req *rq) { struct bchannel *bch; - if (rq->adr.channel > 2) + if (rq->adr.channel == 0 || rq->adr.channel > 2) return -EINVAL; if (rq->protocol == ISDN_P_NONE) return -EINVAL; -- cgit v0.10.2 From 09e79d6ea65d66e0a5e9ba76865320e74832dc7c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 26 Mar 2012 22:52:00 +0000 Subject: eql: dont rely on HZ=100 HZ is more likely to be 1000 these days. timer handlers are run from softirq, no need to disable bh skb priority 1 is TC_PRIO_FILLER Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/drivers/net/eql.c b/drivers/net/eql.c index a59cf96..f219d38 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -125,6 +125,7 @@ #include #include #include +#include #include @@ -143,7 +144,7 @@ static void eql_timer(unsigned long param) equalizer_t *eql = (equalizer_t *) param; struct list_head *this, *tmp, *head; - spin_lock_bh(&eql->queue.lock); + spin_lock(&eql->queue.lock); head = &eql->queue.all_slaves; list_for_each_safe(this, tmp, head) { slave_t *slave = list_entry(this, slave_t, list); @@ -157,7 +158,7 @@ static void eql_timer(unsigned long param) } } - spin_unlock_bh(&eql->queue.lock); + spin_unlock(&eql->queue.lock); eql->timer.expires = jiffies + EQL_DEFAULT_RESCHED_IVAL; add_timer(&eql->timer); @@ -341,7 +342,7 @@ static netdev_tx_t eql_slave_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device *slave_dev = slave->dev; skb->dev = slave_dev; - skb->priority = 1; + skb->priority = TC_PRIO_FILLER; slave->bytes_queued += skb->len; dev_queue_xmit(skb); dev->stats.tx_packets++; diff --git a/include/linux/if_eql.h b/include/linux/if_eql.h index 79c4f26..18a5d02 100644 --- a/include/linux/if_eql.h +++ b/include/linux/if_eql.h @@ -22,7 +22,7 @@ #define EQL_DEFAULT_SLAVE_PRIORITY 28800 #define EQL_DEFAULT_MAX_SLAVES 4 #define EQL_DEFAULT_MTU 576 -#define EQL_DEFAULT_RESCHED_IVAL 100 +#define EQL_DEFAULT_RESCHED_IVAL HZ #define EQL_ENSLAVE (SIOCDEVPRIVATE) #define EQL_EMANCIPATE (SIOCDEVPRIVATE + 1) -- cgit v0.10.2 From 21dcda6083a0573686acabca39b3f92ba032d333 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 27 Mar 2012 03:04:02 +0000 Subject: f_phonet: fix skb truesize underestimation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now skb_add_rx_frag() has a truesize parameter, we can fix f_phonet to properly account truesize of each fragment : a full page. Signed-off-by: Eric Dumazet Cc: Felipe Balbi Cc: Greg Kroah-Hartman Cc: Rémi Denis-Courmont Signed-off-by: David S. Miller diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index 85a5ceb..965a629 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -345,7 +345,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req) } skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, - skb->len <= 1, req->actual, req->actual); + skb->len <= 1, req->actual, PAGE_SIZE); page = NULL; if (req->actual < req->length) { /* Last fragment */ -- cgit v0.10.2 From 094b5855bf37eae4b297bc47bb5bc5454f1f6fab Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 27 Mar 2012 03:17:26 +0000 Subject: cdc-phonet: fix skb truesize underestimation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now skb_add_rx_frag() has a truesize parameter, we can fix cdc-phonet to properly account truesize of each fragment : a full page. Signed-off-by: Eric Dumazet Cc: Felipe Balbi Cc: Greg Kroah-Hartman Cc: Rémi Denis-Courmont Acked-by: Rémi Denis-Courmont Signed-off-by: David S. Miller diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 3886b30..3e41b00 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -165,13 +165,13 @@ static void rx_complete(struct urb *req) memcpy(skb_put(skb, 1), page_address(page), 1); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 1, req->actual_length, - req->actual_length); + PAGE_SIZE); page = NULL; } } else { skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0, req->actual_length, - req->actual_length); + PAGE_SIZE); page = NULL; } if (req->actual_length < PAGE_SIZE) -- cgit v0.10.2 From 8cf662ed3ef190fddc186bb5b1cd75eb3880d5a9 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 27 Mar 2012 10:10:15 +0200 Subject: microblaze: Fix __futex_atomic_op macro register usage Old Microblaze toolchain supported "b" contstrains for all register but it always points to general purpose reg. New Microblaze toolchain is more strict in this and general purpose register should be used there "r". Signed-off-by: Michal Simek diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h index b0526d2..ff8cde1 100644 --- a/arch/microblaze/include/asm/futex.h +++ b/arch/microblaze/include/asm/futex.h @@ -24,7 +24,7 @@ .word 1b,4b,2b,4b; \ .previous;" \ : "=&r" (oldval), "=&r" (ret) \ - : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + : "r" (uaddr), "i" (-EFAULT), "r" (oparg) \ ); \ }) -- cgit v0.10.2 From b3f4d5990bfc8b060e5010c1464789fca1f4c5b4 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 13 Mar 2012 06:04:20 +0000 Subject: intel: make wired ethernet driver message level consistent (rev2) Dan Carpenter noticed that ixgbevf initial default was different than the rest. But the problem is broader than that, only one Intel driver (ixgb) was doing it almost right. The convention for default debug level should be consistent among Intel drivers and follow established convention. Signed-off-by: Stephen Hemminger Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index bcba9cf..4348b6f 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -217,7 +217,8 @@ MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); @@ -981,7 +982,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; - adapter->msg_enable = (1 << debug) - 1; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); adapter->bars = bars; adapter->need_ioport = need_ioport; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 7152eb1..2c38a65 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -60,6 +60,11 @@ char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); static const struct e1000_info *e1000_info_tbl[] = { @@ -6172,7 +6177,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->hw.adapter = adapter; adapter->hw.mac.type = ei->mac; adapter->max_hw_frame_size = ei->max_hw_frame_size; - adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); mmio_start = pci_resource_start(pdev, 0); mmio_len = pci_resource_len(pdev, 0); diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index c490241..5ec3159 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -238,6 +238,11 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + struct igb_reg_info { u32 ofs; char *name; @@ -1893,7 +1898,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, adapter->pdev = pdev; hw = &adapter->hw; hw->back = adapter; - adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); mmio_start = pci_resource_start(pdev, 0); mmio_len = pci_resource_len(pdev, 0); diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 217c143..d61ca2a 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -55,6 +55,11 @@ static const char igbvf_driver_string[] = static const char igbvf_copyright[] = "Copyright (c) 2009 - 2012 Intel Corporation."; +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + static int igbvf_poll(struct napi_struct *napi, int budget); static void igbvf_reset(struct igbvf_adapter *); static void igbvf_set_interrupt_capability(struct igbvf_adapter *); @@ -2649,7 +2654,7 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, adapter->flags = ei->flags; adapter->hw.back = adapter; adapter->hw.mac.type = ei->mac; - adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); /* PCI config space info */ diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 82aaa79..5fce363 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -134,8 +134,8 @@ MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -#define DEFAULT_DEBUG_LEVEL_SHIFT 3 -static int debug = DEFAULT_DEBUG_LEVEL_SHIFT; +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); @@ -442,7 +442,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->netdev = netdev; adapter->pdev = pdev; adapter->hw.back = adapter; - adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT); + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); adapter->hw.hw_addr = pci_ioremap_bar(pdev, BAR_0); if (!adapter->hw.hw_addr) { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 398fc22..6dbad2b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -141,13 +141,16 @@ module_param(allow_unsupported_sfp, uint, 0); MODULE_PARM_DESC(allow_unsupported_sfp, "Allow unsupported and untested SFP+ modules on 82599-based adapters"); +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -#define DEFAULT_DEBUG_LEVEL_SHIFT 3 - static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter) { if (!test_bit(__IXGBE_DOWN, &adapter->state) && @@ -6834,7 +6837,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, adapter->pdev = pdev; hw = &adapter->hw; hw->back = adapter; - adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); hw->hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 581c659..307611a 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -91,7 +91,10 @@ MODULE_DESCRIPTION("Intel(R) 82599 Virtual Function Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -#define DEFAULT_DEBUG_LEVEL_SHIFT 3 +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); /* forward decls */ static void ixgbevf_set_itr_msix(struct ixgbevf_q_vector *q_vector); @@ -3367,7 +3370,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, adapter->pdev = pdev; hw = &adapter->hw; hw->back = adapter; - adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); /* * call save state here in standalone driver because it relies on -- cgit v0.10.2 From 70e5576cb0af5c1351432704a39319af119584bb Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 15 Mar 2012 04:55:59 +0000 Subject: ixgbe: fix typo in enumeration name This was pointed out to me by Xiaojun Zhang on Source Forge. CC: Xiaojun Zhang Signed-off-by: Don Skidmore Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 80e26ff..74e1921 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -544,7 +544,7 @@ struct ixgbe_fdir_filter { u16 action; }; -enum ixbge_state_t { +enum ixgbe_state_t { __IXGBE_TESTING, __IXGBE_RESETTING, __IXGBE_DOWN, -- cgit v0.10.2 From 8e4f3250f4162315fd57190d3364210eacafd7c7 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Fri, 16 Mar 2012 05:41:48 +0000 Subject: ixgbe: update version number Update the driver version number to better match version of out of tree driver that has similar functionality. Signed-off-by: Don Skidmore Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 6dbad2b..3e26b1f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -63,8 +63,8 @@ static char ixgbe_default_device_descr[] = "Intel(R) 10 Gigabit Network Connection"; #endif #define MAJ 3 -#define MIN 6 -#define BUILD 7 +#define MIN 8 +#define BUILD 21 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ __stringify(BUILD) "-k" const char ixgbe_driver_version[] = DRV_VERSION; -- cgit v0.10.2 From a28d73ca3ac7fffff317e62167ef26310b951ca0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 28 Mar 2012 10:31:36 +0200 Subject: microblaze: Fix tlb_skip variable on noMMU system TLBs are available only for MMU systems. Error log: arch/microblaze/kernel/setup.c: In function 'debugfs_tlb': arch/microblaze/kernel/setup.c:217: error: 'tlb_skip' undeclared (first use in this function) arch/microblaze/kernel/setup.c:217: error: (Each undeclared identifier is reported only once arch/microblaze/kernel/setup.c:217: error: for each function it appears in.) make[1]: *** [arch/microblaze/kernel/setup.o] Error 1 Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index e4f5956..61dc739 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -209,6 +209,7 @@ static int microblaze_debugfs_init(void) } arch_initcall(microblaze_debugfs_init); +# ifdef CONFIG_MMU static int __init debugfs_tlb(void) { struct dentry *d; @@ -221,6 +222,7 @@ static int __init debugfs_tlb(void) return -ENOMEM; } device_initcall(debugfs_tlb); +# endif #endif static int dflt_bus_notify(struct notifier_block *nb, -- cgit v0.10.2 From 2e57b79ccef1ff1422fdf45a9b28fe60f8f084f7 Mon Sep 17 00:00:00 2001 From: Rick Jones Date: Tue, 27 Mar 2012 07:28:09 +0000 Subject: virtio_net: do not rate limit counter increments While it is desirable to rate limit certain messages, it is not desirable to rate limit the incrementing of counters associated with those messages. Signed-off-by: Rick Jones Acked-by: Rusty Russell Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 019da01..4de2760 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -625,12 +625,13 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) /* This can happen with OOM and indirect buffers. */ if (unlikely(capacity < 0)) { - if (net_ratelimit()) { - if (likely(capacity == -ENOMEM)) { + if (likely(capacity == -ENOMEM)) { + if (net_ratelimit()) { dev_warn(&dev->dev, "TX queue failure: out of memory\n"); } else { - dev->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; + if (net_ratelimit()) dev_warn(&dev->dev, "Unexpected TX queue failure: %d\n", capacity); -- cgit v0.10.2 From 4e7b2f1454382b220f792a7fbcbebd0985187161 Mon Sep 17 00:00:00 2001 From: Benjamin LaHaise Date: Tue, 27 Mar 2012 15:55:32 +0000 Subject: net/ipv4: fix IPv4 multicast over network namespaces When using multicast over a local bridge feeding a number of LXC guests using veth, the LXC guests are unable to get a response from other guests when pinging 224.0.0.1. Multicast packets did not appear to be getting delivered to the network namespaces of the guest hosts, and further inspection showed that the incoming route was pointing to the loopback device of the host, not the guest. This lead to the wrong network namespace being picked up by sockets (like ICMP). Fix this by using the correct network namespace when creating the inbound route entry. Signed-off-by: Benjamin LaHaise Signed-off-by: David S. Miller diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 12ccf88..3b110a4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2042,7 +2042,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, if (err < 0) goto e_err; } - rth = rt_dst_alloc(init_net.loopback_dev, + rth = rt_dst_alloc(dev_net(dev)->loopback_dev, IN_DEV_CONF_GET(in_dev, NOPOLICY), false); if (!rth) goto e_nobufs; -- cgit v0.10.2 From 3b9785c6b0ff37ac4ef5085b38756283da84dceb Mon Sep 17 00:00:00 2001 From: Benjamin LaHaise Date: Tue, 27 Mar 2012 15:55:44 +0000 Subject: net/core: dev_forward_skb() should clear skb_iif While investigating another bug, I found that the code on the incoming path in __netif_receive_skb will only set skb->skb_iif if it is already 0. When dev_forward_skb() is used in the case of interfaces like veth, skb_iif may already have been set. Making dev_forward_skb() cause the packet to look like a newly received packet would seem to the the correct behaviour here, as otherwise the wrong incoming interface can be reported for such a packet. Signed-off-by: Benjamin LaHaise Signed-off-by: David S. Miller diff --git a/net/core/dev.c b/net/core/dev.c index 452db70..723a406 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1597,6 +1597,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) kfree_skb(skb); return NET_RX_DROP; } + skb->skb_iif = 0; skb_set_dev(skb, dev); skb->tstamp.tv64 = 0; skb->pkt_type = PACKET_HOST; -- cgit v0.10.2 From 2f2cc27f50e3d232602d3b7c972071b4a30e5e38 Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Tue, 27 Mar 2012 15:54:01 +0800 Subject: regulator: anatop: patching to device-tree property "reg". Change "reg" to "anatop-reg-offset" due to there is a warning of handling no size field in reg. This patch also adds the missing device-tree binding documentation. Signed-off-by: Ying-Chun Liu (PaulLiu) Acked-by: Shawn Guo Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt new file mode 100644 index 0000000..357758c --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt @@ -0,0 +1,29 @@ +Anatop Voltage regulators + +Required properties: +- compatible: Must be "fsl,anatop-regulator" +- anatop-reg-offset: Anatop MFD register offset +- anatop-vol-bit-shift: Bit shift for the register +- anatop-vol-bit-width: Number of bits used in the register +- anatop-min-bit-val: Minimum value of this register +- anatop-min-voltage: Minimum voltage of this regulator +- anatop-max-voltage: Maximum voltage of this regulator + +Any property defined as part of the core regulator +binding, defined in regulator.txt, can also be used. + +Example: + + regulator-vddpu { + compatible = "fsl,anatop-regulator"; + regulator-name = "vddpu"; + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + anatop-reg-offset = <0x140>; + anatop-vol-bit-shift = <9>; + anatop-vol-bit-width = <5>; + anatop-min-bit-val = <1>; + anatop-min-voltage = <725000>; + anatop-max-voltage = <1300000>; + }; diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 17499a5..53969af 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -138,9 +138,10 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev) rdesc->type = REGULATOR_VOLTAGE; rdesc->owner = THIS_MODULE; sreg->mfd = anatopmfd; - ret = of_property_read_u32(np, "reg", &sreg->control_reg); + ret = of_property_read_u32(np, "anatop-reg-offset", + &sreg->control_reg); if (ret) { - dev_err(dev, "no reg property set\n"); + dev_err(dev, "no anatop-reg-offset property set\n"); goto anatop_probe_end; } ret = of_property_read_u32(np, "anatop-vol-bit-width", -- cgit v0.10.2 From a171e782a97d4ba55d7fa02f9a46904288b2c229 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 15:17:26 +0800 Subject: regulator: wm831x-dcdc: Fix the logic to choose best current limit setting Current code in wm831x_buckv_set_current_limit actually set the current limit setting greater than specified range. Fix the logic in wm831x_buckv_set_current_limit to choose the smallest current limit setting falls within the specified range. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 3044001..ff810e7 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -380,7 +380,8 @@ static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev, int i; for (i = 0; i < ARRAY_SIZE(wm831x_dcdc_ilim); i++) { - if (max_uA <= wm831x_dcdc_ilim[i]) + if ((min_uA <= wm831x_dcdc_ilim[i]) && + (wm831x_dcdc_ilim[i] <= max_uA)) break; } if (i == ARRAY_SIZE(wm831x_dcdc_ilim)) -- cgit v0.10.2 From ed3be9a0e3c1050fe07d69a8c600d86cac76cdc4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 15:18:53 +0800 Subject: regulator: wm831x-isink: Fix the logic to choose best current limit setting Current code in wm831x_isink_set_current actually set the current limit setting smaller than specified range. Fix the logic in wm831x_isink_set_current to choose the smallest current limit setting falls within the specified range. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 634aac3..b414e09 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -101,7 +101,7 @@ static int wm831x_isink_set_current(struct regulator_dev *rdev, for (i = 0; i < ARRAY_SIZE(wm831x_isinkv_values); i++) { int val = wm831x_isinkv_values[i]; - if (min_uA >= val && val <= max_uA) { + if (min_uA <= val && val <= max_uA) { ret = wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_ISEL_MASK, i); return ret; -- cgit v0.10.2 From 3a744038b3709cd467b693f3e146c6d5b8120a18 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 15:20:08 +0800 Subject: regulator: wm8350: Fix the logic to choose best current limit setting Current implementation in get_isink_val actually choose the biggest current limit setting falls within the specified range. What we want is to choose the smallest current limit setting falls within the specified range. Fix it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index ff34654..f29803c 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -99,7 +99,7 @@ static int get_isink_val(int min_uA, int max_uA, u16 *setting) { int i; - for (i = ARRAY_SIZE(isink_cur) - 1; i >= 0; i--) { + for (i = 0; i < ARRAY_SIZE(isink_cur); i++) { if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) { *setting = i; return 0; -- cgit v0.10.2 From fa5a97bb0c65cb8d0382b72a55e2b87e15268289 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 15:21:45 +0800 Subject: regulator: Return microamps in wm8350_isink_get_current The values in isink_cur array are microamps. The regulator core expects get_current_limit callback to return microamps. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index f29803c..c5f3b40 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -186,7 +186,7 @@ static int wm8350_isink_get_current(struct regulator_dev *rdev) return 0; } - return DIV_ROUND_CLOSEST(isink_cur[val], 100); + return isink_cur[val]; } /* turn on ISINK followed by DCDC */ -- cgit v0.10.2 From 613c4578d4079a14dbee76ef7e0c80f635522fe3 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 28 Mar 2012 16:36:27 +0200 Subject: common: dma-mapping: introduce generic alloc() and free() methods Introduce new generic alloc and free methods with attributes argument. Existing alloc_coherent and free_coherent can be implemented on top of the new calls with NULL attributes argument. Later also dma_alloc_non_coherent can be implemented using DMA_ATTR_NONCOHERENT attribute as well as dma_alloc_writecombine with separate DMA_ATTR_WRITECOMBINE attribute. This way the drivers will get more generic, platform independent way of allocating dma buffers with specific parameters. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park Reviewed-by: David Gibson Reviewed-by: Arnd Bergmann diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index e13117c..8cc7f95 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -13,6 +13,12 @@ struct dma_map_ops { dma_addr_t *dma_handle, gfp_t gfp); void (*free_coherent)(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); + void* (*alloc)(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs); + void (*free)(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs); dma_addr_t (*map_page)(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, -- cgit v0.10.2 From baa676fcf8d555269bd0a5a2496782beee55824d Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 27 Mar 2012 14:28:18 +0200 Subject: X86 & IA64: adapt for dma_map_ops changes Adapt core x86 and IA64 architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Kyungmin Park [removed swiotlb related changes and replaced it with wrappers, merged with IA64 patch to avoid inter-patch dependences in intel-iommu code] Signed-off-by: Marek Szyprowski Reviewed-by: Arnd Bergmann Acked-by: Tony Luck diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index f5f4ef1..e5eb9c4 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -1130,7 +1130,8 @@ void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size, * See Documentation/DMA-API-HOWTO.txt */ static void * -sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags) +sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flags, struct dma_attrs *attrs) { struct ioc *ioc; void *addr; @@ -1192,8 +1193,8 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp * * See Documentation/DMA-API-HOWTO.txt */ -static void sba_free_coherent (struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_handle) +static void sba_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle, struct dma_attrs *attrs) { sba_unmap_single_attrs(dev, dma_handle, size, 0, NULL); free_pages((unsigned long) vaddr, get_order(size)); @@ -2213,8 +2214,8 @@ sba_page_override(char *str) __setup("sbapagesize=",sba_page_override); struct dma_map_ops sba_dma_ops = { - .alloc_coherent = sba_alloc_coherent, - .free_coherent = sba_free_coherent, + .alloc = sba_alloc_coherent, + .free = sba_free_coherent, .map_page = sba_map_page, .unmap_page = sba_unmap_page, .map_sg = sba_map_sg_attrs, diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index 4336d08..4f5e814 100644 --- a/arch/ia64/include/asm/dma-mapping.h +++ b/arch/ia64/include/asm/dma-mapping.h @@ -23,23 +23,29 @@ extern void machvec_dma_sync_single(struct device *, dma_addr_t, size_t, extern void machvec_dma_sync_sg(struct device *, struct scatterlist *, int, enum dma_data_direction); -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *daddr, gfp_t gfp) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *daddr, gfp_t gfp, + struct dma_attrs *attrs) { struct dma_map_ops *ops = platform_dma_get_ops(dev); void *caddr; - caddr = ops->alloc_coherent(dev, size, daddr, gfp); + caddr = ops->alloc(dev, size, daddr, gfp, attrs); debug_dma_alloc_coherent(dev, size, *daddr, caddr); return caddr; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *caddr, dma_addr_t daddr) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *caddr, dma_addr_t daddr, + struct dma_attrs *attrs) { struct dma_map_ops *ops = platform_dma_get_ops(dev); debug_dma_free_coherent(dev, size, caddr, daddr); - ops->free_coherent(dev, size, caddr, daddr); + ops->free(dev, size, caddr, daddr, attrs); } #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c index d9485d9..939260a 100644 --- a/arch/ia64/kernel/pci-swiotlb.c +++ b/arch/ia64/kernel/pci-swiotlb.c @@ -15,16 +15,24 @@ int swiotlb __read_mostly; EXPORT_SYMBOL(swiotlb); static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs) { if (dev->coherent_dma_mask != DMA_BIT_MASK(64)) gfp |= GFP_DMA; return swiotlb_alloc_coherent(dev, size, dma_handle, gfp); } +static void ia64_swiotlb_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_addr, + struct dma_attrs *attrs) +{ + swiotlb_free_coherent(dev, size, vaddr, dma_addr); +} + struct dma_map_ops swiotlb_dma_ops = { - .alloc_coherent = ia64_swiotlb_alloc_coherent, - .free_coherent = swiotlb_free_coherent, + .alloc = ia64_swiotlb_alloc_coherent, + .free = ia64_swiotlb_free_coherent, .map_page = swiotlb_map_page, .unmap_page = swiotlb_unmap_page, .map_sg = swiotlb_map_sg_attrs, diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index a9d310d..3290d6e 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -76,7 +76,8 @@ EXPORT_SYMBOL(sn_dma_set_mask); * more information. */ static void *sn_dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t * dma_handle, gfp_t flags) + dma_addr_t * dma_handle, gfp_t flags, + struct dma_attrs *attrs) { void *cpuaddr; unsigned long phys_addr; @@ -137,7 +138,7 @@ static void *sn_dma_alloc_coherent(struct device *dev, size_t size, * any associated IOMMU mappings. */ static void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, - dma_addr_t dma_handle) + dma_addr_t dma_handle, struct dma_attrs *attrs) { struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); @@ -466,8 +467,8 @@ int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) } static struct dma_map_ops sn_dma_ops = { - .alloc_coherent = sn_dma_alloc_coherent, - .free_coherent = sn_dma_free_coherent, + .alloc = sn_dma_alloc_coherent, + .free = sn_dma_free_coherent, .map_page = sn_dma_map_page, .unmap_page = sn_dma_unmap_page, .map_sg = sn_dma_map_sg, diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index ed3065f..4b4331d 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -59,7 +59,8 @@ extern int dma_supported(struct device *hwdev, u64 mask); extern int dma_set_mask(struct device *dev, u64 mask); extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addr, gfp_t flag); + dma_addr_t *dma_addr, gfp_t flag, + struct dma_attrs *attrs); static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) { @@ -111,9 +112,11 @@ static inline gfp_t dma_alloc_coherent_gfp_flags(struct device *dev, gfp_t gfp) return gfp; } +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + static inline void * -dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - gfp_t gfp) +dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t gfp, struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); void *memory; @@ -129,18 +132,21 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, if (!is_device_dma_capable(dev)) return NULL; - if (!ops->alloc_coherent) + if (!ops->alloc) return NULL; - memory = ops->alloc_coherent(dev, size, dma_handle, - dma_alloc_coherent_gfp_flags(dev, gfp)); + memory = ops->alloc(dev, size, dma_handle, + dma_alloc_coherent_gfp_flags(dev, gfp), attrs); debug_dma_alloc_coherent(dev, size, *dma_handle, memory); return memory; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t bus) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *vaddr, dma_addr_t bus, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); @@ -150,8 +156,8 @@ static inline void dma_free_coherent(struct device *dev, size_t size, return; debug_dma_free_coherent(dev, size, vaddr, bus); - if (ops->free_coherent) - ops->free_coherent(dev, size, vaddr, bus); + if (ops->free) + ops->free(dev, size, vaddr, bus, attrs); } #endif diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c index b1e7c7f..e663112 100644 --- a/arch/x86/kernel/amd_gart_64.c +++ b/arch/x86/kernel/amd_gart_64.c @@ -477,7 +477,7 @@ error: /* allocate and map a coherent mapping */ static void * gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, - gfp_t flag) + gfp_t flag, struct dma_attrs *attrs) { dma_addr_t paddr; unsigned long align_mask; @@ -500,7 +500,8 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, } __free_pages(page, get_order(size)); } else - return dma_generic_alloc_coherent(dev, size, dma_addr, flag); + return dma_generic_alloc_coherent(dev, size, dma_addr, flag, + attrs); return NULL; } @@ -508,7 +509,7 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, /* free a coherent mapping */ static void gart_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_addr) + dma_addr_t dma_addr, struct dma_attrs *attrs) { gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, NULL); free_pages((unsigned long)vaddr, get_order(size)); @@ -700,8 +701,8 @@ static struct dma_map_ops gart_dma_ops = { .unmap_sg = gart_unmap_sg, .map_page = gart_map_page, .unmap_page = gart_unmap_page, - .alloc_coherent = gart_alloc_coherent, - .free_coherent = gart_free_coherent, + .alloc = gart_alloc_coherent, + .free = gart_free_coherent, .mapping_error = gart_mapping_error, }; diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 726494b..07b587c 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -431,7 +431,7 @@ static void calgary_unmap_page(struct device *dev, dma_addr_t dma_addr, } static void* calgary_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, struct dma_attrs *attrs) { void *ret = NULL; dma_addr_t mapping; @@ -464,7 +464,8 @@ error: } static void calgary_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { unsigned int npages; struct iommu_table *tbl = find_iommu_table(dev); @@ -477,8 +478,8 @@ static void calgary_free_coherent(struct device *dev, size_t size, } static struct dma_map_ops calgary_dma_ops = { - .alloc_coherent = calgary_alloc_coherent, - .free_coherent = calgary_free_coherent, + .alloc = calgary_alloc_coherent, + .free = calgary_free_coherent, .map_sg = calgary_map_sg, .unmap_sg = calgary_unmap_sg, .map_page = calgary_map_page, diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 1c4d769..75e1cc1 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -96,7 +96,8 @@ void __init pci_iommu_alloc(void) } } void *dma_generic_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addr, gfp_t flag) + dma_addr_t *dma_addr, gfp_t flag, + struct dma_attrs *attrs) { unsigned long dma_mask; struct page *page; diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 3af4af8..f960506 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -75,7 +75,7 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, } static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_addr) + dma_addr_t dma_addr, struct dma_attrs *attrs) { free_pages((unsigned long)vaddr, get_order(size)); } @@ -96,8 +96,8 @@ static void nommu_sync_sg_for_device(struct device *dev, } struct dma_map_ops nommu_dma_ops = { - .alloc_coherent = dma_generic_alloc_coherent, - .free_coherent = nommu_free_coherent, + .alloc = dma_generic_alloc_coherent, + .free = nommu_free_coherent, .map_sg = nommu_map_sg, .map_page = nommu_map_page, .sync_single_for_device = nommu_sync_single_for_device, diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c index 8f972cb..6c483ba 100644 --- a/arch/x86/kernel/pci-swiotlb.c +++ b/arch/x86/kernel/pci-swiotlb.c @@ -15,21 +15,30 @@ int swiotlb __read_mostly; static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flags) + dma_addr_t *dma_handle, gfp_t flags, + struct dma_attrs *attrs) { void *vaddr; - vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags); + vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags, + attrs); if (vaddr) return vaddr; return swiotlb_alloc_coherent(hwdev, size, dma_handle, flags); } +static void x86_swiotlb_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_addr, + struct dma_attrs *attrs) +{ + swiotlb_free_coherent(dev, size, vaddr, dma_addr); +} + static struct dma_map_ops swiotlb_dma_ops = { .mapping_error = swiotlb_dma_mapping_error, - .alloc_coherent = x86_swiotlb_alloc_coherent, - .free_coherent = swiotlb_free_coherent, + .alloc = x86_swiotlb_alloc_coherent, + .free = x86_swiotlb_free_coherent, .sync_single_for_cpu = swiotlb_sync_single_for_cpu, .sync_single_for_device = swiotlb_sync_single_for_device, .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c index b480d42..967633a 100644 --- a/arch/x86/xen/pci-swiotlb-xen.c +++ b/arch/x86/xen/pci-swiotlb-xen.c @@ -12,8 +12,8 @@ int xen_swiotlb __read_mostly; static struct dma_map_ops xen_swiotlb_dma_ops = { .mapping_error = xen_swiotlb_dma_mapping_error, - .alloc_coherent = xen_swiotlb_alloc_coherent, - .free_coherent = xen_swiotlb_free_coherent, + .alloc = xen_swiotlb_alloc_coherent, + .free = xen_swiotlb_free_coherent, .sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu, .sync_single_for_device = xen_swiotlb_sync_single_for_device, .sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu, diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index f75e060..daa333f 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2707,7 +2707,8 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, * The exported alloc_coherent function for dma_ops. */ static void *alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addr, gfp_t flag) + dma_addr_t *dma_addr, gfp_t flag, + struct dma_attrs *attrs) { unsigned long flags; void *virt_addr; @@ -2765,7 +2766,8 @@ out_free: * The exported free_coherent function for dma_ops. */ static void free_coherent(struct device *dev, size_t size, - void *virt_addr, dma_addr_t dma_addr) + void *virt_addr, dma_addr_t dma_addr, + struct dma_attrs *attrs) { unsigned long flags; struct protection_domain *domain; @@ -2846,8 +2848,8 @@ static void prealloc_protection_domains(void) } static struct dma_map_ops amd_iommu_dma_ops = { - .alloc_coherent = alloc_coherent, - .free_coherent = free_coherent, + .alloc = alloc_coherent, + .free = free_coherent, .map_page = map_page, .unmap_page = unmap_page, .map_sg = map_sg, diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c9c6053..e39bfdc 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2938,7 +2938,8 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, } static void *intel_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flags) + dma_addr_t *dma_handle, gfp_t flags, + struct dma_attrs *attrs) { void *vaddr; int order; @@ -2970,7 +2971,7 @@ static void *intel_alloc_coherent(struct device *hwdev, size_t size, } static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr, - dma_addr_t dma_handle) + dma_addr_t dma_handle, struct dma_attrs *attrs) { int order; @@ -3115,8 +3116,8 @@ static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr) } struct dma_map_ops intel_dma_ops = { - .alloc_coherent = intel_alloc_coherent, - .free_coherent = intel_free_coherent, + .alloc = intel_alloc_coherent, + .free = intel_free_coherent, .map_sg = intel_map_sg, .unmap_sg = intel_unmap_sg, .map_page = intel_map_page, diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 19e6a20..1afb4fb 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -204,7 +204,8 @@ error: void * xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flags) + dma_addr_t *dma_handle, gfp_t flags, + struct dma_attrs *attrs) { void *ret; int order = get_order(size); @@ -253,7 +254,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent); void xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, - dma_addr_t dev_addr) + dma_addr_t dev_addr, struct dma_attrs *attrs) { int order = get_order(size); phys_addr_t phys; diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index 2ea2fdc..4f4d449 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h @@ -7,11 +7,13 @@ extern void xen_swiotlb_init(int verbose); extern void *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flags); + dma_addr_t *dma_handle, gfp_t flags, + struct dma_attrs *attrs); extern void xen_swiotlb_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle); + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs); extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, -- cgit v0.10.2 From e8d51e54ab4020d984dda471ca077c7fed094326 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 27 Mar 2012 14:32:21 +0200 Subject: MIPS: adapt for dma_map_ops changes Adapt core MIPS architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Kyungmin Park [added missing changes to arch/mips/cavium-octeon/dma-octeon.c, fixed attrs argument in dma-mapping.h] Signed-off-by: Marek Szyprowski Reviewed-by: Arnd Bergmann diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index b6bb92c..41dd0088 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -157,7 +157,7 @@ static void octeon_dma_sync_sg_for_device(struct device *dev, } static void *octeon_dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) + dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs) { void *ret; @@ -192,7 +192,7 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size, } static void octeon_dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs) { int order = get_order(size); @@ -240,8 +240,8 @@ EXPORT_SYMBOL(dma_to_phys); static struct octeon_dma_map_ops octeon_linear_dma_map_ops = { .dma_map_ops = { - .alloc_coherent = octeon_dma_alloc_coherent, - .free_coherent = octeon_dma_free_coherent, + .alloc = octeon_dma_alloc_coherent, + .free = octeon_dma_free_coherent, .map_page = octeon_dma_map_page, .unmap_page = swiotlb_unmap_page, .map_sg = octeon_dma_map_sg, @@ -325,8 +325,8 @@ void __init plat_swiotlb_setup(void) #ifdef CONFIG_PCI static struct octeon_dma_map_ops _octeon_pci_dma_map_ops = { .dma_map_ops = { - .alloc_coherent = octeon_dma_alloc_coherent, - .free_coherent = octeon_dma_free_coherent, + .alloc = octeon_dma_alloc_coherent, + .free = octeon_dma_free_coherent, .map_page = octeon_dma_map_page, .unmap_page = swiotlb_unmap_page, .map_sg = octeon_dma_map_sg, diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h index 7aa37dd..be39a12 100644 --- a/arch/mips/include/asm/dma-mapping.h +++ b/arch/mips/include/asm/dma-mapping.h @@ -57,25 +57,31 @@ dma_set_mask(struct device *dev, u64 mask) extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction); -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs) { void *ret; struct dma_map_ops *ops = get_dma_ops(dev); - ret = ops->alloc_coherent(dev, size, dma_handle, gfp); + ret = ops->alloc(dev, size, dma_handle, gfp, attrs); debug_dma_alloc_coherent(dev, size, *dma_handle, ret); return ret; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); - ops->free_coherent(dev, size, vaddr, dma_handle); + ops->free(dev, size, vaddr, dma_handle, attrs); debug_dma_free_coherent(dev, size, vaddr, dma_handle); } diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 4608491..3fab204 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -98,7 +98,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size, EXPORT_SYMBOL(dma_alloc_noncoherent); static void *mips_dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t * dma_handle, gfp_t gfp) + dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs) { void *ret; @@ -132,7 +132,7 @@ void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, EXPORT_SYMBOL(dma_free_noncoherent); static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_handle) + dma_addr_t dma_handle, struct dma_attrs *attrs) { unsigned long addr = (unsigned long) vaddr; int order = get_order(size); @@ -323,8 +323,8 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, EXPORT_SYMBOL(dma_cache_sync); static struct dma_map_ops mips_default_dma_map_ops = { - .alloc_coherent = mips_dma_alloc_coherent, - .free_coherent = mips_dma_free_coherent, + .alloc = mips_dma_alloc_coherent, + .free = mips_dma_free_coherent, .map_page = mips_dma_map_page, .unmap_page = mips_dma_unmap_page, .map_sg = mips_dma_map_sg, -- cgit v0.10.2 From bfbf7d615101391c4e24792685b64b38d84d542e Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 6 Dec 2011 14:14:46 +0100 Subject: PowerPC: adapt for dma_map_ops changes Adapt core PowerPC architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz [added missing changes to arch/powerpc/kernel/vio.c] Signed-off-by: Kyungmin Park Signed-off-by: Marek Szyprowski Reviewed-by: David Gibson Reviewed-by: Arnd Bergmann diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index dd70fac..62678e3 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -22,9 +22,11 @@ /* Some dma direct funcs must be visible for use in other dma_ops */ extern void *dma_direct_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag); + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs); extern void dma_direct_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs); #ifdef CONFIG_NOT_COHERENT_CACHE @@ -130,23 +132,29 @@ static inline int dma_supported(struct device *dev, u64 mask) extern int dma_set_mask(struct device *dev, u64 dma_mask); -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { struct dma_map_ops *dma_ops = get_dma_ops(dev); void *cpu_addr; BUG_ON(!dma_ops); - cpu_addr = dma_ops->alloc_coherent(dev, size, dma_handle, flag); + cpu_addr = dma_ops->alloc(dev, size, dma_handle, flag, attrs); debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr); return cpu_addr; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct dma_map_ops *dma_ops = get_dma_ops(dev); @@ -154,7 +162,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size, debug_dma_free_coherent(dev, size, cpu_addr, dma_handle); - dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); + dma_ops->free(dev, size, cpu_addr, dma_handle, attrs); } static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 3f6464b..bcfdcd2 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c @@ -17,7 +17,8 @@ * to the dma address (mapping) of the first page. */ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size, dma_handle, dev->coherent_dma_mask, flag, @@ -25,7 +26,8 @@ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, } static void dma_iommu_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle); } @@ -105,8 +107,8 @@ static u64 dma_iommu_get_required_mask(struct device *dev) } struct dma_map_ops dma_iommu_ops = { - .alloc_coherent = dma_iommu_alloc_coherent, - .free_coherent = dma_iommu_free_coherent, + .alloc = dma_iommu_alloc_coherent, + .free = dma_iommu_free_coherent, .map_sg = dma_iommu_map_sg, .unmap_sg = dma_iommu_unmap_sg, .dma_supported = dma_iommu_dma_supported, diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index 1ebc918..4ab88da 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c @@ -47,8 +47,8 @@ static u64 swiotlb_powerpc_get_required(struct device *dev) * for everything else. */ struct dma_map_ops swiotlb_dma_ops = { - .alloc_coherent = dma_direct_alloc_coherent, - .free_coherent = dma_direct_free_coherent, + .alloc = dma_direct_alloc_coherent, + .free = dma_direct_free_coherent, .map_sg = swiotlb_map_sg_attrs, .unmap_sg = swiotlb_unmap_sg_attrs, .dma_supported = swiotlb_dma_supported, diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 7d0233c..b1ec983 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c @@ -26,7 +26,8 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { void *ret; #ifdef CONFIG_NOT_COHERENT_CACHE @@ -54,7 +55,8 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size, } void dma_direct_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { #ifdef CONFIG_NOT_COHERENT_CACHE __dma_free_coherent(size, vaddr); @@ -150,8 +152,8 @@ static inline void dma_direct_sync_single(struct device *dev, #endif struct dma_map_ops dma_direct_ops = { - .alloc_coherent = dma_direct_alloc_coherent, - .free_coherent = dma_direct_free_coherent, + .alloc = dma_direct_alloc_coherent, + .free = dma_direct_free_coherent, .map_sg = dma_direct_map_sg, .unmap_sg = dma_direct_unmap_sg, .dma_supported = dma_direct_dma_supported, diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index d39ae60..716d918 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -65,7 +65,8 @@ static struct of_device_id __initdata ibmebus_matches[] = { static void *ibmebus_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - gfp_t flag) + gfp_t flag, + struct dma_attrs *attrs) { void *mem; @@ -77,7 +78,8 @@ static void *ibmebus_alloc_coherent(struct device *dev, static void ibmebus_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_handle) + dma_addr_t dma_handle, + struct dma_attrs *attrs) { kfree(vaddr); } @@ -136,8 +138,8 @@ static u64 ibmebus_dma_get_required_mask(struct device *dev) } static struct dma_map_ops ibmebus_dma_ops = { - .alloc_coherent = ibmebus_alloc_coherent, - .free_coherent = ibmebus_free_coherent, + .alloc = ibmebus_alloc_coherent, + .free = ibmebus_free_coherent, .map_sg = ibmebus_map_sg, .unmap_sg = ibmebus_unmap_sg, .dma_supported = ibmebus_dma_supported, diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 8b08629..2d49c32 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -487,7 +487,8 @@ static void vio_cmo_balance(struct work_struct *work) } static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { struct vio_dev *viodev = to_vio_dev(dev); void *ret; @@ -497,7 +498,7 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size, return NULL; } - ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag); + ret = dma_iommu_ops.alloc(dev, size, dma_handle, flag, attrs); if (unlikely(ret == NULL)) { vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE)); atomic_inc(&viodev->cmo.allocs_failed); @@ -507,11 +508,12 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size, } static void vio_dma_iommu_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct vio_dev *viodev = to_vio_dev(dev); - dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle); + dma_iommu_ops.free(dev, size, vaddr, dma_handle, attrs); vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE)); } @@ -612,8 +614,8 @@ static u64 vio_dma_get_required_mask(struct device *dev) } struct dma_map_ops vio_dma_mapping_ops = { - .alloc_coherent = vio_dma_iommu_alloc_coherent, - .free_coherent = vio_dma_iommu_free_coherent, + .alloc = vio_dma_iommu_alloc_coherent, + .free = vio_dma_iommu_free_coherent, .map_sg = vio_dma_iommu_map_sg, .unmap_sg = vio_dma_iommu_unmap_sg, .map_page = vio_dma_iommu_map_page, diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index ae9fc7b..b9f509a 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -564,7 +564,8 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev) /* A coherent allocation implies strong ordering */ static void *dma_fixed_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { if (iommu_fixed_is_weak) return iommu_alloc_coherent(dev, cell_get_iommu_table(dev), @@ -572,18 +573,19 @@ static void *dma_fixed_alloc_coherent(struct device *dev, size_t size, device_to_mask(dev), flag, dev_to_node(dev)); else - return dma_direct_ops.alloc_coherent(dev, size, dma_handle, - flag); + return dma_direct_ops.alloc(dev, size, dma_handle, flag, + attrs); } static void dma_fixed_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { if (iommu_fixed_is_weak) iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr, dma_handle); else - dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle); + dma_direct_ops.free(dev, size, vaddr, dma_handle, attrs); } static dma_addr_t dma_fixed_map_page(struct device *dev, struct page *page, @@ -642,8 +644,8 @@ static int dma_fixed_dma_supported(struct device *dev, u64 mask) static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask); struct dma_map_ops dma_iommu_fixed_ops = { - .alloc_coherent = dma_fixed_alloc_coherent, - .free_coherent = dma_fixed_free_coherent, + .alloc = dma_fixed_alloc_coherent, + .free = dma_fixed_free_coherent, .map_sg = dma_fixed_map_sg, .unmap_sg = dma_fixed_unmap_sg, .dma_supported = dma_fixed_dma_supported, diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 880eb9c..5606fe3 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -515,7 +515,8 @@ core_initcall(ps3_system_bus_init); * to the dma address (mapping) of the first page. */ static void * ps3_alloc_coherent(struct device *_dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { int result; struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); @@ -552,7 +553,7 @@ clean_none: } static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, - dma_addr_t dma_handle) + dma_addr_t dma_handle, struct dma_attrs *attrs) { struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); @@ -701,8 +702,8 @@ static u64 ps3_dma_get_required_mask(struct device *_dev) } static struct dma_map_ops ps3_sb_dma_ops = { - .alloc_coherent = ps3_alloc_coherent, - .free_coherent = ps3_free_coherent, + .alloc = ps3_alloc_coherent, + .free = ps3_free_coherent, .map_sg = ps3_sb_map_sg, .unmap_sg = ps3_sb_unmap_sg, .dma_supported = ps3_dma_supported, @@ -712,8 +713,8 @@ static struct dma_map_ops ps3_sb_dma_ops = { }; static struct dma_map_ops ps3_ioc0_dma_ops = { - .alloc_coherent = ps3_alloc_coherent, - .free_coherent = ps3_free_coherent, + .alloc = ps3_alloc_coherent, + .free = ps3_free_coherent, .map_sg = ps3_ioc0_map_sg, .unmap_sg = ps3_ioc0_unmap_sg, .dma_supported = ps3_dma_supported, -- cgit v0.10.2 From c416258a6e1e68a33fd328e872007d19941138c5 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 27 Mar 2012 14:56:55 +0200 Subject: SPARC: adapt for dma_map_ops changes Adapt core SPARC architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Kyungmin Park Signed-off-by: Marek Szyprowski Reviewed-by: Arnd Bergmann Acked-by: David S. Miller diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h index 8c0e4f7..48a7c65 100644 --- a/arch/sparc/include/asm/dma-mapping.h +++ b/arch/sparc/include/asm/dma-mapping.h @@ -26,24 +26,30 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev) #include -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); void *cpu_addr; - cpu_addr = ops->alloc_coherent(dev, size, dma_handle, flag); + cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs); debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr); return cpu_addr; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); debug_dma_free_coherent(dev, size, cpu_addr, dma_handle); - ops->free_coherent(dev, size, cpu_addr, dma_handle); + ops->free(dev, size, cpu_addr, dma_handle, attrs); } static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 4643d68..070ed14 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c @@ -280,7 +280,8 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx) } static void *dma_4u_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addrp, gfp_t gfp) + dma_addr_t *dma_addrp, gfp_t gfp, + struct dma_attrs *attrs) { unsigned long flags, order, first_page; struct iommu *iommu; @@ -330,7 +331,8 @@ static void *dma_4u_alloc_coherent(struct device *dev, size_t size, } static void dma_4u_free_coherent(struct device *dev, size_t size, - void *cpu, dma_addr_t dvma) + void *cpu, dma_addr_t dvma, + struct dma_attrs *attrs) { struct iommu *iommu; unsigned long flags, order, npages; @@ -825,8 +827,8 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev, } static struct dma_map_ops sun4u_dma_ops = { - .alloc_coherent = dma_4u_alloc_coherent, - .free_coherent = dma_4u_free_coherent, + .alloc = dma_4u_alloc_coherent, + .free = dma_4u_free_coherent, .map_page = dma_4u_map_page, .unmap_page = dma_4u_unmap_page, .map_sg = dma_4u_map_sg, diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index d0479e2..21bd739 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -261,7 +261,8 @@ EXPORT_SYMBOL(sbus_set_sbus64); * CPU may access them without any explicit flushing. */ static void *sbus_alloc_coherent(struct device *dev, size_t len, - dma_addr_t *dma_addrp, gfp_t gfp) + dma_addr_t *dma_addrp, gfp_t gfp, + struct dma_attrs *attrs) { struct platform_device *op = to_platform_device(dev); unsigned long len_total = PAGE_ALIGN(len); @@ -315,7 +316,7 @@ err_nopages: } static void sbus_free_coherent(struct device *dev, size_t n, void *p, - dma_addr_t ba) + dma_addr_t ba, struct dma_attrs *attrs) { struct resource *res; struct page *pgv; @@ -407,8 +408,8 @@ static void sbus_sync_sg_for_device(struct device *dev, struct scatterlist *sg, } struct dma_map_ops sbus_dma_ops = { - .alloc_coherent = sbus_alloc_coherent, - .free_coherent = sbus_free_coherent, + .alloc = sbus_alloc_coherent, + .free = sbus_free_coherent, .map_page = sbus_map_page, .unmap_page = sbus_unmap_page, .map_sg = sbus_map_sg, @@ -436,7 +437,8 @@ arch_initcall(sparc_register_ioport); * hwdev should be valid struct pci_dev pointer for PCI devices. */ static void *pci32_alloc_coherent(struct device *dev, size_t len, - dma_addr_t *pba, gfp_t gfp) + dma_addr_t *pba, gfp_t gfp, + struct dma_attrs *attrs) { unsigned long len_total = PAGE_ALIGN(len); void *va; @@ -489,7 +491,7 @@ err_nopages: * past this call are illegal. */ static void pci32_free_coherent(struct device *dev, size_t n, void *p, - dma_addr_t ba) + dma_addr_t ba, struct dma_attrs *attrs) { struct resource *res; @@ -645,8 +647,8 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist * } struct dma_map_ops pci32_dma_ops = { - .alloc_coherent = pci32_alloc_coherent, - .free_coherent = pci32_free_coherent, + .alloc = pci32_alloc_coherent, + .free = pci32_free_coherent, .map_page = pci32_map_page, .unmap_page = pci32_unmap_page, .map_sg = pci32_map_sg, diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index af5755d..7661e84 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c @@ -128,7 +128,8 @@ static inline long iommu_batch_end(void) } static void *dma_4v_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addrp, gfp_t gfp) + dma_addr_t *dma_addrp, gfp_t gfp, + struct dma_attrs *attrs) { unsigned long flags, order, first_page, npages, n; struct iommu *iommu; @@ -198,7 +199,7 @@ range_alloc_fail: } static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu, - dma_addr_t dvma) + dma_addr_t dvma, struct dma_attrs *attrs) { struct pci_pbm_info *pbm; struct iommu *iommu; @@ -527,8 +528,8 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist, } static struct dma_map_ops sun4v_dma_ops = { - .alloc_coherent = dma_4v_alloc_coherent, - .free_coherent = dma_4v_free_coherent, + .alloc = dma_4v_alloc_coherent, + .free = dma_4v_free_coherent, .map_page = dma_4v_map_page, .unmap_page = dma_4v_unmap_page, .map_sg = dma_4v_map_sg, -- cgit v0.10.2 From 4ce9a91f344d08640ea6e9a6eba0c1b4641ab6a1 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 22 Dec 2011 13:58:21 +0100 Subject: Alpha: adapt for dma_map_ops changes Adapt core Alpha architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Kyungmin Park Signed-off-by: Marek Szyprowski Reviewed-by: Arnd Bergmann Acked-by: Matt Turner diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h index 4567aca..dfa32f0 100644 --- a/arch/alpha/include/asm/dma-mapping.h +++ b/arch/alpha/include/asm/dma-mapping.h @@ -12,16 +12,22 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev) #include -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs) { - return get_dma_ops(dev)->alloc_coherent(dev, size, dma_handle, gfp); + return get_dma_ops(dev)->alloc(dev, size, dma_handle, gfp, attrs); } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { - get_dma_ops(dev)->free_coherent(dev, size, vaddr, dma_handle); + get_dma_ops(dev)->free(dev, size, vaddr, dma_handle, attrs); } static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c index 04eea48..df24b76 100644 --- a/arch/alpha/kernel/pci-noop.c +++ b/arch/alpha/kernel/pci-noop.c @@ -108,7 +108,8 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn, } static void *alpha_noop_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs) { void *ret; @@ -123,7 +124,8 @@ static void *alpha_noop_alloc_coherent(struct device *dev, size_t size, } static void alpha_noop_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_addr) + void *cpu_addr, dma_addr_t dma_addr, + struct dma_attrs *attrs) { free_pages((unsigned long)cpu_addr, get_order(size)); } @@ -174,8 +176,8 @@ static int alpha_noop_set_mask(struct device *dev, u64 mask) } struct dma_map_ops alpha_noop_ops = { - .alloc_coherent = alpha_noop_alloc_coherent, - .free_coherent = alpha_noop_free_coherent, + .alloc = alpha_noop_alloc_coherent, + .free = alpha_noop_free_coherent, .map_page = alpha_noop_map_page, .map_sg = alpha_noop_map_sg, .mapping_error = alpha_noop_mapping_error, diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index 4361080..cd63479 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -434,7 +434,8 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr, else DMA_ADDRP is undefined. */ static void *alpha_pci_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addrp, gfp_t gfp) + dma_addr_t *dma_addrp, gfp_t gfp, + struct dma_attrs *attrs) { struct pci_dev *pdev = alpha_gendev_to_pci(dev); void *cpu_addr; @@ -478,7 +479,8 @@ try_again: DMA_ADDR past this call are illegal. */ static void alpha_pci_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_addr) + void *cpu_addr, dma_addr_t dma_addr, + struct dma_attrs *attrs) { struct pci_dev *pdev = alpha_gendev_to_pci(dev); pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL); @@ -952,8 +954,8 @@ static int alpha_pci_set_mask(struct device *dev, u64 mask) } struct dma_map_ops alpha_pci_ops = { - .alloc_coherent = alpha_pci_alloc_coherent, - .free_coherent = alpha_pci_free_coherent, + .alloc = alpha_pci_alloc_coherent, + .free = alpha_pci_free_coherent, .map_page = alpha_pci_map_page, .unmap_page = alpha_pci_unmap_page, .map_sg = alpha_pci_map_sg, -- cgit v0.10.2 From 552c0d3ea68df46646d1f0dfcbf92a133c4e792b Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Wed, 14 Dec 2011 12:11:13 +0100 Subject: SH: adapt for dma_map_ops changes Adapt core SH architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Kyungmin Park Signed-off-by: Marek Szyprowski Reviewed-by: Arnd Bergmann Acked-by: Paul Mundt diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h index 1a73c3e..8bd965e 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -52,25 +52,31 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) return dma_addr == 0; } -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); void *memory; if (dma_alloc_from_coherent(dev, size, dma_handle, &memory)) return memory; - if (!ops->alloc_coherent) + if (!ops->alloc) return NULL; - memory = ops->alloc_coherent(dev, size, dma_handle, gfp); + memory = ops->alloc(dev, size, dma_handle, gfp, attrs); debug_dma_alloc_coherent(dev, size, *dma_handle, memory); return memory; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); @@ -78,14 +84,16 @@ static inline void dma_free_coherent(struct device *dev, size_t size, return; debug_dma_free_coherent(dev, size, vaddr, dma_handle); - if (ops->free_coherent) - ops->free_coherent(dev, size, vaddr, dma_handle); + if (ops->free) + ops->free(dev, size, vaddr, dma_handle, attrs); } /* arch/sh/mm/consistent.c */ extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addr, gfp_t flag); + dma_addr_t *dma_addr, gfp_t flag, + struct dma_attrs *attrs); extern void dma_generic_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs); #endif /* __ASM_SH_DMA_MAPPING_H */ diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c index 3c55b87..5b0bfcd 100644 --- a/arch/sh/kernel/dma-nommu.c +++ b/arch/sh/kernel/dma-nommu.c @@ -63,8 +63,8 @@ static void nommu_sync_sg(struct device *dev, struct scatterlist *sg, #endif struct dma_map_ops nommu_dma_ops = { - .alloc_coherent = dma_generic_alloc_coherent, - .free_coherent = dma_generic_free_coherent, + .alloc = dma_generic_alloc_coherent, + .free = dma_generic_free_coherent, .map_page = nommu_map_page, .map_sg = nommu_map_sg, #ifdef CONFIG_DMA_NONCOHERENT diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index f251b5f..b81d9db 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -33,7 +33,8 @@ static int __init dma_init(void) fs_initcall(dma_init); void *dma_generic_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs) { void *ret, *ret_nocache; int order = get_order(size); @@ -64,7 +65,8 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, } void dma_generic_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { int order = get_order(size); unsigned long pfn = dma_handle >> PAGE_SHIFT; -- cgit v0.10.2 From 988624ec13e87680eb3eaa0f1e921fedd48b4ac4 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 27 Mar 2012 14:56:04 +0200 Subject: Microblaze: adapt for dma_map_ops changes Adapt core Microblaze architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Kyungmin Park [fixed coding style issues] Signed-off-by: Marek Szyprowski Reviewed-by: Arnd Bergmann diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h index 3a3e5b8..01d2282 100644 --- a/arch/microblaze/include/asm/dma-mapping.h +++ b/arch/microblaze/include/asm/dma-mapping.h @@ -123,28 +123,34 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) +#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); void *memory; BUG_ON(!ops); - memory = ops->alloc_coherent(dev, size, dma_handle, flag); + memory = ops->alloc(dev, size, dma_handle, flag, attrs); debug_dma_alloc_coherent(dev, size, *dma_handle, memory); return memory; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d, s, c, h, NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct dma_map_ops *ops = get_dma_ops(dev); BUG_ON(!ops); debug_dma_free_coherent(dev, size, cpu_addr, dma_handle); - ops->free_coherent(dev, size, cpu_addr, dma_handle); + ops->free(dev, size, cpu_addr, dma_handle, attrs); } static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index 65a4af4..a2bfa2c 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -33,7 +33,8 @@ static unsigned long get_dma_direct_offset(struct device *dev) #define NOT_COHERENT_CACHE static void *dma_direct_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { #ifdef NOT_COHERENT_CACHE return consistent_alloc(flag, size, dma_handle); @@ -57,7 +58,8 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size, } static void dma_direct_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) + void *vaddr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { #ifdef NOT_COHERENT_CACHE consistent_free(size, vaddr); @@ -176,8 +178,8 @@ dma_direct_sync_sg_for_device(struct device *dev, } struct dma_map_ops dma_direct_ops = { - .alloc_coherent = dma_direct_alloc_coherent, - .free_coherent = dma_direct_free_coherent, + .alloc = dma_direct_alloc_coherent, + .free = dma_direct_free_coherent, .map_sg = dma_direct_map_sg, .unmap_sg = dma_direct_unmap_sg, .dma_supported = dma_direct_dma_supported, -- cgit v0.10.2 From ffc4a3faf74f00b568393b83e08104c70f33869c Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 27 Mar 2012 14:48:45 +0200 Subject: Unicore32: adapt for dma_map_ops changes Adapt core Unicore32 architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Kyungmin Park [added swiotlb_alloc/free_coherent wrappers] Signed-off-by: Marek Szyprowski Reviewed-by: Arnd Bergmann diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h index 9258e59..366460a 100644 --- a/arch/unicore32/include/asm/dma-mapping.h +++ b/arch/unicore32/include/asm/dma-mapping.h @@ -82,20 +82,26 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask) return 0; } -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { struct dma_map_ops *dma_ops = get_dma_ops(dev); - return dma_ops->alloc_coherent(dev, size, dma_handle, flag); + return dma_ops->alloc(dev, size, dma_handle, flag, attrs); } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct dma_map_ops *dma_ops = get_dma_ops(dev); - dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); + dma_ops->free(dev, size, cpu_addr, dma_handle, attrs); } #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) diff --git a/arch/unicore32/mm/dma-swiotlb.c b/arch/unicore32/mm/dma-swiotlb.c index bfa9fbb..16c08b2 100644 --- a/arch/unicore32/mm/dma-swiotlb.c +++ b/arch/unicore32/mm/dma-swiotlb.c @@ -17,9 +17,23 @@ #include +static void *unicore_swiotlb_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flags, + struct dma_attrs *attrs) +{ + return swiotlb_alloc_coherent(dev, size, dma_handle, flags); +} + +static void unicore_swiotlb_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_addr, + struct dma_attrs *attrs) +{ + swiotlb_free_coherent(dev, size, vaddr, dma_addr); +} + struct dma_map_ops swiotlb_dma_map_ops = { - .alloc_coherent = swiotlb_alloc_coherent, - .free_coherent = swiotlb_free_coherent, + .alloc = unicore_swiotlb_alloc_coherent, + .free = unicore_swiotlb_free_coherent, .map_sg = swiotlb_map_sg_attrs, .unmap_sg = swiotlb_unmap_sg_attrs, .dma_supported = swiotlb_dma_supported, -- cgit v0.10.2 From 77345520c465ccb85e4ed2c8ba352a159f60c2e4 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 13 Feb 2012 10:31:31 +0100 Subject: Hexagon: adapt for dma_map_ops changes Adapt core Hexagon architecture code for dma_map_ops changes: replace alloc/free_coherent with generic alloc/free methods. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park Reviewed-by: Arnd Bergmann Acked-by: Richard Kuo diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h index 448b224..233ed3d 100644 --- a/arch/hexagon/include/asm/dma-mapping.h +++ b/arch/hexagon/include/asm/dma-mapping.h @@ -71,29 +71,35 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) return (dma_addr == bad_dma_address); } -static inline void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) +#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) + +static inline void *dma_alloc_attrs(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { void *ret; struct dma_map_ops *ops = get_dma_ops(dev); BUG_ON(!dma_ops); - ret = ops->alloc_coherent(dev, size, dma_handle, flag); + ret = ops->alloc(dev, size, dma_handle, flag, attrs); debug_dma_alloc_coherent(dev, size, *dma_handle, ret); return ret; } -static inline void dma_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t dma_handle) +#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) + +static inline void dma_free_attrs(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle, + struct dma_attrs *attrs) { struct dma_map_ops *dma_ops = get_dma_ops(dev); BUG_ON(!dma_ops); - dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); + dma_ops->free(dev, size, cpu_addr, dma_handle, attrs); debug_dma_free_coherent(dev, size, cpu_addr, dma_handle); } diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c index e711ace..3730221 100644 --- a/arch/hexagon/kernel/dma.c +++ b/arch/hexagon/kernel/dma.c @@ -54,7 +54,8 @@ static struct gen_pool *coherent_pool; /* Allocates from a pool of uncached memory that was reserved at boot time */ void *hexagon_dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addr, gfp_t flag) + dma_addr_t *dma_addr, gfp_t flag, + struct dma_attrs *attrs) { void *ret; @@ -81,7 +82,7 @@ void *hexagon_dma_alloc_coherent(struct device *dev, size_t size, } static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_addr) + dma_addr_t dma_addr, struct dma_attrs *attrs) { gen_pool_free(coherent_pool, (unsigned long) vaddr, size); } @@ -202,8 +203,8 @@ static void hexagon_sync_single_for_device(struct device *dev, } struct dma_map_ops hexagon_dma_ops = { - .alloc_coherent = hexagon_dma_alloc_coherent, - .free_coherent = hexagon_free_coherent, + .alloc = hexagon_dma_alloc_coherent, + .free = hexagon_free_coherent, .map_sg = hexagon_map_sg, .map_page = hexagon_map_page, .sync_single_for_cpu = hexagon_sync_single_for_cpu, -- cgit v0.10.2 From 645ae3bce3e62541f8dc2701dde2a2791d842b6c Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 21 Dec 2011 16:55:57 +0100 Subject: common: dma-mapping: remove old alloc_coherent and free_coherent methods Remove old, unused alloc_coherent and free_coherent methods from dma_map_ops structure. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park Reviewed-by: Arnd Bergmann diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 8cc7f95..2fc413a 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -9,10 +9,6 @@ #include struct dma_map_ops { - void* (*alloc_coherent)(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp); - void (*free_coherent)(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); void* (*alloc)(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs); -- cgit v0.10.2 From 9adc537452e1e341cabd39a02d4788d3c510b0e2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 21 Dec 2011 16:55:33 +0100 Subject: common: dma-mapping: introduce mmap method Introduce new generic mmap method with attributes argument. This method lets drivers to create a userspace mapping for a DMA buffer in generic, architecture independent way. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park Reviewed-by: Arnd Bergmann diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 2fc413a..b903a20 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -15,6 +15,9 @@ struct dma_map_ops { void (*free)(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs); + int (*mmap)(struct device *, struct vm_area_struct *, + void *, dma_addr_t, size_t, struct dma_attrs *attrs); + dma_addr_t (*map_page)(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, -- cgit v0.10.2 From 8a4134322bd429d24f71147eb59a47a981e8f63a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 23 Dec 2011 09:30:47 +0100 Subject: common: DMA-mapping: add WRITE_COMBINE attribute DMA_ATTR_WRITE_COMBINE specifies that writes to the mapping may be buffered to improve performance. It will be used by the replacement for ARM/ARV32 specific dma_alloc_writecombine() function. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park Reviewed-by: Arnd Bergmann diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt index b768cc0..811a5d4 100644 --- a/Documentation/DMA-attributes.txt +++ b/Documentation/DMA-attributes.txt @@ -31,3 +31,13 @@ may be weakly ordered, that is that reads and writes may pass each other. Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING, those that do not will simply ignore the attribute and exhibit default behavior. + +DMA_ATTR_WRITE_COMBINE +---------------------- + +DMA_ATTR_WRITE_COMBINE specifies that writes to the mapping may be +buffered to improve performance. + +Since it is optional for platforms to implement DMA_ATTR_WRITE_COMBINE, +those that do not will simply ignore the attribute and exhibit default +behavior. diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h index 71ad34e..ada61e1 100644 --- a/include/linux/dma-attrs.h +++ b/include/linux/dma-attrs.h @@ -13,6 +13,7 @@ enum dma_attr { DMA_ATTR_WRITE_BARRIER, DMA_ATTR_WEAK_ORDERING, + DMA_ATTR_WRITE_COMBINE, DMA_ATTR_MAX, }; -- cgit v0.10.2 From 64d70fe5d3640e1a89790ed21120921278f8cb86 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 28 Mar 2012 07:55:56 +0200 Subject: common: DMA-mapping: add NON-CONSISTENT attribute DMA_ATTR_NON_CONSISTENT lets the platform to choose to return either consistent or non-consistent memory as it sees fit. By using this API, you are guaranteeing to the platform that you have all the correct and necessary sync points for this memory in the driver. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park Reviewed-by: Arnd Bergmann diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt index 811a5d4..5c72eed 100644 --- a/Documentation/DMA-attributes.txt +++ b/Documentation/DMA-attributes.txt @@ -41,3 +41,11 @@ buffered to improve performance. Since it is optional for platforms to implement DMA_ATTR_WRITE_COMBINE, those that do not will simply ignore the attribute and exhibit default behavior. + +DMA_ATTR_NON_CONSISTENT +----------------------- + +DMA_ATTR_NON_CONSISTENT lets the platform to choose to return either +consistent or non-consistent memory as it sees fit. By using this API, +you are guaranteeing to the platform that you have all the correct and +necessary sync points for this memory in the driver. diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h index ada61e1..547ab56 100644 --- a/include/linux/dma-attrs.h +++ b/include/linux/dma-attrs.h @@ -14,6 +14,7 @@ enum dma_attr { DMA_ATTR_WRITE_BARRIER, DMA_ATTR_WEAK_ORDERING, DMA_ATTR_WRITE_COMBINE, + DMA_ATTR_NON_CONSISTENT, DMA_ATTR_MAX, }; -- cgit v0.10.2 From 75836b8daefdde84f8b5dde1be5b67d858139df3 Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Tue, 20 Mar 2012 17:52:57 -0400 Subject: net/wireless: ipw2x00: fix a typo in wiphy struct initilization Fix comment as well. Signed-off-by: Stanislav Yakovlev Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 4fcdac6..2b02257 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11507,9 +11507,9 @@ static int ipw_wdev_init(struct net_device *dev) rc = -ENOMEM; goto out; } - /* translate geo->bg to a_band.channels */ + /* translate geo->a to a_band.channels */ for (i = 0; i < geo->a_channels; i++) { - a_band->channels[i].band = IEEE80211_BAND_2GHZ; + a_band->channels[i].band = IEEE80211_BAND_5GHZ; a_band->channels[i].center_freq = geo->a[i].freq; a_band->channels[i].hw_value = geo->a[i].channel; a_band->channels[i].max_power = geo->a[i].max_power; -- cgit v0.10.2 From e90c7e712980bf794f88f749e2a1270e4a4a116e Mon Sep 17 00:00:00 2001 From: Santosh Nayak Date: Thu, 22 Mar 2012 12:42:41 +0530 Subject: net: orinoco: add error handling for failed kmalloc(). With flag 'GFP_ATOMIC', probability of allocation failure is more. Add error handling after kmalloc() call to avoid null dereference. Signed-off-by: Santosh Nayak Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index dd6c64a..88e3ad2 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -1336,6 +1336,10 @@ static void qbuf_scan(struct orinoco_private *priv, void *buf, unsigned long flags; sd = kmalloc(sizeof(*sd), GFP_ATOMIC); + if (!sd) { + printk(KERN_ERR "%s: failed to alloc memory\n", __func__); + return; + } sd->buf = buf; sd->len = len; sd->type = type; @@ -1353,6 +1357,10 @@ static void qabort_scan(struct orinoco_private *priv) unsigned long flags; sd = kmalloc(sizeof(*sd), GFP_ATOMIC); + if (!sd) { + printk(KERN_ERR "%s: failed to alloc memory\n", __func__); + return; + } sd->len = -1; /* Abort */ spin_lock_irqsave(&priv->scan_lock, flags); -- cgit v0.10.2 From ca907a90735877ceff800d08f780f2f1b4388afa Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Sat, 24 Mar 2012 03:41:01 -0400 Subject: MAINTAINERS: adding maintainer for ipw2x00 Add myself as maintainer as suggested by Stanislaw Gruszka. Signed-off-by: Stanislav Yakovlev Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 0ddc77fe..09a79f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3519,17 +3519,13 @@ L: linux-pm@vger.kernel.org S: Supported F: arch/x86/platform/mrst/pmu.* -INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT +INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT +M: Stanislav Yakovlev L: linux-wireless@vger.kernel.org -S: Orphan +S: Maintained F: Documentation/networking/README.ipw2100 -F: drivers/net/wireless/ipw2x00/ipw2100.* - -INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT -L: linux-wireless@vger.kernel.org -S: Orphan F: Documentation/networking/README.ipw2200 -F: drivers/net/wireless/ipw2x00/ipw2200.* +F: drivers/net/wireless/ipw2x00/ INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) M: Joseph Cihula -- cgit v0.10.2 From a4d6367fa77fb604ce62582e1c0998e0ed098927 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 27 Mar 2012 10:08:55 +0530 Subject: ath9k: Use HW HT capabilites properly The commit "ath9k: Remove aggregation flags" changed how nodes were being initialized. Use the HW HT cap bits to initialize/de-initialize nodes, else we would be accessing an uninitialized entry during a suspend/resume cycle, resulting in a panic. Reported-by: Justin P. Mattock Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3879485..215eb25 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -640,7 +640,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, an->sta = sta; an->vif = vif; - if (sta->ht_cap.ht_supported) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { ath_tx_node_init(sc, an); an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor); @@ -659,7 +659,7 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) an->sta = NULL; #endif - if (sta->ht_cap.ht_supported) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) ath_tx_node_cleanup(sc, an); } -- cgit v0.10.2 From de312db345f9770b64ff39ef5a7f86f6358e93cc Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 27 Mar 2012 11:01:06 +0530 Subject: mac80211: fix oper channel timestamp updation Whenever the station informs the AP that it is about to leave the operating channel, the timestamp should be recorded. It is handled in scan resume but not in scan start. Fix that. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 33cd169..c70e176 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -370,7 +370,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) */ drv_sw_scan_start(local); - local->leave_oper_channel_time = 0; + local->leave_oper_channel_time = jiffies; local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; -- cgit v0.10.2 From fe2e39d8782d885755139304d8dba0b3e5bfa878 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Mar 2012 23:29:45 +0200 Subject: firmware_class: Rework usermodehelper check Instead of two functions, read_lock_usermodehelper() and usermodehelper_is_disabled(), used in combination, introduce usermodehelper_read_trylock() that will only return with umhelper_sem held if usermodehelper_disabled is unset (and will return -EAGAIN otherwise) and make _request_firmware() use it. Rename read_unlock_usermodehelper() to usermodehelper_read_unlock() to follow the naming convention of the new function. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Cc: stable@vger.kernel.org diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 6c9387d..deee871 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -533,12 +533,10 @@ static int _request_firmware(const struct firmware **firmware_p, return 0; } - read_lock_usermodehelper(); - - if (WARN_ON(usermodehelper_is_disabled())) { + retval = usermodehelper_read_trylock(); + if (WARN_ON(retval)) { dev_err(device, "firmware: %s will not be loaded\n", name); - retval = -EBUSY; - goto out; + goto out_nolock; } if (uevent) @@ -573,8 +571,9 @@ static int _request_firmware(const struct firmware **firmware_p, fw_destroy_instance(fw_priv); out: - read_unlock_usermodehelper(); + usermodehelper_read_unlock(); +out_nolock: if (retval) { release_firmware(firmware); *firmware_p = NULL; diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 9efeae6..97d22c3 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -114,8 +114,7 @@ extern void usermodehelper_init(void); extern int usermodehelper_disable(void); extern void usermodehelper_enable(void); -extern bool usermodehelper_is_disabled(void); -extern void read_lock_usermodehelper(void); -extern void read_unlock_usermodehelper(void); +extern int usermodehelper_read_trylock(void); +extern void usermodehelper_read_unlock(void); #endif /* __LINUX_KMOD_H__ */ diff --git a/kernel/kmod.c b/kernel/kmod.c index 957a7aa..4079ac1 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -339,17 +339,24 @@ static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq); */ #define RUNNING_HELPERS_TIMEOUT (5 * HZ) -void read_lock_usermodehelper(void) +int usermodehelper_read_trylock(void) { + int ret = 0; + down_read(&umhelper_sem); + if (usermodehelper_disabled) { + up_read(&umhelper_sem); + ret = -EAGAIN; + } + return ret; } -EXPORT_SYMBOL_GPL(read_lock_usermodehelper); +EXPORT_SYMBOL_GPL(usermodehelper_read_trylock); -void read_unlock_usermodehelper(void) +void usermodehelper_read_unlock(void) { up_read(&umhelper_sem); } -EXPORT_SYMBOL_GPL(read_unlock_usermodehelper); +EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); /** * usermodehelper_disable - prevent new helpers from being started @@ -390,15 +397,6 @@ void usermodehelper_enable(void) up_write(&umhelper_sem); } -/** - * usermodehelper_is_disabled - check if new helpers are allowed to be started - */ -bool usermodehelper_is_disabled(void) -{ - return usermodehelper_disabled; -} -EXPORT_SYMBOL_GPL(usermodehelper_is_disabled); - static void helper_lock(void) { atomic_inc(&running_helpers); -- cgit v0.10.2 From 811fa4004485dec8977176bf605a5b0508ee206c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Mar 2012 23:29:55 +0200 Subject: firmware_class: Split _request_firmware() into three functions, v2 Split _request_firmware() into three functions, _request_firmware_prepare() doing preparatory work that need not be done under umhelper_sem, _request_firmware_cleanup() doing the post-error cleanup and _request_firmware() carrying out the remaining operations. This change is requisite for moving the acquisition of umhelper_sem from _request_firmware() to the callers, which is going to be done subsequently. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Reviewed-by: Stephen Boyd Cc: stable@vger.kernel.org diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index deee871..6029067 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -435,7 +435,7 @@ static void firmware_class_timeout(u_long data) } static struct firmware_priv * -fw_create_instance(struct firmware *firmware, const char *fw_name, +fw_create_instance(const struct firmware *firmware, const char *fw_name, struct device *device, bool uevent, bool nowait) { struct firmware_priv *fw_priv; @@ -449,7 +449,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, goto err_out; } - fw_priv->fw = firmware; + fw_priv->fw = (struct firmware *)firmware; fw_priv->nowait = nowait; strcpy(fw_priv->fw_id, fw_name); init_completion(&fw_priv->completion); @@ -510,13 +510,10 @@ static void fw_destroy_instance(struct firmware_priv *fw_priv) device_unregister(f_dev); } -static int _request_firmware(const struct firmware **firmware_p, - const char *name, struct device *device, - bool uevent, bool nowait) +static int _request_firmware_prepare(const struct firmware **firmware_p, + const char *name, struct device *device) { - struct firmware_priv *fw_priv; struct firmware *firmware; - int retval = 0; if (!firmware_p) return -EINVAL; @@ -533,10 +530,26 @@ static int _request_firmware(const struct firmware **firmware_p, return 0; } + return 1; +} + +static void _request_firmware_cleanup(const struct firmware **firmware_p) +{ + release_firmware(*firmware_p); + *firmware_p = NULL; +} + +static int _request_firmware(const struct firmware *firmware, + const char *name, struct device *device, + bool uevent, bool nowait) +{ + struct firmware_priv *fw_priv; + int retval; + retval = usermodehelper_read_trylock(); if (WARN_ON(retval)) { dev_err(device, "firmware: %s will not be loaded\n", name); - goto out_nolock; + return retval; } if (uevent) @@ -572,13 +585,6 @@ static int _request_firmware(const struct firmware **firmware_p, out: usermodehelper_read_unlock(); - -out_nolock: - if (retval) { - release_firmware(firmware); - *firmware_p = NULL; - } - return retval; } @@ -601,7 +607,17 @@ int request_firmware(const struct firmware **firmware_p, const char *name, struct device *device) { - return _request_firmware(firmware_p, name, device, true, false); + int ret; + + ret = _request_firmware_prepare(firmware_p, name, device); + if (ret <= 0) + return ret; + + ret = _request_firmware(*firmware_p, name, device, true, false); + if (ret) + _request_firmware_cleanup(firmware_p); + + return ret; } /** @@ -639,8 +655,16 @@ static int request_firmware_work_func(void *arg) return 0; } - ret = _request_firmware(&fw, fw_work->name, fw_work->device, + ret = _request_firmware_prepare(&fw, fw_work->name, fw_work->device); + if (ret <= 0) + goto out; + + ret = _request_firmware(fw, fw_work->name, fw_work->device, fw_work->uevent, true); + if (ret) + _request_firmware_cleanup(&fw); + + out: fw_work->cont(fw, fw_work->context); module_put(fw_work->module); -- cgit v0.10.2 From 9b78c1da60b3c62ccdd1509f0902ad19ceaf776b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Mar 2012 23:30:02 +0200 Subject: firmware_class: Do not warn that system is not ready from async loads If firmware is requested asynchronously, by calling request_firmware_nowait(), there is no reason to fail the request (and warn the user) when the system is (presumably temporarily) unready to handle it (because user space is not available yet or frozen). For this reason, introduce an alternative routine for read-locking umhelper_sem, usermodehelper_read_lock_wait(), that will wait for usermodehelper_disabled to be unset (possibly with a timeout) and make request_firmware_work_func() use it instead of usermodehelper_read_trylock(). Accordingly, modify request_firmware() so that it uses usermodehelper_read_trylock() to acquire umhelper_sem and remove the code related to that lock from _request_firmware(). Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Cc: stable@vger.kernel.org diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 6029067..72c644b 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -81,6 +81,11 @@ enum { static int loading_timeout = 60; /* In seconds */ +static inline long firmware_loading_timeout(void) +{ + return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT; +} + /* fw_lock could be moved to 'struct firmware_priv' but since it is just * guarding for corner cases a global lock should be OK */ static DEFINE_MUTEX(fw_lock); @@ -541,31 +546,22 @@ static void _request_firmware_cleanup(const struct firmware **firmware_p) static int _request_firmware(const struct firmware *firmware, const char *name, struct device *device, - bool uevent, bool nowait) + bool uevent, bool nowait, long timeout) { struct firmware_priv *fw_priv; - int retval; - - retval = usermodehelper_read_trylock(); - if (WARN_ON(retval)) { - dev_err(device, "firmware: %s will not be loaded\n", name); - return retval; - } + int retval = 0; if (uevent) dev_dbg(device, "firmware: requesting %s\n", name); fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); - if (IS_ERR(fw_priv)) { - retval = PTR_ERR(fw_priv); - goto out; - } + if (IS_ERR(fw_priv)) + return PTR_ERR(fw_priv); if (uevent) { - if (loading_timeout > 0) + if (timeout != MAX_SCHEDULE_TIMEOUT) mod_timer(&fw_priv->timeout, - round_jiffies_up(jiffies + - loading_timeout * HZ)); + round_jiffies_up(jiffies + timeout)); kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); } @@ -582,9 +578,6 @@ static int _request_firmware(const struct firmware *firmware, mutex_unlock(&fw_lock); fw_destroy_instance(fw_priv); - -out: - usermodehelper_read_unlock(); return retval; } @@ -613,7 +606,14 @@ request_firmware(const struct firmware **firmware_p, const char *name, if (ret <= 0) return ret; - ret = _request_firmware(*firmware_p, name, device, true, false); + ret = usermodehelper_read_trylock(); + if (WARN_ON(ret)) { + dev_err(device, "firmware: %s will not be loaded\n", name); + } else { + ret = _request_firmware(*firmware_p, name, device, true, false, + firmware_loading_timeout()); + usermodehelper_read_unlock(); + } if (ret) _request_firmware_cleanup(firmware_p); @@ -648,6 +648,7 @@ static int request_firmware_work_func(void *arg) { struct firmware_work *fw_work = arg; const struct firmware *fw; + long timeout; int ret; if (!arg) { @@ -659,8 +660,16 @@ static int request_firmware_work_func(void *arg) if (ret <= 0) goto out; - ret = _request_firmware(fw, fw_work->name, fw_work->device, - fw_work->uevent, true); + timeout = usermodehelper_read_lock_wait(firmware_loading_timeout()); + if (timeout) { + ret = _request_firmware(fw, fw_work->name, fw_work->device, + fw_work->uevent, true, timeout); + usermodehelper_read_unlock(); + } else { + dev_dbg(fw_work->device, "firmware: %s loading timed out\n", + fw_work->name); + ret = -EAGAIN; + } if (ret) _request_firmware_cleanup(&fw); diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 97d22c3..b087377 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -115,6 +115,7 @@ extern void usermodehelper_init(void); extern int usermodehelper_disable(void); extern void usermodehelper_enable(void); extern int usermodehelper_read_trylock(void); +extern long usermodehelper_read_lock_wait(long timeout); extern void usermodehelper_read_unlock(void); #endif /* __LINUX_KMOD_H__ */ diff --git a/kernel/kmod.c b/kernel/kmod.c index 4079ac1..da7fcca 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -334,6 +334,12 @@ static atomic_t running_helpers = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq); /* + * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled + * to become 'false'. + */ +static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq); + +/* * Time to wait for running_helpers to become zero before the setting of * usermodehelper_disabled in usermodehelper_disable() fails */ @@ -352,6 +358,33 @@ int usermodehelper_read_trylock(void) } EXPORT_SYMBOL_GPL(usermodehelper_read_trylock); +long usermodehelper_read_lock_wait(long timeout) +{ + DEFINE_WAIT(wait); + + if (timeout < 0) + return -EINVAL; + + down_read(&umhelper_sem); + for (;;) { + prepare_to_wait(&usermodehelper_disabled_waitq, &wait, + TASK_UNINTERRUPTIBLE); + if (!usermodehelper_disabled) + break; + + up_read(&umhelper_sem); + + timeout = schedule_timeout(timeout); + if (!timeout) + break; + + down_read(&umhelper_sem); + } + finish_wait(&usermodehelper_disabled_waitq, &wait); + return timeout; +} +EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait); + void usermodehelper_read_unlock(void) { up_read(&umhelper_sem); @@ -359,6 +392,17 @@ void usermodehelper_read_unlock(void) EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); /** + * usermodehelper_enable - allow new helpers to be started again + */ +void usermodehelper_enable(void) +{ + down_write(&umhelper_sem); + usermodehelper_disabled = 0; + wake_up(&usermodehelper_disabled_waitq); + up_write(&umhelper_sem); +} + +/** * usermodehelper_disable - prevent new helpers from being started */ int usermodehelper_disable(void) @@ -381,22 +425,10 @@ int usermodehelper_disable(void) if (retval) return 0; - down_write(&umhelper_sem); - usermodehelper_disabled = 0; - up_write(&umhelper_sem); + usermodehelper_enable(); return -EAGAIN; } -/** - * usermodehelper_enable - allow new helpers to be started again - */ -void usermodehelper_enable(void) -{ - down_write(&umhelper_sem); - usermodehelper_disabled = 0; - up_write(&umhelper_sem); -} - static void helper_lock(void) { atomic_inc(&running_helpers); -- cgit v0.10.2 From 7b5179ac14dbad945647ac9e76bbbf14ed9e0dbe Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Mar 2012 23:30:14 +0200 Subject: PM / Hibernate: Disable usermode helpers right before freezing tasks There is no reason to call usermodehelper_disable() before creating memory bitmaps in hibernate() and software_resume(), so call it right before freeze_processes(), in accordance with the other suspend and hibernation code. Consequently, call usermodehelper_enable() right after the thawing of tasks rather than after freeing the memory bitmaps. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Cc: stable@vger.kernel.org diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 0a186cf..639ff6e 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -611,19 +611,19 @@ int hibernate(void) if (error) goto Exit; - error = usermodehelper_disable(); - if (error) - goto Exit; - /* Allocate memory management structures */ error = create_basic_memory_bitmaps(); if (error) - goto Enable_umh; + goto Exit; printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); printk("done.\n"); + error = usermodehelper_disable(); + if (error) + goto Exit; + error = freeze_processes(); if (error) goto Free_bitmaps; @@ -660,9 +660,8 @@ int hibernate(void) freezer_test_done = false; Free_bitmaps: - free_basic_memory_bitmaps(); - Enable_umh: usermodehelper_enable(); + free_basic_memory_bitmaps(); Exit: pm_notifier_call_chain(PM_POST_HIBERNATION); pm_restore_console(); @@ -777,15 +776,13 @@ static int software_resume(void) if (error) goto close_finish; - error = usermodehelper_disable(); + error = create_basic_memory_bitmaps(); if (error) goto close_finish; - error = create_basic_memory_bitmaps(); - if (error) { - usermodehelper_enable(); + error = usermodehelper_disable(); + if (error) goto close_finish; - } pr_debug("PM: Preparing processes for restore.\n"); error = freeze_processes(); @@ -805,8 +802,8 @@ static int software_resume(void) swsusp_free(); thaw_processes(); Done: - free_basic_memory_bitmaps(); usermodehelper_enable(); + free_basic_memory_bitmaps(); Finish: pm_notifier_call_chain(PM_POST_RESTORE); pm_restore_console(); -- cgit v0.10.2 From 1e73203cd1157a03facc41ffb54050f5b28e55bd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Mar 2012 23:30:21 +0200 Subject: PM / Sleep: Move disabling of usermode helpers to the freezer The core suspend/hibernation code calls usermodehelper_disable() to avoid race conditions between the freezer and the starting of usermode helpers and each code path has to do that on its own. However, it is always called right before freeze_processes() and usermodehelper_enable() is always called right after thaw_processes(). For this reason, to avoid code duplication and to make the connection between usermodehelper_disable() and the freezer more visible, make freeze_processes() call it and remove the direct usermodehelper_disable() and usermodehelper_enable() calls from all suspend/hibernation code paths. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Cc: stable@vger.kernel.org diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 639ff6e..e09dfbf 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -620,10 +619,6 @@ int hibernate(void) sys_sync(); printk("done.\n"); - error = usermodehelper_disable(); - if (error) - goto Exit; - error = freeze_processes(); if (error) goto Free_bitmaps; @@ -660,7 +655,6 @@ int hibernate(void) freezer_test_done = false; Free_bitmaps: - usermodehelper_enable(); free_basic_memory_bitmaps(); Exit: pm_notifier_call_chain(PM_POST_HIBERNATION); @@ -780,10 +774,6 @@ static int software_resume(void) if (error) goto close_finish; - error = usermodehelper_disable(); - if (error) - goto close_finish; - pr_debug("PM: Preparing processes for restore.\n"); error = freeze_processes(); if (error) { @@ -802,7 +792,6 @@ static int software_resume(void) swsusp_free(); thaw_processes(); Done: - usermodehelper_enable(); free_basic_memory_bitmaps(); Finish: pm_notifier_call_chain(PM_POST_RESTORE); diff --git a/kernel/power/process.c b/kernel/power/process.c index 0d2aeb2..56eaac7 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -16,6 +16,7 @@ #include #include #include +#include /* * Timeout for stopping processes @@ -122,6 +123,10 @@ int freeze_processes(void) { int error; + error = usermodehelper_disable(); + if (error) + return error; + if (!pm_freezing) atomic_inc(&system_freezing_cnt); @@ -187,6 +192,8 @@ void thaw_processes(void) } while_each_thread(g, p); read_unlock(&tasklist_lock); + usermodehelper_enable(); + schedule(); printk("done.\n"); } diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 88e5c967..396d262 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -102,17 +101,12 @@ static int suspend_prepare(void) if (error) goto Finish; - error = usermodehelper_disable(); - if (error) - goto Finish; - error = suspend_freeze_processes(); if (!error) return 0; suspend_stats.failed_freeze++; dpm_save_failed_step(SUSPEND_FREEZE); - usermodehelper_enable(); Finish: pm_notifier_call_chain(PM_POST_SUSPEND); pm_restore_console(); @@ -259,7 +253,6 @@ int suspend_devices_and_enter(suspend_state_t state) static void suspend_finish(void) { suspend_thaw_processes(); - usermodehelper_enable(); pm_notifier_call_chain(PM_POST_SUSPEND); pm_restore_console(); } diff --git a/kernel/power/user.c b/kernel/power/user.c index 33c4329..91b0fd0 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -222,14 +221,8 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, sys_sync(); printk("done.\n"); - error = usermodehelper_disable(); - if (error) - break; - error = freeze_processes(); - if (error) - usermodehelper_enable(); - else + if (!error) data->frozen = 1; break; @@ -238,7 +231,6 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, break; pm_restore_gfp_mask(); thaw_processes(); - usermodehelper_enable(); data->frozen = 0; break; -- cgit v0.10.2 From 247bc03742545fec2f79939a3b9f738392a0f7b4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 28 Mar 2012 23:30:28 +0200 Subject: PM / Sleep: Mitigate race between the freezer and request_firmware() There is a race condition between the freezer and request_firmware() such that if request_firmware() is run on one CPU and freeze_processes() is run on another CPU and usermodehelper_disable() called by it succeeds to grab umhelper_sem for writing before usermodehelper_read_trylock() called from request_firmware() acquires it for reading, the request_firmware() will fail and trigger a WARN_ON() complaining that it was called at a wrong time. However, in fact, it wasn't called at a wrong time and freeze_processes() simply happened to be executed simultaneously. To avoid this race, at least in some cases, modify usermodehelper_read_trylock() so that it doesn't fail if the freezing of tasks has just started and hasn't been completed yet. Instead, during the freezing of tasks, it will try to freeze the task that has called it so that it can wait until user space is thawed without triggering the scary warning. For this purpose, change usermodehelper_disabled so that it can take three different values, UMH_ENABLED (0), UMH_FREEZING and UMH_DISABLED. The first one means that usermode helpers are enabled, the last one means "hard disable" (i.e. the system is not ready for usermode helpers to be used) and the second one is reserved for the freezer. Namely, when freeze_processes() is started, it sets usermodehelper_disabled to UMH_FREEZING which tells usermodehelper_read_trylock() that it shouldn't fail just yet and should call try_to_freeze() if woken up and cannot return immediately. This way all freezable tasks that happen to call request_firmware() right before freeze_processes() is started and lose the race for umhelper_sem with it will be frozen and will sleep until thaw_processes() unsets usermodehelper_disabled. [For the non-freezable callers of request_firmware() the race for umhelper_sem against freeze_processes() is unfortunately unavoidable.] Reported-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Cc: stable@vger.kernel.org diff --git a/include/linux/kmod.h b/include/linux/kmod.h index b087377..dd99c329 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -110,10 +110,27 @@ call_usermodehelper(char *path, char **argv, char **envp, int wait) extern struct ctl_table usermodehelper_table[]; +enum umh_disable_depth { + UMH_ENABLED = 0, + UMH_FREEZING, + UMH_DISABLED, +}; + extern void usermodehelper_init(void); -extern int usermodehelper_disable(void); -extern void usermodehelper_enable(void); +extern int __usermodehelper_disable(enum umh_disable_depth depth); +extern void __usermodehelper_set_disable_depth(enum umh_disable_depth depth); + +static inline int usermodehelper_disable(void) +{ + return __usermodehelper_disable(UMH_DISABLED); +} + +static inline void usermodehelper_enable(void) +{ + __usermodehelper_set_disable_depth(UMH_ENABLED); +} + extern int usermodehelper_read_trylock(void); extern long usermodehelper_read_lock_wait(long timeout); extern void usermodehelper_read_unlock(void); diff --git a/kernel/kmod.c b/kernel/kmod.c index da7fcca..05698a7 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -322,7 +322,7 @@ static void __call_usermodehelper(struct work_struct *work) * land has been frozen during a system-wide hibernation or suspend operation). * Should always be manipulated under umhelper_sem acquired for write. */ -static int usermodehelper_disabled = 1; +static enum umh_disable_depth usermodehelper_disabled = UMH_DISABLED; /* Number of helpers running */ static atomic_t running_helpers = ATOMIC_INIT(0); @@ -347,13 +347,30 @@ static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq); int usermodehelper_read_trylock(void) { + DEFINE_WAIT(wait); int ret = 0; down_read(&umhelper_sem); - if (usermodehelper_disabled) { + for (;;) { + prepare_to_wait(&usermodehelper_disabled_waitq, &wait, + TASK_INTERRUPTIBLE); + if (!usermodehelper_disabled) + break; + + if (usermodehelper_disabled == UMH_DISABLED) + ret = -EAGAIN; + up_read(&umhelper_sem); - ret = -EAGAIN; + + if (ret) + break; + + schedule(); + try_to_freeze(); + + down_read(&umhelper_sem); } + finish_wait(&usermodehelper_disabled_waitq, &wait); return ret; } EXPORT_SYMBOL_GPL(usermodehelper_read_trylock); @@ -392,25 +409,35 @@ void usermodehelper_read_unlock(void) EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); /** - * usermodehelper_enable - allow new helpers to be started again + * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled. + * depth: New value to assign to usermodehelper_disabled. + * + * Change the value of usermodehelper_disabled (under umhelper_sem locked for + * writing) and wakeup tasks waiting for it to change. */ -void usermodehelper_enable(void) +void __usermodehelper_set_disable_depth(enum umh_disable_depth depth) { down_write(&umhelper_sem); - usermodehelper_disabled = 0; + usermodehelper_disabled = depth; wake_up(&usermodehelper_disabled_waitq); up_write(&umhelper_sem); } /** - * usermodehelper_disable - prevent new helpers from being started + * __usermodehelper_disable - Prevent new helpers from being started. + * @depth: New value to assign to usermodehelper_disabled. + * + * Set usermodehelper_disabled to @depth and wait for running helpers to exit. */ -int usermodehelper_disable(void) +int __usermodehelper_disable(enum umh_disable_depth depth) { long retval; + if (!depth) + return -EINVAL; + down_write(&umhelper_sem); - usermodehelper_disabled = 1; + usermodehelper_disabled = depth; up_write(&umhelper_sem); /* @@ -425,7 +452,7 @@ int usermodehelper_disable(void) if (retval) return 0; - usermodehelper_enable(); + __usermodehelper_set_disable_depth(UMH_ENABLED); return -EAGAIN; } diff --git a/kernel/power/process.c b/kernel/power/process.c index 56eaac7..19db29f 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -123,7 +123,7 @@ int freeze_processes(void) { int error; - error = usermodehelper_disable(); + error = __usermodehelper_disable(UMH_FREEZING); if (error) return error; @@ -135,6 +135,7 @@ int freeze_processes(void) error = try_to_freeze_tasks(true); if (!error) { printk("done."); + __usermodehelper_set_disable_depth(UMH_DISABLED); oom_killer_disable(); } printk("\n"); -- cgit v0.10.2 From dddb5549da6b15ea8b9ce9ee0859c8d1fa268b5b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 28 Mar 2012 23:30:43 +0200 Subject: firmware_class: Reorganize fw_create_instance() Recent patches to split up the three phases of request_firmware() lead to a casting away of const in fw_create_instance(). We can avoid this cast by splitting up fw_create_instance() a bit. Make _request_firmware_setup() return a struct fw_priv and use that struct instead of passing struct firmware to _request_firmware(). Move the uevent and device file creation bits to the loading phase and rename the function to _request_firmware_load() to better reflect its purpose. Signed-off-by: Stephen Boyd Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 72c644b..ae00a2f 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -440,21 +440,19 @@ static void firmware_class_timeout(u_long data) } static struct firmware_priv * -fw_create_instance(const struct firmware *firmware, const char *fw_name, +fw_create_instance(struct firmware *firmware, const char *fw_name, struct device *device, bool uevent, bool nowait) { struct firmware_priv *fw_priv; struct device *f_dev; - int error; fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL); if (!fw_priv) { dev_err(device, "%s: kmalloc failed\n", __func__); - error = -ENOMEM; - goto err_out; + return ERR_PTR(-ENOMEM); } - fw_priv->fw = (struct firmware *)firmware; + fw_priv->fw = firmware; fw_priv->nowait = nowait; strcpy(fw_priv->fw_id, fw_name); init_completion(&fw_priv->completion); @@ -468,74 +466,37 @@ fw_create_instance(const struct firmware *firmware, const char *fw_name, f_dev->parent = device; f_dev->class = &firmware_class; - dev_set_uevent_suppress(f_dev, true); - - /* Need to pin this module until class device is destroyed */ - __module_get(THIS_MODULE); - - error = device_add(f_dev); - if (error) { - dev_err(device, "%s: device_register failed\n", __func__); - goto err_put_dev; - } - - error = device_create_bin_file(f_dev, &firmware_attr_data); - if (error) { - dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__); - goto err_del_dev; - } - - error = device_create_file(f_dev, &dev_attr_loading); - if (error) { - dev_err(device, "%s: device_create_file failed\n", __func__); - goto err_del_bin_attr; - } - - if (uevent) - dev_set_uevent_suppress(f_dev, false); - return fw_priv; - -err_del_bin_attr: - device_remove_bin_file(f_dev, &firmware_attr_data); -err_del_dev: - device_del(f_dev); -err_put_dev: - put_device(f_dev); -err_out: - return ERR_PTR(error); -} - -static void fw_destroy_instance(struct firmware_priv *fw_priv) -{ - struct device *f_dev = &fw_priv->dev; - - device_remove_file(f_dev, &dev_attr_loading); - device_remove_bin_file(f_dev, &firmware_attr_data); - device_unregister(f_dev); } -static int _request_firmware_prepare(const struct firmware **firmware_p, - const char *name, struct device *device) +static struct firmware_priv * +_request_firmware_prepare(const struct firmware **firmware_p, const char *name, + struct device *device, bool uevent, bool nowait) { struct firmware *firmware; + struct firmware_priv *fw_priv; if (!firmware_p) - return -EINVAL; + return ERR_PTR(-EINVAL); *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) { dev_err(device, "%s: kmalloc(struct firmware) failed\n", __func__); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } if (fw_get_builtin_firmware(firmware, name)) { dev_dbg(device, "firmware: using built-in firmware %s\n", name); - return 0; + return NULL; } - return 1; + fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); + if (IS_ERR(fw_priv)) { + release_firmware(firmware); + *firmware_p = NULL; + } + return fw_priv; } static void _request_firmware_cleanup(const struct firmware **firmware_p) @@ -544,21 +505,38 @@ static void _request_firmware_cleanup(const struct firmware **firmware_p) *firmware_p = NULL; } -static int _request_firmware(const struct firmware *firmware, - const char *name, struct device *device, - bool uevent, bool nowait, long timeout) +static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, + long timeout) { - struct firmware_priv *fw_priv; int retval = 0; + struct device *f_dev = &fw_priv->dev; + + dev_set_uevent_suppress(f_dev, true); - if (uevent) - dev_dbg(device, "firmware: requesting %s\n", name); + /* Need to pin this module until class device is destroyed */ + __module_get(THIS_MODULE); - fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); - if (IS_ERR(fw_priv)) - return PTR_ERR(fw_priv); + retval = device_add(f_dev); + if (retval) { + dev_err(f_dev, "%s: device_register failed\n", __func__); + goto err_put_dev; + } + + retval = device_create_bin_file(f_dev, &firmware_attr_data); + if (retval) { + dev_err(f_dev, "%s: sysfs_create_bin_file failed\n", __func__); + goto err_del_dev; + } + + retval = device_create_file(f_dev, &dev_attr_loading); + if (retval) { + dev_err(f_dev, "%s: device_create_file failed\n", __func__); + goto err_del_bin_attr; + } if (uevent) { + dev_set_uevent_suppress(f_dev, false); + dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_id); if (timeout != MAX_SCHEDULE_TIMEOUT) mod_timer(&fw_priv->timeout, round_jiffies_up(jiffies + timeout)); @@ -577,7 +555,13 @@ static int _request_firmware(const struct firmware *firmware, fw_priv->fw = NULL; mutex_unlock(&fw_lock); - fw_destroy_instance(fw_priv); + device_remove_file(f_dev, &dev_attr_loading); +err_del_bin_attr: + device_remove_bin_file(f_dev, &firmware_attr_data); +err_del_dev: + device_del(f_dev); +err_put_dev: + put_device(f_dev); return retval; } @@ -600,17 +584,19 @@ int request_firmware(const struct firmware **firmware_p, const char *name, struct device *device) { + struct firmware_priv *fw_priv; int ret; - ret = _request_firmware_prepare(firmware_p, name, device); - if (ret <= 0) - return ret; + fw_priv = _request_firmware_prepare(firmware_p, name, device, true, + false); + if (IS_ERR_OR_NULL(fw_priv)) + return PTR_RET(fw_priv); ret = usermodehelper_read_trylock(); if (WARN_ON(ret)) { dev_err(device, "firmware: %s will not be loaded\n", name); } else { - ret = _request_firmware(*firmware_p, name, device, true, false, + ret = _request_firmware_load(fw_priv, true, firmware_loading_timeout()); usermodehelper_read_unlock(); } @@ -648,6 +634,7 @@ static int request_firmware_work_func(void *arg) { struct firmware_work *fw_work = arg; const struct firmware *fw; + struct firmware_priv *fw_priv; long timeout; int ret; @@ -656,14 +643,16 @@ static int request_firmware_work_func(void *arg) return 0; } - ret = _request_firmware_prepare(&fw, fw_work->name, fw_work->device); - if (ret <= 0) + fw_priv = _request_firmware_prepare(&fw, fw_work->name, fw_work->device, + fw_work->uevent, true); + if (IS_ERR_OR_NULL(fw_priv)) { + ret = PTR_RET(fw_priv); goto out; + } timeout = usermodehelper_read_lock_wait(firmware_loading_timeout()); if (timeout) { - ret = _request_firmware(fw, fw_work->name, fw_work->device, - fw_work->uevent, true, timeout); + ret = _request_firmware_load(fw_priv, fw_work->uevent, timeout); usermodehelper_read_unlock(); } else { dev_dbg(fw_work->device, "firmware: %s loading timed out\n", -- cgit v0.10.2 From a36cf844c543c6193445a7b1492d16e5a8cf376e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 28 Mar 2012 23:31:00 +0200 Subject: firmware_class: Move request_firmware_nowait() to workqueues Oddly enough a work_struct was already part of the firmware_work structure but nobody was using it. Instead of creating a new kthread for each request_firmware_nowait() call just schedule the work on the system workqueue. This should avoid some overhead in forking new threads when they're not strictly necessary. Signed-off-by: Stephen Boyd Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index ae00a2f..5401814 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -16,10 +16,11 @@ #include #include #include -#include +#include #include #include #include +#include #define to_dev(obj) container_of(obj, struct device, kobj) @@ -630,19 +631,15 @@ struct firmware_work { bool uevent; }; -static int request_firmware_work_func(void *arg) +static void request_firmware_work_func(struct work_struct *work) { - struct firmware_work *fw_work = arg; + struct firmware_work *fw_work; const struct firmware *fw; struct firmware_priv *fw_priv; long timeout; int ret; - if (!arg) { - WARN_ON(1); - return 0; - } - + fw_work = container_of(work, struct firmware_work, work); fw_priv = _request_firmware_prepare(&fw, fw_work->name, fw_work->device, fw_work->uevent, true); if (IS_ERR_OR_NULL(fw_priv)) { @@ -667,8 +664,6 @@ static int request_firmware_work_func(void *arg) module_put(fw_work->module); kfree(fw_work); - - return ret; } /** @@ -694,7 +689,6 @@ request_firmware_nowait( const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)) { - struct task_struct *task; struct firmware_work *fw_work; fw_work = kzalloc(sizeof (struct firmware_work), gfp); @@ -713,15 +707,8 @@ request_firmware_nowait( return -EFAULT; } - task = kthread_run(request_firmware_work_func, fw_work, - "firmware/%s", name); - if (IS_ERR(task)) { - fw_work->cont(NULL, fw_work->context); - module_put(fw_work->module); - kfree(fw_work); - return PTR_ERR(task); - } - + INIT_WORK(&fw_work->work, request_firmware_work_func); + schedule_work(&fw_work->work); return 0; } -- cgit v0.10.2 From c4772d192c70b61d52262b0db76f7abd8aeb51c6 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Wed, 28 Mar 2012 23:31:24 +0200 Subject: PM / QoS: add pm_qos_update_request_timeout() API The new API, pm_qos_update_request_timeout() is to provide a timeout with pm_qos_update_request. For example, pm_qos_update_request_timeout(req, 100, 1000), means that QoS request on req with value 100 will be active for 1000 microseconds. After 1000 microseconds, the QoS request thru req is reset. If there were another pm_qos_update_request(req, x) during the 1000 us, this new request with value x will override as this is another request on the same req handle. A new request on the same req handle will always override the previous request whether it is the conventional request or it is the new timeout request. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Acked-by: Mark Gross Signed-off-by: Rafael J. Wysocki diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 2e9191a..233149c 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -8,6 +8,7 @@ #include #include #include +#include enum { PM_QOS_RESERVED = 0, @@ -29,6 +30,7 @@ enum { struct pm_qos_request { struct plist_node node; int pm_qos_class; + struct delayed_work work; /* for pm_qos_update_request_timeout */ }; struct dev_pm_qos_request { @@ -73,6 +75,8 @@ void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class, s32 value); void pm_qos_update_request(struct pm_qos_request *req, s32 new_value); +void pm_qos_update_request_timeout(struct pm_qos_request *req, + s32 new_value, unsigned long timeout_us); void pm_qos_remove_request(struct pm_qos_request *req); int pm_qos_request(int pm_qos_class); diff --git a/kernel/power/qos.c b/kernel/power/qos.c index d6d6dbd..6a031e6 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -230,6 +230,21 @@ int pm_qos_request_active(struct pm_qos_request *req) EXPORT_SYMBOL_GPL(pm_qos_request_active); /** + * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout + * @work: work struct for the delayed work (timeout) + * + * This cancels the timeout request by falling back to the default at timeout. + */ +static void pm_qos_work_fn(struct work_struct *work) +{ + struct pm_qos_request *req = container_of(to_delayed_work(work), + struct pm_qos_request, + work); + + pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE); +} + +/** * pm_qos_add_request - inserts new qos request into the list * @req: pointer to a preallocated handle * @pm_qos_class: identifies which list of qos request to use @@ -253,6 +268,7 @@ void pm_qos_add_request(struct pm_qos_request *req, return; } req->pm_qos_class = pm_qos_class; + INIT_DELAYED_WORK(&req->work, pm_qos_work_fn); pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints, &req->node, PM_QOS_ADD_REQ, value); } @@ -279,6 +295,9 @@ void pm_qos_update_request(struct pm_qos_request *req, return; } + if (delayed_work_pending(&req->work)) + cancel_delayed_work_sync(&req->work); + if (new_value != req->node.prio) pm_qos_update_target( pm_qos_array[req->pm_qos_class]->constraints, @@ -287,6 +306,34 @@ void pm_qos_update_request(struct pm_qos_request *req, EXPORT_SYMBOL_GPL(pm_qos_update_request); /** + * pm_qos_update_request_timeout - modifies an existing qos request temporarily. + * @req : handle to list element holding a pm_qos request to use + * @new_value: defines the temporal qos request + * @timeout_us: the effective duration of this qos request in usecs. + * + * After timeout_us, this qos request is cancelled automatically. + */ +void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value, + unsigned long timeout_us) +{ + if (!req) + return; + if (WARN(!pm_qos_request_active(req), + "%s called for unknown object.", __func__)) + return; + + if (delayed_work_pending(&req->work)) + cancel_delayed_work_sync(&req->work); + + if (new_value != req->node.prio) + pm_qos_update_target( + pm_qos_array[req->pm_qos_class]->constraints, + &req->node, PM_QOS_UPDATE_REQ, new_value); + + schedule_delayed_work(&req->work, usecs_to_jiffies(timeout_us)); +} + +/** * pm_qos_remove_request - modifies an existing qos request * @req: handle to request list element * @@ -305,6 +352,9 @@ void pm_qos_remove_request(struct pm_qos_request *req) return; } + if (delayed_work_pending(&req->work)) + cancel_delayed_work_sync(&req->work); + pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints, &req->node, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); -- cgit v0.10.2 From 0b5f9c005def154f9c21f9be0223b65b50d54368 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 29 Mar 2012 15:38:30 +1030 Subject: remove references to cpu_*_map in arch/ This has been obsolescent for a while; time for the final push. In adjacent context, replaced old cpus_* with cpumask_*. Signed-off-by: Rusty Russell Acked-by: David S. Miller (arch/sparc) Acked-by: Chris Metcalf (arch/tile) Cc: user-mode-linux-devel@lists.sourceforge.net Cc: Russell King Cc: linux-arm-kernel@lists.infradead.org Cc: Richard Kuo Cc: linux-hexagon@vger.kernel.org Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Cc: Kyle McMartin Cc: Helge Deller Cc: sparclinux@vger.kernel.org diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 129c116..a79e5c7 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c @@ -127,7 +127,7 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) flush_insns(addr, sizeof(u16)); } else if (addr & 2) { /* A 32-bit instruction spanning two words needs special care */ - stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map); + stop_machine(set_t32_breakpoint, (void *)addr, cpu_online_mask); } else { /* Word aligned 32-bit instruction can be written atomically */ u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION; @@ -190,7 +190,7 @@ int __kprobes __arch_disarm_kprobe(void *p) void __kprobes arch_disarm_kprobe(struct kprobe *p) { - stop_machine(__arch_disarm_kprobe, p, &cpu_online_map); + stop_machine(__arch_disarm_kprobe, p, cpu_online_mask); } void __kprobes arch_remove_kprobe(struct kprobe *p) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8f8cce2..9a4bdde 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -354,7 +354,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) * re-initialize the map in platform_smp_prepare_cpus() if * present != possible (e.g. physical hotplug). */ - init_cpu_present(&cpu_possible_map); + init_cpu_present(cpu_possible_mask); /* * Initialise the SCU if there are more than one CPU @@ -586,8 +586,9 @@ void smp_send_stop(void) unsigned long timeout; if (num_online_cpus() > 1) { - cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); + struct cpumask mask; + cpumask_copy(&mask, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &mask); smp_cross_call(&mask, IPI_CPU_STOP); } diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index 15d1fd2..9b44a9e 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -35,7 +35,7 @@ #define BASE_IPI_IRQ 26 /* - * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas + * cpu_possible_mask needs to be filled out prior to setup_per_cpu_areas * (which is prior to any of our smp_prepare_cpu crap), in order to set * up the... per_cpu areas. */ @@ -208,7 +208,7 @@ int __cpuinit __cpu_up(unsigned int cpu) stack_start = ((void *) thread) + THREAD_SIZE; __vmstart(start_secondary, stack_start); - while (!cpu_isset(cpu, cpu_online_map)) + while (!cpu_online(cpu)) barrier(); return 0; @@ -229,7 +229,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) /* Right now, let's just fake it. */ for (i = 0; i < max_cpus; i++) - cpu_set(i, cpu_present_map); + set_cpu_present(i, true); /* Also need to register the interrupts for IPI */ if (max_cpus > 1) @@ -269,5 +269,5 @@ void smp_start_cpus(void) int i; for (i = 0; i < NR_CPUS; i++) - cpu_set(i, cpu_possible_map); + set_cpu_possible(i, true); } diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index c3e2b85..ef56d8a 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -268,7 +268,7 @@ static int octeon_cpu_disable(void) spin_lock(&smp_reserve_lock); - cpu_clear(cpu, cpu_online_map); + set_cpu_online(cpu, false); cpu_clear(cpu, cpu_callin_map); local_irq_disable(); fixup_irqs(); diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index 802e616..33f63ba 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -173,7 +173,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len, if (retval) goto out_unlock; - cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map); + cpumask_and(&mask, &p->thread.user_cpus_allowed, cpu_possible_mask); out_unlock: read_unlock(&tasklist_lock); diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index e309665..f8b2c59 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -25,7 +25,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) int i; #ifdef CONFIG_SMP - if (!cpu_isset(n, cpu_online_map)) + if (!cpu_online(n)) return 0; #endif diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index ca67356..3046e29 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -317,7 +317,7 @@ static int bmips_cpu_disable(void) pr_info("SMP: CPU%d is offline\n", cpu); - cpu_clear(cpu, cpu_online_map); + set_cpu_online(cpu, false); cpu_clear(cpu, cpu_callin_map); local_flush_tlb_all(); diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 9c1cce9..ba9376b 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -148,7 +148,7 @@ static void stop_this_cpu(void *dummy) /* * Remove this CPU: */ - cpu_clear(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), false); for (;;) { if (cpu_wait) (*cpu_wait)(); /* Wait if available. */ @@ -174,7 +174,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) mp_ops->prepare_cpus(max_cpus); set_cpu_sibling_map(0); #ifndef CONFIG_HOTPLUG_CPU - init_cpu_present(&cpu_possible_map); + init_cpu_present(cpu_possible_mask); #endif } @@ -248,7 +248,7 @@ int __cpuinit __cpu_up(unsigned int cpu) while (!cpu_isset(cpu, cpu_callin_map)) udelay(100); - cpu_set(cpu, cpu_online_map); + set_cpu_online(cpu, true); return 0; } @@ -320,13 +320,12 @@ void flush_tlb_mm(struct mm_struct *mm) if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { smp_on_other_tlbs(flush_tlb_mm_ipi, mm); } else { - cpumask_t mask = cpu_online_map; unsigned int cpu; - cpu_clear(smp_processor_id(), mask); - for_each_cpu_mask(cpu, mask) - if (cpu_context(cpu, mm)) + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id() && cpu_context(cpu, mm)) cpu_context(cpu, mm) = 0; + } } local_flush_tlb_mm(mm); @@ -360,13 +359,12 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned l smp_on_other_tlbs(flush_tlb_range_ipi, &fd); } else { - cpumask_t mask = cpu_online_map; unsigned int cpu; - cpu_clear(smp_processor_id(), mask); - for_each_cpu_mask(cpu, mask) - if (cpu_context(cpu, mm)) + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id() && cpu_context(cpu, mm)) cpu_context(cpu, mm) = 0; + } } local_flush_tlb_range(vma, start, end); preempt_enable(); @@ -407,13 +405,12 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) smp_on_other_tlbs(flush_tlb_page_ipi, &fd); } else { - cpumask_t mask = cpu_online_map; unsigned int cpu; - cpu_clear(smp_processor_id(), mask); - for_each_cpu_mask(cpu, mask) - if (cpu_context(cpu, vma->vm_mm)) + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id() && cpu_context(cpu, vma->vm_mm)) cpu_context(cpu, vma->vm_mm) = 0; + } } local_flush_tlb_page(vma, page); preempt_enable(); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index c4f75bb..f5dd38f 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -291,7 +291,7 @@ static void smtc_configure_tlb(void) * possibly leave some TCs/VPEs as "slave" processors. * * Use c0_MVPConf0 to find out how many TCs are available, setting up - * cpu_possible_map and the logical/physical mappings. + * cpu_possible_mask and the logical/physical mappings. */ int __init smtc_build_cpu_map(int start_cpu_slot) diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index 1f9ca07..47037ec 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -80,9 +80,9 @@ static void octeon_flush_icache_all_cores(struct vm_area_struct *vma) if (vma) mask = *mm_cpumask(vma->vm_mm); else - mask = cpu_online_map; - cpu_clear(cpu, mask); - for_each_cpu_mask(cpu, mask) + mask = *cpu_online_mask; + cpumask_clear_cpu(cpu, &mask); + for_each_cpu(cpu, &mask) octeon_send_ipi_single(cpu, SMP_ICACHE_FLUSH); preempt_enable(); diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index db17f49..fab316d 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -165,7 +165,7 @@ void __init nlm_smp_setup(void) cpu_set(boot_cpu, phys_cpu_present_map); __cpu_number_map[boot_cpu] = 0; __cpu_logical_map[0] = boot_cpu; - cpu_set(0, cpu_possible_map); + set_cpu_possible(0, true); num_cpus = 1; for (i = 0; i < NR_CPUS; i++) { @@ -177,14 +177,14 @@ void __init nlm_smp_setup(void) cpu_set(i, phys_cpu_present_map); __cpu_number_map[i] = num_cpus; __cpu_logical_map[num_cpus] = i; - cpu_set(num_cpus, cpu_possible_map); + set_cpu_possible(num_cpus, true); ++num_cpus; } } pr_info("Phys CPU present map: %lx, possible map %lx\n", (unsigned long)phys_cpu_present_map.bits[0], - (unsigned long)cpu_possible_map.bits[0]); + (unsigned long)cpumask_bits(cpu_possible_mask)[0]); pr_info("Detected %i Slave CPU(s)\n", num_cpus); nlm_set_nmi_handler(nlm_boot_secondary_cpus); diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 2608752..00a0d2e 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -155,10 +155,10 @@ static void __init yos_smp_setup(void) { int i; - cpus_clear(cpu_possible_map); + init_cpu_possible(cpu_none_mask); for (i = 0; i < 2; i++) { - cpu_set(i, cpu_possible_map); + set_cpu_possible(i, true); __cpu_number_map[i] = i; __cpu_logical_map[i] = i; } @@ -169,7 +169,7 @@ static void __init yos_prepare_cpus(unsigned int max_cpus) /* * Be paranoid. Enable the IPI only if we're really about to go SMP. */ - if (cpus_weight(cpu_possible_map)) + if (num_possible_cpus()) set_c0_status(STATUSF_IP5); } diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index c6851df..735b43b 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -76,7 +76,7 @@ static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest) /* Only let it join in if it's marked enabled */ if ((acpu->cpu_info.flags & KLINFO_ENABLE) && (tot_cpus_found != NR_CPUS)) { - cpu_set(cpuid, cpu_possible_map); + set_cpu_possible(cpuid, true); alloc_cpupda(cpuid, tot_cpus_found); cpus_found++; tot_cpus_found++; diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index d667875..63d2211 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -147,14 +147,13 @@ static void __init bcm1480_smp_setup(void) { int i, num; - cpus_clear(cpu_possible_map); - cpu_set(0, cpu_possible_map); + init_cpu_possible(cpumask_of(0)); __cpu_number_map[0] = 0; __cpu_logical_map[0] = 0; for (i = 1, num = 0; i < NR_CPUS; i++) { if (cfe_cpu_stop(i) == 0) { - cpu_set(i, cpu_possible_map); + set_cpu_possible(i, true); __cpu_number_map[i] = ++num; __cpu_logical_map[num] = i; } diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 38e7f6b..285cfef 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -126,7 +126,7 @@ static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle) /* * Use CFE to find out how many CPUs are available, setting up - * cpu_possible_map and the logical/physical mappings. + * cpu_possible_mask and the logical/physical mappings. * XXXKW will the boot CPU ever not be physical 0? * * Common setup before any secondaries are started @@ -135,14 +135,13 @@ static void __init sb1250_smp_setup(void) { int i, num; - cpus_clear(cpu_possible_map); - cpu_set(0, cpu_possible_map); + init_cpu_possible(cpumask_of(0)); __cpu_number_map[0] = 0; __cpu_logical_map[0] = 0; for (i = 1, num = 0; i < NR_CPUS; i++) { if (cfe_cpu_stop(i) == 0) { - cpu_set(i, cpu_possible_map); + set_cpu_possible(i, true); __cpu_number_map[i] = ++num; __cpu_logical_map[num] = i; } diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index a19c8a0..35e4367 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -104,11 +104,11 @@ static int irq_choose_cpu(const struct cpumask *affinity) { cpumask_t mask; - cpus_and(mask, cpu_online_map, *affinity); - if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask)) + cpumask_and(&mask, cpu_online_mask, affinity); + if (cpumask_equal(&mask, cpu_online_mask) || cpumask_empty(&mask)) return boot_cpu_id; else - return first_cpu(mask); + return cpumask_first(&mask); } #else #define irq_choose_cpu(affinity) boot_cpu_id diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 5f85d8b..5124093 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -1186,7 +1186,7 @@ static void __init setup_cpu_maps(void) sizeof(cpu_lotar_map)); if (rc < 0) { pr_err("warning: no HV_INQ_TILES_LOTAR; using AVAIL\n"); - cpu_lotar_map = cpu_possible_map; + cpu_lotar_map = *cpu_possible_mask; } #if CHIP_HAS_CBOX_HOME_MAP() @@ -1196,9 +1196,9 @@ static void __init setup_cpu_maps(void) sizeof(hash_for_home_map)); if (rc < 0) early_panic("hv_inquire_tiles(HFH_CACHE) failed: rc %d\n", rc); - cpumask_or(&cpu_cacheable_map, &cpu_possible_map, &hash_for_home_map); + cpumask_or(&cpu_cacheable_map, cpu_possible_mask, &hash_for_home_map); #else - cpu_cacheable_map = cpu_possible_map; + cpu_cacheable_map = *cpu_possible_mask; #endif } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 2e9852c..0a9e57e 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -41,7 +41,7 @@ static int __init start_kernel_proc(void *unused) cpu_tasks[0].pid = pid; cpu_tasks[0].task = current; #ifdef CONFIG_SMP - cpu_online_map = cpumask_of_cpu(0); + init_cpu_online(get_cpu_mask(0)); #endif start_kernel(); return 0; diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 155206a..6f588e1 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -76,7 +76,7 @@ static int idle_proc(void *cpup) cpu_relax(); notify_cpu_starting(cpu); - cpu_set(cpu, cpu_online_map); + set_cpu_online(cpu, true); default_idle(); return 0; } @@ -110,8 +110,7 @@ void smp_prepare_cpus(unsigned int maxcpus) for (i = 0; i < ncpus; ++i) set_cpu_possible(i, true); - cpu_clear(me, cpu_online_map); - cpu_set(me, cpu_online_map); + set_cpu_online(me, true); cpu_set(me, cpu_callin_map); err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); @@ -138,13 +137,13 @@ void smp_prepare_cpus(unsigned int maxcpus) void smp_prepare_boot_cpu(void) { - cpu_set(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), true); } int __cpu_up(unsigned int cpu) { cpu_set(cpu, smp_commenced_mask); - while (!cpu_isset(cpu, cpu_online_map)) + while (!cpu_online(cpu)) mb(); return 0; } -- cgit v0.10.2 From 88d8cd52bc9dd7696617b31ea91263d6c47f22e4 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 29 Mar 2012 15:38:30 +1030 Subject: drivers/cpufreq/db8500-cpufreq: remove references to cpu_*_map. This has been obsolescent for a while; time for the final push. Signed-off-by: Rusty Russell Cc: Dave Jones Cc: cpufreq@vger.kernel.org Cc: Sundar Iyer Cc: Martin Persson Cc: Jonas Aaberg diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index a22ffa5..0bf1b89 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -142,7 +142,7 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */ /* policy sharing between dual CPUs */ - cpumask_copy(policy->cpus, &cpu_present_map); + cpumask_copy(policy->cpus, cpu_present_mask); policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; -- cgit v0.10.2 From 5f054e31c63be774bf1ce252f20d56012a00f8a5 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 29 Mar 2012 15:38:31 +1030 Subject: documentation: remove references to cpu_*_map. This has been obsolescent for a while, fix documentation and misc comments. Signed-off-by: Rusty Russell diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt index 5c51ed4..cefd3d8 100644 --- a/Documentation/cgroups/cpusets.txt +++ b/Documentation/cgroups/cpusets.txt @@ -217,7 +217,7 @@ and name space for cpusets, with a minimum of additional kernel code. The cpus and mems files in the root (top_cpuset) cpuset are read-only. The cpus file automatically tracks the value of -cpu_online_map using a CPU hotplug notifier, and the mems file +cpu_online_mask using a CPU hotplug notifier, and the mems file automatically tracks the value of node_states[N_HIGH_MEMORY]--i.e., nodes with memory--using the cpuset_track_online_nodes() hook. diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index a20bfd4..66ef8f3 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt @@ -47,7 +47,7 @@ maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using other cpus later online, read FAQ's for more info. additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets - cpu_possible_map = cpu_present_map + additional_cpus + cpu_possible_mask = cpu_present_mask + additional_cpus cede_offline={"off","on"} Use this option to disable/enable putting offlined processors to an extended H_CEDE state on @@ -64,11 +64,11 @@ should only rely on this to count the # of cpus, but *MUST* not rely on the apicid values in those tables for disabled apics. In the event BIOS doesn't mark such hot-pluggable cpus as disabled entries, one could use this parameter "additional_cpus=x" to represent those cpus in the -cpu_possible_map. +cpu_possible_mask. possible_cpus=n [s390,x86_64] use this to set hotpluggable cpus. This option sets possible_cpus bits in - cpu_possible_map. Thus keeping the numbers of bits set + cpu_possible_mask. Thus keeping the numbers of bits set constant even if the machine gets rebooted. CPU maps and such @@ -76,7 +76,7 @@ CPU maps and such [More on cpumaps and primitive to manipulate, please check include/linux/cpumask.h that has more descriptive text.] -cpu_possible_map: Bitmap of possible CPUs that can ever be available in the +cpu_possible_mask: Bitmap of possible CPUs that can ever be available in the system. This is used to allocate some boot time memory for per_cpu variables that aren't designed to grow/shrink as CPUs are made available or removed. Once set during boot time discovery phase, the map is static, i.e no bits @@ -84,13 +84,13 @@ are added or removed anytime. Trimming it accurately for your system needs upfront can save some boot time memory. See below for how we use heuristics in x86_64 case to keep this under check. -cpu_online_map: Bitmap of all CPUs currently online. Its set in __cpu_up() +cpu_online_mask: Bitmap of all CPUs currently online. Its set in __cpu_up() after a cpu is available for kernel scheduling and ready to receive interrupts from devices. Its cleared when a cpu is brought down using __cpu_disable(), before which all OS services including interrupts are migrated to another target CPU. -cpu_present_map: Bitmap of CPUs currently present in the system. Not all +cpu_present_mask: Bitmap of CPUs currently present in the system. Not all of them may be online. When physical hotplug is processed by the relevant subsystem (e.g ACPI) can change and new bit either be added or removed from the map depending on the event is hot-add/hot-remove. There are currently @@ -99,22 +99,22 @@ at which time hotplug is disabled. You really dont need to manipulate any of the system cpu maps. They should be read-only for most use. When setting up per-cpu resources almost always use -cpu_possible_map/for_each_possible_cpu() to iterate. +cpu_possible_mask/for_each_possible_cpu() to iterate. Never use anything other than cpumask_t to represent bitmap of CPUs. #include - for_each_possible_cpu - Iterate over cpu_possible_map - for_each_online_cpu - Iterate over cpu_online_map - for_each_present_cpu - Iterate over cpu_present_map + for_each_possible_cpu - Iterate over cpu_possible_mask + for_each_online_cpu - Iterate over cpu_online_mask + for_each_present_cpu - Iterate over cpu_present_mask for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask. #include get_online_cpus() and put_online_cpus(): The above calls are used to inhibit cpu hotplug operations. While the -cpu_hotplug.refcount is non zero, the cpu_online_map will not change. +cpu_hotplug.refcount is non zero, the cpu_online_mask will not change. If you merely need to avoid cpus going away, you could also use preempt_disable() and preempt_enable() for those sections. Just remember the critical section cannot call any diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 4087a56..50d438d 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -450,7 +450,7 @@ setup_smp(void) smp_num_probed = 1; } - printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n", + printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n", smp_num_probed, cpumask_bits(cpu_present_mask)[0]); } diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index ac795d3..6f38b61 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -839,7 +839,7 @@ static __init int setup_additional_cpus(char *s) early_param("additional_cpus", setup_additional_cpus); /* - * cpu_possible_map should be static, it cannot change as CPUs + * cpu_possible_mask should be static, it cannot change as CPUs * are onlined, or offlined. The reason is per-cpu data-structures * are allocated by some modules at init time, and dont expect to * do this dynamically on cpu arrival/departure. diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index ef56d8a..97e7ce9 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -78,7 +78,7 @@ static inline void octeon_send_ipi_mask(const struct cpumask *mask, } /** - * Detect available CPUs, populate cpu_possible_map + * Detect available CPUs, populate cpu_possible_mask */ static void octeon_smp_hotplug_setup(void) { diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 00a0d2e..b71fae2 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -146,7 +146,7 @@ static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle) } /* - * Detect available CPUs, populate cpu_possible_map before smp_init + * Detect available CPUs, populate cpu_possible_mask before smp_init * * We don't want to start the secondary CPU yet nor do we have a nice probing * feature in PMON so we just assume presence of the secondary core. diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 63d2211..de88e22 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -138,7 +138,7 @@ static void __cpuinit bcm1480_boot_secondary(int cpu, struct task_struct *idle) /* * Use CFE to find out how many CPUs are available, setting up - * cpu_possible_map and the logical/physical mappings. + * cpu_possible_mask and the logical/physical mappings. * XXXKW will the boot CPU ever not be physical 0? * * Common setup before any secondaries are started diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 5124093..92a94f4 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -1100,7 +1100,7 @@ EXPORT_SYMBOL(hash_for_home_map); /* * cpu_cacheable_map lists all the cpus whose caches the hypervisor can - * flush on our behalf. It is set to cpu_possible_map OR'ed with + * flush on our behalf. It is set to cpu_possible_mask OR'ed with * hash_for_home_map, and it is what should be passed to * hv_flush_remote() to flush all caches. Note that if there are * dedicated hypervisor driver tiles that have authorized use of their diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index b132ade..4f51beb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -967,7 +967,7 @@ void xen_setup_shared_info(void) xen_setup_mfn_list_list(); } -/* This is called once we have the cpu_possible_map */ +/* This is called once we have the cpu_possible_mask */ void xen_setup_vcpu_info_placement(void) { int cpu; diff --git a/init/Kconfig b/init/Kconfig index 72f33fa..6cfd71d 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1414,8 +1414,8 @@ endif # MODULES config INIT_ALL_POSSIBLE bool help - Back when each arch used to define their own cpu_online_map and - cpu_possible_map, some of them chose to initialize cpu_possible_map + Back when each arch used to define their own cpu_online_mask and + cpu_possible_mask, some of them chose to initialize cpu_possible_mask with all 1s, and others with all 0s. When they were centralised, it was better to provide this option than to break all the archs and have several arch maintainers pursuing me down dark alleys. diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 1010cc6..eedeebe 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -270,11 +270,11 @@ static struct file_system_type cpuset_fs_type = { * are online. If none are online, walk up the cpuset hierarchy * until we find one that does have some online cpus. If we get * all the way to the top and still haven't found any online cpus, - * return cpu_online_map. Or if passed a NULL cs from an exit'ing - * task, return cpu_online_map. + * return cpu_online_mask. Or if passed a NULL cs from an exit'ing + * task, return cpu_online_mask. * * One way or another, we guarantee to return some non-empty subset - * of cpu_online_map. + * of cpu_online_mask. * * Call with callback_mutex held. */ @@ -867,7 +867,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, int retval; int is_load_balanced; - /* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */ + /* top_cpuset.cpus_allowed tracks cpu_online_mask; it's read-only */ if (cs == &top_cpuset) return -EACCES; @@ -2149,7 +2149,7 @@ void __init cpuset_init_smp(void) * * Description: Returns the cpumask_var_t cpus_allowed of the cpuset * attached to the specified @tsk. Guaranteed to return some non-empty - * subset of cpu_online_map, even if this means going outside the + * subset of cpu_online_mask, even if this means going outside the * tasks cpuset. **/ -- cgit v0.10.2 From 615399c84d1b8d8d8752629e5e5ab4e5044d6918 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 29 Mar 2012 15:38:31 +1030 Subject: cpumask: remove old cpu_*_map. These are obsolete: cpu_*_mask provides (const) pointers. Signed-off-by: Rusty Russell diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 1ffdb98..a2c819d 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -764,12 +764,6 @@ static inline const struct cpumask *get_cpu_mask(unsigned int cpu) * */ #ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS -/* These strip const, as traditionally they weren't const. */ -#define cpu_possible_map (*(cpumask_t *)cpu_possible_mask) -#define cpu_online_map (*(cpumask_t *)cpu_online_mask) -#define cpu_present_map (*(cpumask_t *)cpu_present_mask) -#define cpu_active_map (*(cpumask_t *)cpu_active_mask) - #define cpumask_of_cpu(cpu) (*get_cpu_mask(cpu)) #define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS) -- cgit v0.10.2 From e841a36abb0f95ea356d52e4386b8e8f762e9c40 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 29 Mar 2012 15:02:55 +0800 Subject: regulator: Fix setting low power mode for wm831x aldo Set BIT[8] of LDO7 ON Control mode for low power mode. R16507 (407Bh) LDO7 ON Control BIT[8] LDO7_ON_MODE: LDO7 ON Operating Mode 0 = Normal mode 1 = Low Power mode Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index f1e4ab0..641e9f6 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -506,22 +506,19 @@ static int wm831x_aldo_set_mode(struct regulator_dev *rdev, { struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); struct wm831x *wm831x = ldo->wm831x; - int ctrl_reg = ldo->base + WM831X_LDO_CONTROL; int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; int ret; switch (mode) { case REGULATOR_MODE_NORMAL: - ret = wm831x_set_bits(wm831x, on_reg, - WM831X_LDO7_ON_MODE, 0); + ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE, 0); if (ret < 0) return ret; break; case REGULATOR_MODE_IDLE: - ret = wm831x_set_bits(wm831x, ctrl_reg, - WM831X_LDO7_ON_MODE, + ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE, WM831X_LDO7_ON_MODE); if (ret < 0) return ret; -- cgit v0.10.2 From cee1a799eb044657922c4d63003d7bf71f8c8b8d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 29 Mar 2012 10:47:36 +0800 Subject: regulator: Only update [LDOx|DCx]_HIB_MODE bits in wm8350_[ldo|dcdc]_set_suspend_disable What we want is to disable output by setting [LDOx|DCx]_HIB_MODE bits. Current code also clears other bits in LDOx/DCDCx Low Power register. R202 (CAh) LDO1 Low Power BIT[13:12] LDO1 Hibernate behaviour: 00 = Select voltage image settings 01 = disable output 10 = reserved 11 = reserved R182 (B6h) DCDC1 Low Power BIT[14:12] DC-DC1 Hibernate behaviour: 000 = Use current settings (no change) 001 = Select voltage image settings 010 = Force standby mode 011 = Force standby mode and voltage image settings. 100 = Force LDO mode 101 = Force LDO mode and voltage image settings. 110 = Reserved. 111 = Disable output Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index c5f3b40..05ecfb8 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -535,25 +535,25 @@ static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev) val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER); wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER, - WM8350_DCDC_HIB_MODE_DIS); + val | WM8350_DCDC_HIB_MODE_DIS); break; case WM8350_DCDC_3: val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER); wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER, - WM8350_DCDC_HIB_MODE_DIS); + val | WM8350_DCDC_HIB_MODE_DIS); break; case WM8350_DCDC_4: val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER); wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER, - WM8350_DCDC_HIB_MODE_DIS); + val | WM8350_DCDC_HIB_MODE_DIS); break; case WM8350_DCDC_6: val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER); wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER, - WM8350_DCDC_HIB_MODE_DIS); + val | WM8350_DCDC_HIB_MODE_DIS); break; case WM8350_DCDC_2: case WM8350_DCDC_5: @@ -749,7 +749,7 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev) /* all LDOs have same mV bits */ val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK; - wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS); + wm8350_reg_write(wm8350, volt_reg, val | WM8350_LDO1_HIB_MODE_DIS); return 0; } -- cgit v0.10.2 From 15c08f664d8ca4f4d0e202cbd4034422a706ef80 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 29 Mar 2012 12:21:17 +0800 Subject: regulator: Fix comments in include/linux/regulator/machine.h Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 7abb160..b021084 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -71,7 +71,7 @@ struct regulator_state { * @uV_offset: Offset applied to voltages from consumer to compensate for * voltage drops. * - * @min_uA: Smallest consumers consumers may set. + * @min_uA: Smallest current consumers may set. * @max_uA: Largest current consumers may set. * * @valid_modes_mask: Mask of modes which may be configured by consumers. @@ -134,10 +134,8 @@ struct regulation_constraints { /** * struct regulator_consumer_supply - supply -> device mapping * - * This maps a supply name to a device. Only one of dev or dev_name - * can be specified. Use of dev_name allows support for buses which - * make struct device available late such as I2C and is the preferred - * form. + * This maps a supply name to a device. Use of dev_name allows support for + * buses which make struct device available late such as I2C. * * @dev_name: Result of dev_name() for the consumer. * @supply: Name for the supply. -- cgit v0.10.2 From 107f8bdac992356b3a80d41c9f6ff4399159aa81 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 28 Mar 2012 08:42:34 +0200 Subject: padata: Add a reference to the api documentation Add a reference to the padata api documentation at Documentation/padata.txt Suggested-by: Peter Zijlstra Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu diff --git a/kernel/padata.c b/kernel/padata.c index 6f10eb2..7875088 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -1,6 +1,8 @@ /* * padata.c - generic interface to process data streams in parallel * + * See Documentation/padata.txt for an api documentation. + * * Copyright (C) 2008, 2009 secunet Security Networks AG * Copyright (C) 2008, 2009 Steffen Klassert * -- cgit v0.10.2 From 13614e0fb1a8840c134be35c179ff23e23676304 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 28 Mar 2012 08:43:21 +0200 Subject: padata: Use the online cpumask as the default We use the active cpumask to determine the superset of cpus to use for parallelization. However, the active cpumask is for internal usage of the scheduler and therefore not the appropriate cpumask for these purposes. So use the online cpumask instead. Reported-by: Peter Zijlstra Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu diff --git a/kernel/padata.c b/kernel/padata.c index 7875088..de3d0d9 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -356,13 +356,13 @@ static int padata_setup_cpumasks(struct parallel_data *pd, if (!alloc_cpumask_var(&pd->cpumask.pcpu, GFP_KERNEL)) return -ENOMEM; - cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_active_mask); + cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_online_mask); if (!alloc_cpumask_var(&pd->cpumask.cbcpu, GFP_KERNEL)) { free_cpumask_var(pd->cpumask.cbcpu); return -ENOMEM; } - cpumask_and(pd->cpumask.cbcpu, cbcpumask, cpu_active_mask); + cpumask_and(pd->cpumask.cbcpu, cbcpumask, cpu_online_mask); return 0; } @@ -566,7 +566,7 @@ EXPORT_SYMBOL(padata_unregister_cpumask_notifier); static bool padata_validate_cpumask(struct padata_instance *pinst, const struct cpumask *cpumask) { - if (!cpumask_intersects(cpumask, cpu_active_mask)) { + if (!cpumask_intersects(cpumask, cpu_online_mask)) { pinst->flags |= PADATA_INVALID; return false; } @@ -680,7 +680,7 @@ static int __padata_add_cpu(struct padata_instance *pinst, int cpu) { struct parallel_data *pd; - if (cpumask_test_cpu(cpu, cpu_active_mask)) { + if (cpumask_test_cpu(cpu, cpu_online_mask)) { pd = padata_alloc_pd(pinst, pinst->cpumask.pcpu, pinst->cpumask.cbcpu); if (!pd) -- cgit v0.10.2 From 9612090527526a15832480c48b1f4b39e93e8a35 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 28 Mar 2012 08:44:07 +0200 Subject: padata: Fix cpu hotplug We don't remove the cpu that went offline from our cpumasks on cpu hotplug. This got lost somewhere along the line, so restore it. This fixes a hang of the padata instance on cpu hotplug. Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu diff --git a/kernel/padata.c b/kernel/padata.c index de3d0d9..89fe3d1 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -748,6 +748,9 @@ static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) return -ENOMEM; padata_replace(pinst, pd); + + cpumask_clear_cpu(cpu, pd->cpumask.cbcpu); + cpumask_clear_cpu(cpu, pd->cpumask.pcpu); } return 0; -- cgit v0.10.2 From fbf0ca1bf852fe224cec5400a69cd755ddc4ddcb Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 28 Mar 2012 08:51:03 +0200 Subject: crypto: pcrypt - Use the online cpumask as the default We use the active cpumask to determine the superset of cpus to use for parallelization. However, the active cpumask is for internal usage of the scheduler and therefore not the appropriate cpumask for these purposes. So use the online cpumask instead. Reported-by: Peter Zijlstra Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index 29a89da..b2c99dc 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -280,11 +280,11 @@ static int pcrypt_aead_init_tfm(struct crypto_tfm *tfm) ictx->tfm_count++; - cpu_index = ictx->tfm_count % cpumask_weight(cpu_active_mask); + cpu_index = ictx->tfm_count % cpumask_weight(cpu_online_mask); - ctx->cb_cpu = cpumask_first(cpu_active_mask); + ctx->cb_cpu = cpumask_first(cpu_online_mask); for (cpu = 0; cpu < cpu_index; cpu++) - ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_active_mask); + ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_online_mask); cipher = crypto_spawn_aead(crypto_instance_ctx(inst)); @@ -472,7 +472,7 @@ static int pcrypt_init_padata(struct padata_pcrypt *pcrypt, goto err_free_padata; } - cpumask_and(mask->mask, cpu_possible_mask, cpu_active_mask); + cpumask_and(mask->mask, cpu_possible_mask, cpu_online_mask); rcu_assign_pointer(pcrypt->cb_cpumask, mask); pcrypt->nblock.notifier_call = pcrypt_cpumask_change_notify; -- cgit v0.10.2 From 1e1229940045a537c61fb69f86010a8774e576d0 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Thu, 29 Mar 2012 09:03:47 +0200 Subject: crypto: user - Fix lookup of algorithms with IV generator We lookup algorithms with crypto_alg_mod_lookup() when instantiating via crypto_add_alg(). However, algorithms that are wrapped by an IV genearator (e.g. aead or genicv type algorithms) need special care. The userspace process hangs until it gets a timeout when we use crypto_alg_mod_lookup() to lookup these algorithms. So export the lookup functions for these algorithms and use them in crypto_add_alg(). Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index a0f768c..8d3a056 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -613,8 +613,7 @@ out: return err; } -static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, - u32 mask) +struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask) { struct crypto_alg *alg; @@ -652,6 +651,7 @@ static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, return ERR_PTR(crypto_givcipher_default(alg, type, mask)); } +EXPORT_SYMBOL_GPL(crypto_lookup_skcipher); int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, u32 type, u32 mask) diff --git a/crypto/aead.c b/crypto/aead.c index 04add3dc..e4cb351 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -470,8 +470,7 @@ out: return err; } -static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, - u32 mask) +struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask) { struct crypto_alg *alg; @@ -503,6 +502,7 @@ static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, return ERR_PTR(crypto_nivaead_default(alg, type, mask)); } +EXPORT_SYMBOL_GPL(crypto_lookup_aead); int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, u32 type, u32 mask) diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index f76e42b..e91c161 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -21,9 +21,13 @@ #include #include #include +#include #include #include #include +#include +#include + #include "internal.h" DEFINE_MUTEX(crypto_cfg_mutex); @@ -301,6 +305,60 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, return crypto_unregister_instance(alg); } +static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type, + u32 mask) +{ + int err; + struct crypto_alg *alg; + + type = crypto_skcipher_type(type); + mask = crypto_skcipher_mask(mask); + + for (;;) { + alg = crypto_lookup_skcipher(name, type, mask); + if (!IS_ERR(alg)) + return alg; + + err = PTR_ERR(alg); + if (err != -EAGAIN) + break; + if (signal_pending(current)) { + err = -EINTR; + break; + } + } + + return ERR_PTR(err); +} + +static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type, + u32 mask) +{ + int err; + struct crypto_alg *alg; + + type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); + type |= CRYPTO_ALG_TYPE_AEAD; + mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); + mask |= CRYPTO_ALG_TYPE_MASK; + + for (;;) { + alg = crypto_lookup_aead(name, type, mask); + if (!IS_ERR(alg)) + return alg; + + err = PTR_ERR(alg); + if (err != -EAGAIN) + break; + if (signal_pending(current)) { + err = -EINTR; + break; + } + } + + return ERR_PTR(err); +} + static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { @@ -325,7 +383,19 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh, else name = p->cru_name; - alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask); + switch (p->cru_type & p->cru_mask & CRYPTO_ALG_TYPE_MASK) { + case CRYPTO_ALG_TYPE_AEAD: + alg = crypto_user_aead_alg(name, p->cru_type, p->cru_mask); + break; + case CRYPTO_ALG_TYPE_GIVCIPHER: + case CRYPTO_ALG_TYPE_BLKCIPHER: + case CRYPTO_ALG_TYPE_ABLKCIPHER: + alg = crypto_user_skcipher_alg(name, p->cru_type, p->cru_mask); + break; + default: + alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask); + } + if (IS_ERR(alg)) return PTR_ERR(alg); diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h index d838c94..2eba340 100644 --- a/include/crypto/internal/aead.h +++ b/include/crypto/internal/aead.h @@ -31,6 +31,8 @@ static inline void crypto_set_aead_spawn( crypto_set_spawn(&spawn->base, inst); } +struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask); + int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, u32 type, u32 mask); diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index 3a748a6..06e8b32 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -34,6 +34,8 @@ static inline void crypto_set_skcipher_spawn( int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, u32 type, u32 mask); +struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask); + static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn) { crypto_drop_spawn(&spawn->base); -- cgit v0.10.2 From 5219a5342ab13650ae0f0c62319407268c48d0ab Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Thu, 29 Mar 2012 09:04:46 +0200 Subject: crypto: user - Fix size of netlink dump message The default netlink message size limit might be exceeded when dumping a lot of algorithms to userspace. As a result, not all of the instantiated algorithms dumped to userspace. So calculate an upper bound on the message size and call netlink_dump_start() with that value. Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index e91c161..f1ea0a0 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -457,12 +457,20 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) && (nlh->nlmsg_flags & NLM_F_DUMP))) { + struct crypto_alg *alg; + u16 dump_alloc = 0; + if (link->dump == NULL) return -EINVAL; + + list_for_each_entry(alg, &crypto_alg_list, cra_list) + dump_alloc += CRYPTO_REPORT_MAXSIZE; + { struct netlink_dump_control c = { .dump = link->dump, .done = link->done, + .min_dump_alloc = dump_alloc, }; return netlink_dump_start(crypto_nlsk, skb, nlh, &c); } diff --git a/include/linux/cryptouser.h b/include/linux/cryptouser.h index 532fb58..4abf2ea 100644 --- a/include/linux/cryptouser.h +++ b/include/linux/cryptouser.h @@ -100,3 +100,6 @@ struct crypto_report_rng { char type[CRYPTO_MAX_NAME]; unsigned int seedsize; }; + +#define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \ + sizeof(struct crypto_report_blkcipher)) -- cgit v0.10.2 From 9cb6abcb2645985a886f36459d480f5163c57623 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 19 Mar 2012 11:06:39 -0500 Subject: powerpc/8xxx: remove 85xx/86xx restrictions from fsl_guts.h Remove the check for CONFIG_PPC_85xx and CONFIG_PPC_86xx from fsl_guts.h. The check was originally intended to allow the same header file to be used on 85xx and 86xx systems, even though the Global Utilities register could be different. It turns out that they're not actually different, and so the check is not necessary. In addition, neither macro is defined for 64-bit e5500 kernels, so that causes a build break. Signed-off-by: Timur Tabi Acked-by: Mark Brown Signed-off-by: Kumar Gala diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h index ce04530..aa4c488 100644 --- a/arch/powerpc/include/asm/fsl_guts.h +++ b/arch/powerpc/include/asm/fsl_guts.h @@ -16,15 +16,6 @@ #define __ASM_POWERPC_FSL_GUTS_H__ #ifdef __KERNEL__ -/* - * These #ifdefs are safe because it's not possible to build a kernel that - * runs on e500 and e600 cores. - */ - -#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx) -#error Only 85xx and 86xx SOCs are supported -#endif - /** * Global Utility Registers. * @@ -36,11 +27,7 @@ * different names. In these cases, one name is chosen to avoid extraneous * #ifdefs. */ -#ifdef CONFIG_PPC_85xx -struct ccsr_guts_85xx { -#else -struct ccsr_guts_86xx { -#endif +struct ccsr_guts { __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ @@ -77,11 +64,8 @@ struct ccsr_guts_86xx { u8 res0a8[0xb0 - 0xa8]; __be32 rstcr; /* 0x.00b0 - Reset Control Register */ u8 res0b4[0xc0 - 0xb4]; -#ifdef CONFIG_PPC_85xx - __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register */ -#else - __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ -#endif + __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register + Called 'elbcvselcr' on 86xx SOCs */ u8 res0c4[0x224 - 0xc4]; __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ @@ -136,7 +120,7 @@ struct ccsr_guts_86xx { * ch: The channel on the DMA controller (0, 1, 2, or 3) * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) */ -static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts, +static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, unsigned int co, unsigned int ch, unsigned int device) { unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); @@ -172,7 +156,7 @@ static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts, * ch: The channel on the DMA controller (0, 1, 2, or 3) * value: the new value for the bit (0 or 1) */ -static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts, +static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, unsigned int co, unsigned int ch, unsigned int value) { if ((ch == 0) || (ch == 3)) { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index f33662b..e82f06f 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -271,7 +271,7 @@ static void __init mpc85xx_mds_qe_init(void) if (machine_is(p1021_mds)) { - struct ccsr_guts_85xx __iomem *guts; + struct ccsr_guts __iomem *guts; np = of_find_node_by_name(NULL, "global-utilities"); if (np) { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index db214cd..1a66c3d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -128,7 +128,7 @@ static void __init mpc85xx_rdb_setup_arch(void) #if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE) if (machine_is(p1025_rdb)) { - struct ccsr_guts_85xx __iomem *guts; + struct ccsr_guts __iomem *guts; np = of_find_node_by_name(NULL, "global-utilities"); if (np) { diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 0fe88e3..e74b7cd 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -150,7 +150,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) { struct device_node *guts_node; struct device_node *indirect_node = NULL; - struct ccsr_guts_85xx __iomem *guts; + struct ccsr_guts __iomem *guts; u8 __iomem *lbc_lcs0_ba = NULL; u8 __iomem *lbc_lcs1_ba = NULL; u8 b; @@ -269,7 +269,7 @@ exit: void p1022ds_set_pixel_clock(unsigned int pixclock) { struct device_node *guts_np = NULL; - struct ccsr_guts_85xx __iomem *guts; + struct ccsr_guts __iomem *guts; unsigned long freq; u64 temp; u32 pxclk; diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 13fa9a6..b8b1f33 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c @@ -226,7 +226,7 @@ void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port) void mpc8610hpcd_set_pixel_clock(unsigned int pixclock) { struct device_node *guts_np = NULL; - struct ccsr_guts_86xx __iomem *guts; + struct ccsr_guts __iomem *guts; unsigned long freq; u64 temp; u32 pxclk; diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index afbabf4..3fea5a1 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -58,9 +58,9 @@ static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card) { struct mpc8610_hpcd_data *machine_data = container_of(card, struct mpc8610_hpcd_data, card); - struct ccsr_guts_86xx __iomem *guts; + struct ccsr_guts __iomem *guts; - guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); + guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); if (!guts) { dev_err(card->dev, "could not map global utilities\n"); return -ENOMEM; @@ -142,9 +142,9 @@ static int mpc8610_hpcd_machine_remove(struct snd_soc_card *card) { struct mpc8610_hpcd_data *machine_data = container_of(card, struct mpc8610_hpcd_data, card); - struct ccsr_guts_86xx __iomem *guts; + struct ccsr_guts __iomem *guts; - guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); + guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); if (!guts) { dev_err(card->dev, "could not map global utilities\n"); return -ENOMEM; diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 4662340..982a1c9 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -46,7 +46,7 @@ * ch: The channel on the DMA controller (0, 1, 2, or 3) * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx) */ -static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts, +static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts, unsigned int co, unsigned int ch, unsigned int device) { unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); @@ -90,9 +90,9 @@ static int p1022_ds_machine_probe(struct snd_soc_card *card) { struct machine_data *mdata = container_of(card, struct machine_data, card); - struct ccsr_guts_85xx __iomem *guts; + struct ccsr_guts __iomem *guts; - guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx)); + guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); if (!guts) { dev_err(card->dev, "could not map global utilities\n"); return -ENOMEM; @@ -164,9 +164,9 @@ static int p1022_ds_machine_remove(struct snd_soc_card *card) { struct machine_data *mdata = container_of(card, struct machine_data, card); - struct ccsr_guts_85xx __iomem *guts; + struct ccsr_guts __iomem *guts; - guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx)); + guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); if (!guts) { dev_err(card->dev, "could not map global utilities\n"); return -ENOMEM; -- cgit v0.10.2 From 72ea4d48863679911330f977144b2b2bd62dd92a Mon Sep 17 00:00:00 2001 From: Jerry Huang Date: Tue, 20 Mar 2012 14:24:44 +0800 Subject: powerpc/85xx: add the P1020MBG-PC DTS support Signed-off-by: Jerry Huang Signed-off-by: Kumar Gala diff --git a/arch/powerpc/boot/dts/p1020mbg-pc.dtsi b/arch/powerpc/boot/dts/p1020mbg-pc.dtsi new file mode 100644 index 0000000..a24699c --- /dev/null +++ b/arch/powerpc/boot/dts/p1020mbg-pc.dtsi @@ -0,0 +1,151 @@ +/* + * P1020 MBG-PC Device Tree Source stub (no addresses or top-level ranges) + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +&lbc { + nor@0,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "cfi-flash"; + reg = <0x0 0x0 0x4000000>; + bank-width = <2>; + device-width = <1>; + + partition@0 { + /* 128KB for DTB Image */ + reg = <0x0 0x00020000>; + label = "NOR DTB Image"; + }; + + partition@20000 { + /* 3.875 MB for Linux Kernel Image */ + reg = <0x00020000 0x003e0000>; + label = "NOR Linux Kernel Image"; + }; + + partition@400000 { + /* 58MB for Root file System */ + reg = <0x00400000 0x03a00000>; + label = "NOR Root File System"; + }; + + partition@3e00000 { + /* This location must not be altered */ + /* 1M for Vitesse 7385 Switch firmware */ + reg = <0x3e00000 0x00100000>; + label = "NOR Vitesse-7385 Firmware"; + read-only; + }; + + partition@3f00000 { + /* This location must not be altered */ + /* 512KB for u-boot Bootloader Image */ + /* 512KB for u-boot Environment Variables */ + reg = <0x03f00000 0x00100000>; + label = "NOR U-Boot Image"; + read-only; + }; + }; + + L2switch@2,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "vitesse-7385"; + reg = <0x2 0x0 0x20000>; + }; +}; + +&soc { + i2c@3000 { + rtc@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + }; + }; + + mdio@24000 { + phy0: ethernet-phy@0 { + interrupts = <3 1 0 0>; + reg = <0x0>; + }; + phy1: ethernet-phy@1 { + interrupts = <2 1 0 0>; + reg = <0x1>; + }; + }; + + mdio@25000 { + tbi1: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + + mdio@26000 { + tbi2: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + + enet0: ethernet@b0000 { + fixed-link = <1 1 1000 0 0>; + phy-connection-type = "rgmii-id"; + }; + + enet1: ethernet@b1000 { + phy-handle = <&phy0>; + tbi-handle = <&tbi1>; + phy-connection-type = "sgmii"; + }; + + enet2: ethernet@b2000 { + phy-handle = <&phy1>; + phy-connection-type = "rgmii-id"; + }; + + usb@22000 { + phy_type = "ulpi"; + }; + + /* USB2 is shared with localbus, so it must be disabled + by default. We can't put 'status = "disabled";' here + since U-Boot doesn't clear the status property when + it enables USB2. OTOH, U-Boot does create a new node + when there isn't any. So, just comment it out. + */ + usb@23000 { + status = "disabled"; + phy_type = "ulpi"; + }; +}; diff --git a/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts b/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts new file mode 100644 index 0000000..ab8f076 --- /dev/null +++ b/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts @@ -0,0 +1,89 @@ +/* + * P1020 MBG-PC Device Tree Source (32-bit address map) + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/include/ "fsl/p1020si-pre.dtsi" +/ { + model = "fsl,P1020MBG-PC"; + compatible = "fsl,P1020MBG-PC"; + + memory { + device_type = "memory"; + }; + + lbc: localbus@ffe05000 { + reg = <0x0 0xffe05000 0x0 0x1000>; + + /* NOR and L2 switch */ + ranges = <0x0 0x0 0x0 0xec000000 0x04000000 + 0x1 0x0 0x0 0xffa00000 0x00040000 + 0x2 0x0 0x0 0xffb00000 0x00020000>; + }; + + soc: soc@ffe00000 { + ranges = <0x0 0x0 0xffe00000 0x100000>; + }; + + pci0: pcie@ffe09000 { + reg = <0x0 0xffe09000 0x0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0x0 0xa0000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0x0 0xffc10000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; + + pci1: pcie@ffe0a000 { + reg = <0x0 0xffe0a000 0x0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0x0 0x80000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; +}; + +/include/ "p1020mbg-pc.dtsi" +/include/ "fsl/p1020si-post.dtsi" diff --git a/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts b/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts new file mode 100644 index 0000000..9e9f401 --- /dev/null +++ b/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts @@ -0,0 +1,89 @@ +/* + * P1020 MBG-PC Device Tree Source (36-bit address map) + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/include/ "fsl/p1020si-pre.dtsi" +/ { + model = "fsl,P1020MBG-PC"; + compatible = "fsl,P1020MBG-PC"; + + memory { + device_type = "memory"; + }; + + lbc: localbus@fffe05000 { + reg = <0xf 0xffe05000 0x0 0x1000>; + + /* NOR and L2 switch */ + ranges = <0x0 0x0 0xf 0xec000000 0x04000000 + 0x1 0x0 0xf 0xffa00000 0x00040000 + 0x2 0x0 0xf 0xffb00000 0x00020000>; + }; + + soc: soc@fffe00000 { + ranges = <0x0 0xf 0xffe00000 0x100000>; + }; + + pci0: pcie@fffe09000 { + reg = <0xf 0xffe09000 0x0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; + + pci1: pcie@fffe0a000 { + reg = <0xf 0xffe0a000 0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; +}; + +/include/ "p1020mbg-pc.dtsi" +/include/ "fsl/p1020si-post.dtsi" -- cgit v0.10.2 From 2fc1fc0338d568723b32e2d7a79b644f6137fd00 Mon Sep 17 00:00:00 2001 From: Jerry Huang Date: Tue, 20 Mar 2012 14:24:45 +0800 Subject: powerpc/85xx: add the P1020UTM-PC DTS support Signed-off-by: Jerry Huang Signed-off-by: Kumar Gala diff --git a/arch/powerpc/boot/dts/p1020utm-pc.dtsi b/arch/powerpc/boot/dts/p1020utm-pc.dtsi new file mode 100644 index 0000000..7ea85ea --- /dev/null +++ b/arch/powerpc/boot/dts/p1020utm-pc.dtsi @@ -0,0 +1,140 @@ +/* + * P1020 UTM-PC Device Tree Source stub (no addresses or top-level ranges) + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +&lbc { + nor@0,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "cfi-flash"; + reg = <0x0 0x0 0x2000000>; + bank-width = <2>; + device-width = <1>; + + partition@0 { + /* 256KB for DTB Image */ + reg = <0x0 0x00040000>; + label = "NOR DTB Image"; + }; + + partition@40000 { + /* 3.75 MB for Linux Kernel Image */ + reg = <0x00040000 0x003c0000>; + label = "NOR Linux Kernel Image"; + }; + + partition@400000 { + /* 27MB for Root file System */ + reg = <0x00400000 0x01b00000>; + label = "NOR Root File System"; + }; + + partition@1f00000 { + /* This location must not be altered */ + /* 512KB for u-boot Bootloader Image */ + /* 512KB for u-boot Environment Variables */ + reg = <0x01f00000 0x00100000>; + label = "NOR U-Boot Image"; + read-only; + }; + }; +}; + +&soc { + i2c@3000 { + rtc@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + }; + }; + + mdio@24000 { + phy0: ethernet-phy@0 { + interrupts = <3 1 0 0>; + reg = <0x0>; + }; + phy1: ethernet-phy@1 { + interrupts = <2 1 0 0>; + reg = <0x1>; + }; + phy2: ethernet-phy@2 { + interrupts = <1 1 0 0>; + reg = <0x2>; + }; + }; + + mdio@25000 { + tbi1: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + + mdio@26000 { + tbi2: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + + enet0: ethernet@b0000 { + phy-handle = <&phy2>; + phy-connection-type = "rgmii-id"; + }; + + enet1: ethernet@b1000 { + phy-handle = <&phy0>; + tbi-handle = <&tbi1>; + phy-connection-type = "sgmii"; + }; + + enet2: ethernet@b2000 { + phy-handle = <&phy1>; + phy-connection-type = "rgmii-id"; + }; + + usb@22000 { + phy_type = "ulpi"; + }; + + /* USB2 is shared with localbus, so it must be disabled + by default. We can't put 'status = "disabled";' here + since U-Boot doesn't clear the status property when + it enables USB2. OTOH, U-Boot does create a new node + when there isn't any. So, just comment it out. + */ + usb@23000 { + status = "disabled"; + phy_type = "ulpi"; + }; +}; diff --git a/arch/powerpc/boot/dts/p1020utm-pc_32b.dts b/arch/powerpc/boot/dts/p1020utm-pc_32b.dts new file mode 100644 index 0000000..4bfdd89 --- /dev/null +++ b/arch/powerpc/boot/dts/p1020utm-pc_32b.dts @@ -0,0 +1,89 @@ +/* + * P1020 UTM-PC Device Tree Source (32-bit address map) + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/include/ "fsl/p1020si-pre.dtsi" +/ { + model = "fsl,P1020UTM-PC"; + compatible = "fsl,P1020UTM-PC"; + + memory { + device_type = "memory"; + }; + + lbc: localbus@ffe05000 { + reg = <0x0 0xffe05000 0x0 0x1000>; + + /* NOR */ + ranges = <0x0 0x0 0x0 0xec000000 0x02000000 + 0x1 0x0 0x0 0xffa00000 0x00040000 + 0x2 0x0 0x0 0xffb00000 0x00020000>; + }; + + soc: soc@ffe00000 { + ranges = <0x0 0x0 0xffe00000 0x100000>; + }; + + pci0: pcie@ffe09000 { + reg = <0x0 0xffe09000 0x0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0x0 0xa0000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0x0 0xffc10000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; + + pci1: pcie@ffe0a000 { + reg = <0x0 0xffe0a000 0x0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0x0 0x80000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; +}; + +/include/ "p1020utm-pc.dtsi" +/include/ "fsl/p1020si-post.dtsi" diff --git a/arch/powerpc/boot/dts/p1020utm-pc_36b.dts b/arch/powerpc/boot/dts/p1020utm-pc_36b.dts new file mode 100644 index 0000000..abec535 --- /dev/null +++ b/arch/powerpc/boot/dts/p1020utm-pc_36b.dts @@ -0,0 +1,89 @@ +/* + * P1020 UTM-PC Device Tree Source (36-bit address map) + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/include/ "fsl/p1020si-pre.dtsi" +/ { + model = "fsl,P1020UTM-PC"; + compatible = "fsl,P1020UTM-PC"; + + memory { + device_type = "memory"; + }; + + lbc: localbus@fffe05000 { + reg = <0xf 0xffe05000 0x0 0x1000>; + + /* NOR */ + ranges = <0x0 0x0 0xf 0xec000000 0x02000000 + 0x1 0x0 0xf 0xffa00000 0x00040000 + 0x2 0x0 0xf 0xffb00000 0x00020000>; + }; + + soc: soc@fffe00000 { + ranges = <0x0 0xf 0xffe00000 0x100000>; + }; + + pci0: pcie@fffe09000 { + reg = <0xf 0xffe09000 0x0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; + + pci1: pcie@fffe0a000 { + reg = <0xf 0xffe0a000 0 0x1000>; + ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000 + 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>; + pcie@0 { + ranges = <0x2000000 0x0 0xe0000000 + 0x2000000 0x0 0xe0000000 + 0x0 0x20000000 + + 0x1000000 0x0 0x0 + 0x1000000 0x0 0x0 + 0x0 0x100000>; + }; + }; +}; + +/include/ "p1020utm-pc.dtsi" +/include/ "fsl/p1020si-post.dtsi" -- cgit v0.10.2 From 2a78aeb1078994f6dab0173c2ecf5d9803ef0e8e Mon Sep 17 00:00:00 2001 From: Shaveta Leekha Date: Sat, 17 Mar 2012 14:28:56 +0530 Subject: powerpc/85xx: Enable I2C_CHARDEV and I2C_MPC options in defconfigs Enable I2C char dev interface for user space testing of I2C controler. Enable the I2C driver on 64-bit builds (corenet64_smp_defconfig) as it was missing. Signed-off-by: Shaveta Leekha Signed-off-by: Kumar Gala diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig index f8aef20..91db656 100644 --- a/arch/powerpc/configs/corenet32_smp_defconfig +++ b/arch/powerpc/configs/corenet32_smp_defconfig @@ -116,6 +116,7 @@ CONFIG_SERIAL_8250_RSA=y CONFIG_HW_RANDOM=y CONFIG_NVRAM=y CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y CONFIG_I2C_MPC=y CONFIG_SPI=y CONFIG_SPI_GPIO=y diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig index 7ed8d4c..8a42ebb 100644 --- a/arch/powerpc/configs/corenet64_smp_defconfig +++ b/arch/powerpc/configs/corenet64_smp_defconfig @@ -71,6 +71,8 @@ CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MPC=y # CONFIG_HWMON is not set CONFIG_VIDEO_OUTPUT_CONTROL=y # CONFIG_HID_SUPPORT is not set diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index 5fb0c8a..a068ead 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig @@ -117,6 +117,7 @@ CONFIG_SERIAL_8250_RSA=y CONFIG_SERIAL_QE=m CONFIG_NVRAM=y CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y CONFIG_I2C_CPM=m CONFIG_I2C_MPC=y CONFIG_SPI=y diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index fb51bc9..6270dd0 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig @@ -119,6 +119,7 @@ CONFIG_SERIAL_8250_RSA=y CONFIG_SERIAL_QE=m CONFIG_NVRAM=y CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y CONFIG_I2C_CPM=m CONFIG_I2C_MPC=y CONFIG_SPI=y -- cgit v0.10.2 From 3b588c7efc84f15548afdda6a0d2f892fe83babc Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 15 Mar 2012 17:41:02 -0500 Subject: powerpc/epapr: add "memory" as a clobber to all hypercalls The "memory" clobber tells the compiler to ensure that all writes to memory are committed before the hypercall is made. "memory" is only necessary for hcalls where the Hypervisor will read or write guest memory. However, we add it to all hcalls because the impact is minimal, and we want to ensure that it's present for the hcalls that need it. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h index f3b0c2c..976835d 100644 --- a/arch/powerpc/include/asm/epapr_hcalls.h +++ b/arch/powerpc/include/asm/epapr_hcalls.h @@ -134,10 +134,15 @@ * whether they will be clobbered. * * Note that r11 can be used as an output parameter. + * + * The "memory" clobber is only necessary for hcalls where the Hypervisor + * will read or write guest memory. However, we add it to all hcalls because + * the impact is minimal, and we want to ensure that it's present for the + * hcalls that need it. */ /* List of common clobbered registers. Do not use this macro. */ -#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc" +#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory" #define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS #define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10" -- cgit v0.10.2 From 8a57d734004b8018f3d320455c1816b1e6810265 Mon Sep 17 00:00:00 2001 From: Diana CRACIUN Date: Thu, 9 Feb 2012 15:41:00 +0200 Subject: powerpc/dts: Removed fsl,msi property from dts. The association in the decice tree between PCI and MSI using fsl,msi property was an artificial one and it does not reflect the actual hardware. Signed-off-by: Diana CRACIUN Signed-off-by: Kumar Gala diff --git a/arch/powerpc/boot/dts/p2041rdb.dts b/arch/powerpc/boot/dts/p2041rdb.dts index 4f957db..2852139 100644 --- a/arch/powerpc/boot/dts/p2041rdb.dts +++ b/arch/powerpc/boot/dts/p2041rdb.dts @@ -135,7 +135,6 @@ reg = <0xf 0xfe200000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; - fsl,msi = <&msi0>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -151,7 +150,6 @@ reg = <0xf 0xfe201000 0 0x1000>; ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; - fsl,msi = <&msi1>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -167,7 +165,6 @@ reg = <0xf 0xfe202000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; - fsl,msi = <&msi2>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 diff --git a/arch/powerpc/boot/dts/p3041ds.dts b/arch/powerpc/boot/dts/p3041ds.dts index f469145..22a215e 100644 --- a/arch/powerpc/boot/dts/p3041ds.dts +++ b/arch/powerpc/boot/dts/p3041ds.dts @@ -173,7 +173,6 @@ reg = <0xf 0xfe200000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; - fsl,msi = <&msi0>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -189,7 +188,6 @@ reg = <0xf 0xfe201000 0 0x1000>; ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; - fsl,msi = <&msi1>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -205,7 +203,6 @@ reg = <0xf 0xfe202000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; - fsl,msi = <&msi2>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -221,7 +218,6 @@ reg = <0xf 0xfe203000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; - fsl,msi = <&msi2>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 diff --git a/arch/powerpc/boot/dts/p3060qds.dts b/arch/powerpc/boot/dts/p3060qds.dts index 529042e..9ae875c 100644 --- a/arch/powerpc/boot/dts/p3060qds.dts +++ b/arch/powerpc/boot/dts/p3060qds.dts @@ -212,7 +212,6 @@ reg = <0xf 0xfe200000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; - fsl,msi = <&msi0>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -228,7 +227,6 @@ reg = <0xf 0xfe201000 0 0x1000>; ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; - fsl,msi = <&msi1>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts index 6d60e54..3e20460 100644 --- a/arch/powerpc/boot/dts/p4080ds.dts +++ b/arch/powerpc/boot/dts/p4080ds.dts @@ -141,7 +141,6 @@ reg = <0xf 0xfe200000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; - fsl,msi = <&msi0>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -157,7 +156,6 @@ reg = <0xf 0xfe201000 0 0x1000>; ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; - fsl,msi = <&msi1>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -173,7 +171,6 @@ reg = <0xf 0xfe202000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; - fsl,msi = <&msi2>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 diff --git a/arch/powerpc/boot/dts/p5020ds.dts b/arch/powerpc/boot/dts/p5020ds.dts index 1c25068..27c07ed 100644 --- a/arch/powerpc/boot/dts/p5020ds.dts +++ b/arch/powerpc/boot/dts/p5020ds.dts @@ -173,7 +173,6 @@ reg = <0xf 0xfe200000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; - fsl,msi = <&msi0>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -189,7 +188,6 @@ reg = <0xf 0xfe201000 0 0x1000>; ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; - fsl,msi = <&msi1>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -205,7 +203,6 @@ reg = <0xf 0xfe202000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; - fsl,msi = <&msi2>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 @@ -221,7 +218,6 @@ reg = <0xf 0xfe203000 0 0x1000>; ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; - fsl,msi = <&msi2>; pcie@0 { ranges = <0x02000000 0 0xe0000000 0x02000000 0 0xe0000000 -- cgit v0.10.2 From fa1b42b45a9c96da77f3ddabf715f49525a87209 Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Tue, 12 Jan 2010 00:04:03 +0000 Subject: powerpc/qe: Update the SNUM table for MPC8569 Rev2.0 The MPC8569 Rev2.0 has the correct SNUM table as QE Reference Manual, we must follow it. However the Rev1.0 silicon need the old SNUM table as workaround due to Rev1.0 silicon SNUM erratum. So, we support both snum table, and choose the one FDT tell us. And u-boot will fixup FDT according to SPRN_SVR. Signed-off-by: Liu Yu Signed-off-by: Dave Liu Signed-off-by: Kumar Gala diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index ceb09cb..818e763 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved. + * Copyright (C) 2006-2010 Freescale Semicondutor, Inc. All rights reserved. * * Authors: Shlomi Gridish * Li Yang @@ -266,7 +266,19 @@ EXPORT_SYMBOL(qe_clock_source); static void qe_snums_init(void) { int i; - static const u8 snum_init[] = { + static const u8 snum_init_76[] = { + 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, + 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89, + 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9, + 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D, + 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D, + 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D, + 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD, + 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD, + 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED, + 0xF4, 0xF5, 0xFC, 0xFD, + }; + static const u8 snum_init_46[] = { 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89, 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9, @@ -274,9 +286,15 @@ static void qe_snums_init(void) 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59, 0x68, 0x69, 0x78, 0x79, 0x80, 0x81, }; + static const u8 *snum_init; qe_num_of_snum = qe_get_num_of_snums(); + if (qe_num_of_snum == 76) + snum_init = snum_init_76; + else + snum_init = snum_init_46; + for (i = 0; i < qe_num_of_snum; i++) { snums[i].num = snum_init[i]; snums[i].state = QE_SNUM_STATE_FREE; diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 4e3cd2f..17a46e7 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -3945,6 +3945,8 @@ static int ucc_geth_probe(struct platform_device* ofdev) } if (max_speed == SPEED_1000) { + unsigned int snums = qe_get_num_of_snums(); + /* configure muram FIFOs for gigabit operation */ ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT; ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT; @@ -3954,11 +3956,11 @@ static int ucc_geth_probe(struct platform_device* ofdev) ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT; ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4; - /* If QE's snum number is 46 which means we need to support + /* If QE's snum number is 46/76 which means we need to support * 4 UECs at 1000Base-T simultaneously, we need to allocate * more Threads to Rx. */ - if (qe_get_num_of_snums() == 46) + if ((snums == 76) || (snums == 46)) ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6; else ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4; -- cgit v0.10.2 From 4a206ffc0bfe8e8c3fc0468a052f5b0bb625a57b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 27 Mar 2012 14:41:04 +1000 Subject: drm/nouveau: oops, create m2mf for nvd9 too Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index a4886b3..c2a8511 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -642,7 +642,7 @@ nouveau_card_channel_init(struct drm_device *dev) OUT_RING (chan, chan->vram_handle); OUT_RING (chan, chan->gart_handle); } else - if (dev_priv->card_type <= NV_C0) { + if (dev_priv->card_type <= NV_D0) { ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039); if (ret) goto error; -- cgit v0.10.2 From acde2d8037f4502669af251e44b05579681e0dc1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 29 Mar 2012 20:21:32 +1000 Subject: Revert "drm/nouveau: inform userspace of new kernel subchannel requirements" This reverts commit a81f15499887d3f9f24ec70bb9b7e778942a6b7b. Gah, we have a released userspace component using fixed subc assignment that conflicts with this. To avoid breaking ABI this needs to be reverted. Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 44e6416..337e228 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -436,11 +436,18 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, } if (dev_priv->card_type < NV_C0) { - init->subchan[0].handle = NvSw; - init->subchan[0].grclass = NV_SW; - init->nr_subchan = 1; + init->subchan[0].handle = NvM2MF; + if (dev_priv->card_type < NV_50) + init->subchan[0].grclass = 0x0039; + else + init->subchan[0].grclass = 0x5039; + init->subchan[1].handle = NvSw; + init->subchan[1].grclass = NV_SW; + init->nr_subchan = 2; } else { - init->nr_subchan = 0; + init->subchan[0].handle = 0x9039; + init->subchan[0].grclass = 0x9039; + init->nr_subchan = 1; } /* Named memory object area */ diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index bcf0fd9..23d4edf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -48,8 +48,8 @@ void nv50_dma_push(struct nouveau_channel *, struct nouveau_bo *, /* Hardcoded object assignments to subchannels (subchannel id). */ enum { - NvSubSw = 0, - NvSubM2MF = 1, + NvSubM2MF = 0, + NvSubSw = 1, NvSub2D = 2, NvSubCtxSurf2D = 2, NvSubGdiRect = 3, -- cgit v0.10.2 From 02bfc2881e0d5b23147211bb6420798d946a7b5c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 29 Mar 2012 20:24:34 +1000 Subject: drm/nouveau: inform userspace of relaxed kernel subchannel requirements Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 337e228..846afb0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -436,18 +436,11 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, } if (dev_priv->card_type < NV_C0) { - init->subchan[0].handle = NvM2MF; - if (dev_priv->card_type < NV_50) - init->subchan[0].grclass = 0x0039; - else - init->subchan[0].grclass = 0x5039; + init->subchan[0].handle = 0x00000000; + init->subchan[0].grclass = 0x0000; init->subchan[1].handle = NvSw; init->subchan[1].grclass = NV_SW; init->nr_subchan = 2; - } else { - init->subchan[0].handle = 0x9039; - init->subchan[0].grclass = 0x9039; - init->nr_subchan = 1; } /* Named memory object area */ -- cgit v0.10.2 From 99dd5497e5be4fe4194cad181d45fd6569a930db Mon Sep 17 00:00:00 2001 From: "Liu, Chuansheng" Date: Mon, 26 Mar 2012 07:11:50 +0000 Subject: x86: Preserve lazy irq disable semantics in fixup_irqs() The default irq_disable() sematics are to mark the interrupt disabled, but keep it unmasked. If the interrupt is delivered while marked disabled, the low level interrupt handler masks it and marks it pending. This is important for detecting wakeup interrupts during suspend and for edge type interrupts to avoid losing interrupts. fixup_irqs() moves the interrupts away from an offlined cpu. For certain interrupt types it needs to mask the interrupt line before changing the affinity. After affinity has changed the interrupt line is unmasked again, but only if it is not marked disabled. This breaks the lazy irq disable semantics and causes problems in suspend as the interrupt can be lost or wakeup functionality is broken. Check irqd_irq_masked() instead of irqd_irq_disabled() because irqd_irq_masked() is only set, when the core code actually masked the interrupt line. If it's not set, we unmask the interrupt and let the lazy irq disable logic deal with an eventually incoming interrupt. [ tglx: Massaged changelog and added a comment ] Signed-off-by: liu chuansheng Cc: Yanmin Zhang Link: http://lkml.kernel.org/r/27240C0AC20F114CBF8149A2696CBE4A05DFB3@SHSMSX101.ccr.corp.intel.com Signed-off-by: Thomas Gleixner diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 7943e0c..3dafc60 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -282,8 +282,13 @@ void fixup_irqs(void) else if (!(warned++)) set_affinity = 0; + /* + * We unmask if the irq was not marked masked by the + * core code. That respects the lazy irq disable + * behaviour. + */ if (!irqd_can_move_in_process_context(data) && - !irqd_irq_disabled(data) && chip->irq_unmask) + !irqd_irq_masked(data) && chip->irq_unmask) chip->irq_unmask(data); raw_spin_unlock(&desc->lock); -- cgit v0.10.2 From e032b376551a61662b20a2c8544fbbc568ab2e7f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 28 Mar 2012 21:17:55 +0100 Subject: regulator: Fix deadlock on removal of regulators with supplies If a regulator with a supply is being unregistered we will call regulator_put() to release the supply with the regulator_list_mutex held but this deadlocks as regulator_put() takes the same lock. Fix this by releasing the supply before we take the mutex in regulator_unregister(). Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e2f3afa..4a5054e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2992,14 +2992,14 @@ void regulator_unregister(struct regulator_dev *rdev) if (rdev == NULL) return; + if (rdev->supply) + regulator_put(rdev->supply); mutex_lock(®ulator_list_mutex); debugfs_remove_recursive(rdev->debugfs); flush_work_sync(&rdev->disable_work.work); WARN_ON(rdev->open_count); unset_regulator_supplies(rdev); list_del(&rdev->list); - if (rdev->supply) - regulator_put(rdev->supply); kfree(rdev->constraints); device_unregister(&rdev->dev); mutex_unlock(®ulator_list_mutex); -- cgit v0.10.2 From 7d26bb103c4162003bfdf1d63aaa32b548ad0e9a Mon Sep 17 00:00:00 2001 From: Weiping Pan Date: Tue, 27 Mar 2012 19:18:24 +0000 Subject: bonding: emit event when bonding changes MAC When a bonding device is configured with fail_over_mac=active, we expect to see the MAC address of the new active slave as the source MAC address after failover. But we see that the source MAC address is the MAC address of previous active slave. Emit NETDEV_CHANGEADDR event when bonding changes its MAC address, in order to let arp_netdev_event flush neighbour cache and route cache. How to reproduce this bug ? -----------hostB---------------- hostA ----- switch ---|-- eth0--bond0(192.168.100.2/24)| (192.168.100.1/24 \--|-- eth1-/ | -------------------------------- 1 on hostB, modprobe bonding mode=1 miimon=500 fail_over_mac=active downdelay=1000 num_grat_arp=1 ifconfig bond0 192.168.100.2/24 up ifenslave bond0 eth0 ifenslave bond0 eth1 then eth0 is the active slave, and MAC of bond0 is MAC of eth0. 2 on hostA, ping 192.168.100.2 3 on hostB, tcpdump -i bond0 -p icmp -XXX you will see bond0 uses MAC of eth0 as source MAC in icmp reply. 4 on hostB, ifconfig eth0 down tcpdump -i bond0 -p icmp -XXX (just keep it running in step 3) you will see first bond0 uses MAC of eth1 as source MAC in icmp reply, then it will use MAC of eth0 as source MAC. Signed-off-by: Weiping Pan Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b920d82..a20b585 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -892,9 +892,15 @@ static void bond_do_fail_over_mac(struct bonding *bond, switch (bond->params.fail_over_mac) { case BOND_FOM_ACTIVE: - if (new_active) + if (new_active) { memcpy(bond->dev->dev_addr, new_active->dev->dev_addr, new_active->dev->addr_len); + write_unlock_bh(&bond->curr_slave_lock); + read_unlock(&bond->lock); + call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); + read_lock(&bond->lock); + write_lock_bh(&bond->curr_slave_lock); + } break; case BOND_FOM_FOLLOW: /* -- cgit v0.10.2 From 1d24fb3684f347226747c6b11ea426b7b992694e Mon Sep 17 00:00:00 2001 From: "zhuangfeiran@ict.ac.cn" Date: Wed, 28 Mar 2012 23:27:00 +0000 Subject: x86 bpf_jit: fix a bug in emitting the 16-bit immediate operand of AND When K >= 0xFFFF0000, AND needs the two least significant bytes of K as its operand, but EMIT2() gives it the least significant byte of K and 0x2. EMIT() should be used here to replace EMIT2(). Signed-off-by: Feiran Zhuang Acked-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 5671752..5a5b6e4 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -289,7 +289,7 @@ void bpf_jit_compile(struct sk_filter *fp) EMIT2(0x24, K & 0xFF); /* and imm8,%al */ } else if (K >= 0xFFFF0000) { EMIT2(0x66, 0x25); /* and imm16,%ax */ - EMIT2(K, 2); + EMIT(K, 2); } else { EMIT1_off32(0x25, K); /* and imm32,%eax */ } -- cgit v0.10.2 From 78724b8ef83fc2bcfbc0a72a7ad8a3ce5ad25e6a Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 29 Mar 2012 06:17:17 -0500 Subject: kdb: Fix smatch warning on dbg_io_ops->is_console The Smatch tool warned that the change from commit b8adde8dd (kdb: Avoid using dbg_io_ops until it is initialized) should add another null check later in the kdb_printf(). It is worth noting that the second use of dbg_io_ops->is_console is protected by the KDB_PAGER state variable which would only get set when kdb is fully active and initialized. If we ever encounter changes or defects in the KDB_PAGER state we do not want to crash the kernel in a kdb_printf/printk. CC: Tim Bird Reported-by: Dan Carpenter Signed-off-by: Jason Wessel diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 9b5f17d..bb9520f 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -743,7 +743,7 @@ kdb_printit: kdb_input_flush(); c = console_drivers; - if (!dbg_io_ops->is_console) { + if (dbg_io_ops && !dbg_io_ops->is_console) { len = strlen(moreprompt); cp = moreprompt; while (len--) { -- cgit v0.10.2 From 456ca7ff24841bf2d2a2dfd690fe7d42ef70d932 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 29 Mar 2012 06:55:44 -0500 Subject: kgdbts: Fix kernel oops with CONFIG_DEBUG_RODATA On x86 the kgdb test suite will oops when the kernel is compiled with CONFIG_DEBUG_RODATA and you run the tests after boot time. This is regression has existed since 2.6.26 by commit: b33cb815 (kgdbts: Use HW breakpoints with CONFIG_DEBUG_RODATA). The test suite can use hw breakpoints for all the tests, but it has to execute the hardware breakpoint specific tests first in order to determine that the hw breakpoints actually work. Specifically the very first test causes an oops: # echo V1I1 > /sys/module/kgdbts/parameters/kgdbts kgdb: Registered I/O driver kgdbts. kgdbts:RUN plant and detach test Entering kdb (current=0xffff880017aa9320, pid 1078) on processor 0 due to Keyboard Entry [0]kdb> kgdbts: ERROR PUT: end of test buffer on 'plant_and_detach_test' line 1 expected OK got $E14#aa WARNING: at drivers/misc/kgdbts.c:730 run_simple_test+0x151/0x2c0() [...oops clipped...] This commit re-orders the running of the tests and puts the RODATA check into its own function so as to correctly avoid the kernel oops by detecting and using the hw breakpoints. Cc: # >= 2.6.26 Signed-off-by: Jason Wessel diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 3f7ad83..997e94d 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -885,6 +885,22 @@ static void run_singlestep_break_test(void) kgdbts_break_test(); } +static void test_debug_rodata(void) +{ +#ifdef CONFIG_DEBUG_RODATA + /* Until there is an api to write to read-only text segments, use + * HW breakpoints for the remainder of any tests, else print a + * failure message if hw breakpoints do not work. + */ + if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { + eprintk("kgdbts: HW breakpoints BROKEN, ending tests\n"); + return; + } + force_hwbrks = 1; + v1printk("kgdbts:Using HW breakpoints for SW breakpoint tests\n"); +#endif /* CONFIG_DEBUG_RODATA */ +} + static void kgdbts_run_tests(void) { char *ptr; @@ -907,6 +923,18 @@ static void kgdbts_run_tests(void) if (ptr) sstep_test = simple_strtol(ptr+1, NULL, 10); + /* All HW break point tests */ + if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { + hwbreaks_ok = 1; + v1printk("kgdbts:RUN hw breakpoint test\n"); + run_breakpoint_test(1); + v1printk("kgdbts:RUN hw write breakpoint test\n"); + run_hw_break_test(1); + v1printk("kgdbts:RUN access write breakpoint test\n"); + run_hw_break_test(0); + } + test_debug_rodata(); + /* required internal KGDB tests */ v1printk("kgdbts:RUN plant and detach test\n"); run_plant_and_detach_test(0); @@ -924,35 +952,11 @@ static void kgdbts_run_tests(void) /* ===Optional tests=== */ - /* All HW break point tests */ - if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) { - hwbreaks_ok = 1; - v1printk("kgdbts:RUN hw breakpoint test\n"); - run_breakpoint_test(1); - v1printk("kgdbts:RUN hw write breakpoint test\n"); - run_hw_break_test(1); - v1printk("kgdbts:RUN access write breakpoint test\n"); - run_hw_break_test(0); - } - if (nmi_sleep) { v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep); run_nmi_sleep_test(nmi_sleep); } -#ifdef CONFIG_DEBUG_RODATA - /* Until there is an api to write to read-only text segments, use - * HW breakpoints for the remainder of any tests, else print a - * failure message if hw breakpoints do not work. - */ - if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { - eprintk("kgdbts: HW breakpoints do not work," - "skipping remaining tests\n"); - return; - } - force_hwbrks = 1; -#endif /* CONFIG_DEBUG_RODATA */ - /* If the do_fork test is run it will be the last test that is * executed because a kernel thread will be spawned at the very * end to unregister the debug hooks. -- cgit v0.10.2 From 486c5987a00a89d56c2c04c506417ef8f823ca2e Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 29 Mar 2012 17:41:24 -0500 Subject: kgdbts: (1 of 2) fix single step awareness to work correctly with SMP The do_fork and sys_open tests have never worked properly on anything other than a UP configuration with the kgdb test suite. This is because the test suite did not fully implement the behavior of a real debugger. A real debugger tracks the state of what thread it asked to single step and can correctly continue other threads of execution or conditionally stop while waiting for the original thread single step request to return. Below is a simple method to cause a fatal kernel oops with the kgdb test suite on a 4 processor x86 system: while [ 1 ] ; do ls > /dev/null 2> /dev/null; done& while [ 1 ] ; do ls > /dev/null 2> /dev/null; done& while [ 1 ] ; do ls > /dev/null 2> /dev/null; done& while [ 1 ] ; do ls > /dev/null 2> /dev/null; done& echo V1I1F1000 > /sys/module/kgdbts/parameters/kgdbts Very soon after starting the test the kernel will oops with a message like: kgdbts: BP mismatch 3b7da66480 expected ffffffff8106a590 WARNING: at drivers/misc/kgdbts.c:303 check_and_rewind_pc+0xe0/0x100() Call Trace: [] check_and_rewind_pc+0xe0/0x100 [] validate_simple_test+0x25/0xc0 [] run_simple_test+0x107/0x2c0 [] kgdbts_put_char+0x18/0x20 The warn will turn to a hard kernel crash shortly after that because the pc will not get properly rewound to the right value after hitting a breakpoint leading to a hard lockup. This change is broken up into 2 pieces because archs that have hw single stepping (2.6.26 and up) need different changes than archs that do not have hw single stepping (3.0 and up). This change implements the correct behavior for an arch that supports hw single stepping. A minor defect was fixed where sys_open should be do_sys_open for the sys_open break point test. This solves the problem of running a 64 bit with a 32 bit user space. The sys_open() never gets called when using the 32 bit file system for the kgdb testsuite because the 32 bit binaries invoke the compat_sys_open() call leading to the test never completing. In order to mimic a real debugger, the kgdb test suite now tracks the most recent thread that was continued (cont_thread_id), with the intent to single step just this thread. When the response to the single step request stops in a different thread that hit the original break point that thread will now get continued, while the debugger waits for the thread with the single step pending. Here is a high level description of the sequence of events. cont_instead_of_sstep = 0; 1) set breakpoint at do_fork 2) continue 3) Save the thread id where we stop to cont_thread_id 4) Remove breakpoint at do_fork 5) Reset the PC if needed depending on kernel exception type 6) if (cont_instead_of_sstep) { continue } else { single step } 7) Check where we stopped if current thread != cont_thread_id { cont_instead_of_sstep = 1; goto step 5 } else { cont_instead_of_sstep = 0; } 8) clean up and run test again if needed Cc: stable@vger.kernel.org # >= 2.6.26 Signed-off-by: Jason Wessel diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 997e94d..3cad9fc 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -134,6 +134,9 @@ static int force_hwbrks; static int hwbreaks_ok; static int hw_break_val; static int hw_break_val2; +static int cont_instead_of_sstep; +static unsigned long cont_thread_id; +static unsigned long sstep_thread_id; #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC) static int arch_needs_sstep_emulation = 1; #else @@ -211,7 +214,7 @@ static unsigned long lookup_addr(char *arg) if (!strcmp(arg, "kgdbts_break_test")) addr = (unsigned long)kgdbts_break_test; else if (!strcmp(arg, "sys_open")) - addr = (unsigned long)sys_open; + addr = (unsigned long)do_sys_open; else if (!strcmp(arg, "do_fork")) addr = (unsigned long)do_fork; else if (!strcmp(arg, "hw_break_val")) @@ -283,6 +286,16 @@ static void hw_break_val_write(void) hw_break_val++; } +static int get_thread_id_continue(char *put_str, char *arg) +{ + char *ptr = &put_str[11]; + + if (put_str[1] != 'T' || put_str[2] != '0') + return 1; + kgdb_hex2long(&ptr, &cont_thread_id); + return 0; +} + static int check_and_rewind_pc(char *put_str, char *arg) { unsigned long addr = lookup_addr(arg); @@ -324,6 +337,18 @@ static int check_single_step(char *put_str, char *arg) gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs); v2printk("Singlestep stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs)); + + if (sstep_thread_id != cont_thread_id && !arch_needs_sstep_emulation) { + /* + * Ensure we stopped in the same thread id as before, else the + * debugger should continue until the original thread that was + * single stepped is scheduled again, emulating gdb's behavior. + */ + v2printk("ThrID does not match: %lx\n", cont_thread_id); + cont_instead_of_sstep = 1; + ts.idx -= 4; + return 0; + } if (instruction_pointer(&kgdbts_regs) == addr) { eprintk("kgdbts: SingleStep failed at %lx\n", instruction_pointer(&kgdbts_regs)); @@ -368,7 +393,12 @@ static int got_break(char *put_str, char *arg) static void emul_sstep_get(char *arg) { if (!arch_needs_sstep_emulation) { - fill_get_buf(arg); + if (cont_instead_of_sstep) { + cont_instead_of_sstep = 0; + fill_get_buf("c"); + } else { + fill_get_buf(arg); + } return; } switch (sstep_state) { @@ -398,9 +428,11 @@ static void emul_sstep_get(char *arg) static int emul_sstep_put(char *put_str, char *arg) { if (!arch_needs_sstep_emulation) { - if (!strncmp(put_str+1, arg, 2)) - return 0; - return 1; + char *ptr = &put_str[11]; + if (put_str[1] != 'T' || put_str[2] != '0') + return 1; + kgdb_hex2long(&ptr, &sstep_thread_id); + return 0; } switch (sstep_state) { case 1: @@ -502,10 +534,10 @@ static struct test_struct bad_read_test[] = { static struct test_struct singlestep_break_test[] = { { "?", "S0*" }, /* Clear break points */ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ - { "c", "T0*", }, /* Continue */ + { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ + { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */ { "g", "kgdbts_break_test", NULL, check_and_rewind_pc }, { "write", "OK", write_regs }, /* Write registers */ - { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "g", "kgdbts_break_test", NULL, check_single_step }, { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */ @@ -523,10 +555,10 @@ static struct test_struct singlestep_break_test[] = { static struct test_struct do_fork_test[] = { { "?", "S0*" }, /* Clear break points */ { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ - { "c", "T0*", }, /* Continue */ + { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ + { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */ { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */ { "write", "OK", write_regs }, /* Write registers */ - { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "g", "do_fork", NULL, check_single_step }, { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ @@ -541,10 +573,10 @@ static struct test_struct do_fork_test[] = { static struct test_struct sys_open_test[] = { { "?", "S0*" }, /* Clear break points */ { "sys_open", "OK", sw_break, }, /* set sw breakpoint */ - { "c", "T0*", }, /* Continue */ + { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ + { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */ { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */ { "write", "OK", write_regs }, /* Write registers */ - { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "g", "sys_open", NULL, check_single_step }, { "sys_open", "OK", sw_break, }, /* set sw breakpoint */ -- cgit v0.10.2 From 23bbd8e346f1ef3fc1219c79cea53d8d52b207d8 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 29 Mar 2012 17:41:24 -0500 Subject: kgdbts: (2 of 2) fix single step awareness to work correctly with SMP The do_fork and sys_open tests have never worked properly on anything other than a UP configuration with the kgdb test suite. This is because the test suite did not fully implement the behavior of a real debugger. A real debugger tracks the state of what thread it asked to single step and can correctly continue other threads of execution or conditionally stop while waiting for the original thread single step request to return. Below is a simple method to cause a fatal kernel oops with the kgdb test suite on a 2 processor ARM system: while [ 1 ] ; do ls > /dev/null 2> /dev/null; done& while [ 1 ] ; do ls > /dev/null 2> /dev/null; done& echo V1I1F100 > /sys/module/kgdbts/parameters/kgdbts Very soon after starting the test the kernel will start warning with messages like: kgdbts: BP mismatch c002487c expected c0024878 ------------[ cut here ]------------ WARNING: at drivers/misc/kgdbts.c:317 check_and_rewind_pc+0x9c/0xc4() [] (check_and_rewind_pc+0x9c/0xc4) [] (validate_simple_test+0x3c/0xc4) [] (run_simple_test+0x1e8/0x274) The kernel will eventually recovers, but the test suite has completely failed to test anything useful. This patch implements behavior similar to a real debugger that does not rely on hardware single stepping by using only software planted breakpoints. In order to mimic a real debugger, the kgdb test suite now tracks the most recent thread that was continued (cont_thread_id), with the intent to single step just this thread. When the response to the single step request stops in a different thread that hit the original break point that thread will now get continued, while the debugger waits for the thread with the single step pending. Here is a high level description of the sequence of events. cont_instead_of_sstep = 0; 1) set breakpoint at do_fork 2) continue 3) Save the thread id where we stop to cont_thread_id 4) Remove breakpoint at do_fork 5) Reset the PC if needed depending on kernel exception type 6) soft single step 7) Check where we stopped if current thread != cont_thread_id { if (here for more than 2 times for the same thead) { ### must be a really busy system, start test again ### goto step 1 } goto step 5 } else { cont_instead_of_sstep = 0; } 8) clean up and run test again if needed 9) Clear out any threads that were waiting on a break point at the point in time the test is ended with get_cont_catch(). This happens sometimes because breakpoints are used in place of single stepping and some threads could have been in the debugger exception handling queue because breakpoints were hit concurrently on different CPUs. This also means we wait at least one second before unplumbing the debugger connection at the very end, so as respond to any debug threads waiting to be serviced. Cc: stable@vger.kernel.org # >= 3.0 Signed-off-by: Jason Wessel diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 3cad9fc..d087456 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -142,7 +142,9 @@ static int arch_needs_sstep_emulation = 1; #else static int arch_needs_sstep_emulation; #endif +static unsigned long cont_addr; static unsigned long sstep_addr; +static int restart_from_top_after_write; static int sstep_state; /* Storage for the registers, in GDB format. */ @@ -190,7 +192,8 @@ static int kgdbts_unreg_thread(void *ptr) */ while (!final_ack) msleep_interruptible(1500); - + /* Pause for any other threads to exit after final ack. */ + msleep_interruptible(1000); if (configured) kgdb_unregister_io_module(&kgdbts_io_ops); configured = 0; @@ -312,13 +315,21 @@ static int check_and_rewind_pc(char *put_str, char *arg) if (addr + BREAK_INSTR_SIZE == ip) offset = -BREAK_INSTR_SIZE; #endif - if (strcmp(arg, "silent") && ip + offset != addr) { + + if (arch_needs_sstep_emulation && sstep_addr && + ip + offset == sstep_addr && + ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) { + /* This is special case for emulated single step */ + v2printk("Emul: rewind hit single step bp\n"); + restart_from_top_after_write = 1; + } else if (strcmp(arg, "silent") && ip + offset != addr) { eprintk("kgdbts: BP mismatch %lx expected %lx\n", ip + offset, addr); return 1; } /* Readjust the instruction pointer if needed */ ip += offset; + cont_addr = ip; #ifdef GDB_ADJUSTS_BREAK_OFFSET instruction_pointer_set(&kgdbts_regs, ip); #endif @@ -328,6 +339,8 @@ static int check_and_rewind_pc(char *put_str, char *arg) static int check_single_step(char *put_str, char *arg) { unsigned long addr = lookup_addr(arg); + static int matched_id; + /* * From an arch indepent point of view the instruction pointer * should be on a different instruction @@ -338,17 +351,28 @@ static int check_single_step(char *put_str, char *arg) v2printk("Singlestep stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs)); - if (sstep_thread_id != cont_thread_id && !arch_needs_sstep_emulation) { + if (sstep_thread_id != cont_thread_id) { /* * Ensure we stopped in the same thread id as before, else the * debugger should continue until the original thread that was * single stepped is scheduled again, emulating gdb's behavior. */ v2printk("ThrID does not match: %lx\n", cont_thread_id); + if (arch_needs_sstep_emulation) { + if (matched_id && + instruction_pointer(&kgdbts_regs) != addr) + goto continue_test; + matched_id++; + ts.idx -= 2; + sstep_state = 0; + return 0; + } cont_instead_of_sstep = 1; ts.idx -= 4; return 0; } +continue_test: + matched_id = 0; if (instruction_pointer(&kgdbts_regs) == addr) { eprintk("kgdbts: SingleStep failed at %lx\n", instruction_pointer(&kgdbts_regs)); @@ -390,6 +414,31 @@ static int got_break(char *put_str, char *arg) return 1; } +static void get_cont_catch(char *arg) +{ + /* Always send detach because the test is completed at this point */ + fill_get_buf("D"); +} + +static int put_cont_catch(char *put_str, char *arg) +{ + /* This is at the end of the test and we catch any and all input */ + v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id); + ts.idx--; + return 0; +} + +static int emul_reset(char *put_str, char *arg) +{ + if (strncmp(put_str, "$OK", 3)) + return 1; + if (restart_from_top_after_write) { + restart_from_top_after_write = 0; + ts.idx = -1; + } + return 0; +} + static void emul_sstep_get(char *arg) { if (!arch_needs_sstep_emulation) { @@ -443,8 +492,7 @@ static int emul_sstep_put(char *put_str, char *arg) v2printk("Stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs)); /* Want to stop at IP + break instruction size by default */ - sstep_addr = instruction_pointer(&kgdbts_regs) + - BREAK_INSTR_SIZE; + sstep_addr = cont_addr + BREAK_INSTR_SIZE; break; case 2: if (strncmp(put_str, "$OK", 3)) { @@ -456,6 +504,9 @@ static int emul_sstep_put(char *put_str, char *arg) if (strncmp(put_str, "$T0", 3)) { eprintk("kgdbts: failed continue sstep\n"); return 1; + } else { + char *ptr = &put_str[11]; + kgdb_hex2long(&ptr, &sstep_thread_id); } break; case 4: @@ -558,13 +609,13 @@ static struct test_struct do_fork_test[] = { { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */ { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */ - { "write", "OK", write_regs }, /* Write registers */ + { "write", "OK", write_regs, emul_reset }, /* Write registers */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "g", "do_fork", NULL, check_single_step }, { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */ - { "", "" }, + { "", "", get_cont_catch, put_cont_catch }, }; /* Test for hitting a breakpoint at sys_open for what ever the number @@ -576,13 +627,13 @@ static struct test_struct sys_open_test[] = { { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */ { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */ - { "write", "OK", write_regs }, /* Write registers */ + { "write", "OK", write_regs, emul_reset }, /* Write registers */ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ { "g", "sys_open", NULL, check_single_step }, { "sys_open", "OK", sw_break, }, /* set sw breakpoint */ { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */ - { "", "" }, + { "", "", get_cont_catch, put_cont_catch }, }; /* @@ -725,8 +776,8 @@ static int run_simple_test(int is_get_char, int chr) /* This callback is a put char which is when kgdb sends data to * this I/O module. */ - if (ts.tst[ts.idx].get[0] == '\0' && - ts.tst[ts.idx].put[0] == '\0') { + if (ts.tst[ts.idx].get[0] == '\0' && ts.tst[ts.idx].put[0] == '\0' && + !ts.tst[ts.idx].get_handler) { eprintk("kgdbts: ERROR: beyond end of test on" " '%s' line %i\n", ts.name, ts.idx); return 0; -- cgit v0.10.2 From 98b54aa1a2241b59372468bd1e9c2d207bdba54b Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Wed, 21 Mar 2012 10:17:03 -0500 Subject: kgdb,debug_core: pass the breakpoint struct instead of address and memory There is extra state information that needs to be exposed in the kgdb_bpt structure for tracking how a breakpoint was installed. The debug_core only uses the the probe_kernel_write() to install breakpoints, but this is not enough for all the archs. Some arch such as x86 need to use text_poke() in order to install a breakpoint into a read only page. Passing the kgdb_bpt structure to kgdb_arch_set_breakpoint() and kgdb_arch_remove_breakpoint() allows other archs to set the type variable which indicates how the breakpoint was installed. Cc: stable@vger.kernel.org # >= 2.6.36 Signed-off-by: Jason Wessel diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index fa39183..e5d689c 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -207,8 +207,8 @@ extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc); /* Optional functions. */ extern int kgdb_validate_break_address(unsigned long addr); -extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr); -extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle); +extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt); +extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt); /** * kgdb_arch_late - Perform any architecture specific initalization. diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 3f88a45..a7e52ca 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -161,37 +161,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup); * Weak aliases for breakpoint management, * can be overriden by architectures when needed: */ -int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) +int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) { int err; - err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE); + err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, + BREAK_INSTR_SIZE); if (err) return err; - - return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, - BREAK_INSTR_SIZE); + err = probe_kernel_write((char *)bpt->bpt_addr, + arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); + return err; } -int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) +int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) { - return probe_kernel_write((char *)addr, - (char *)bundle, BREAK_INSTR_SIZE); + return probe_kernel_write((char *)bpt->bpt_addr, + (char *)bpt->saved_instr, BREAK_INSTR_SIZE); } int __weak kgdb_validate_break_address(unsigned long addr) { - char tmp_variable[BREAK_INSTR_SIZE]; + struct kgdb_bkpt tmp; int err; - /* Validate setting the breakpoint and then removing it. In the + /* Validate setting the breakpoint and then removing it. If the * remove fails, the kernel needs to emit a bad message because we * are deep trouble not being able to put things back the way we * found them. */ - err = kgdb_arch_set_breakpoint(addr, tmp_variable); + tmp.bpt_addr = addr; + err = kgdb_arch_set_breakpoint(&tmp); if (err) return err; - err = kgdb_arch_remove_breakpoint(addr, tmp_variable); + err = kgdb_arch_remove_breakpoint(&tmp); if (err) printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " "memory destroyed at: %lx", addr); @@ -235,7 +237,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) */ int dbg_activate_sw_breakpoints(void) { - unsigned long addr; int error; int ret = 0; int i; @@ -244,16 +245,15 @@ int dbg_activate_sw_breakpoints(void) if (kgdb_break[i].state != BP_SET) continue; - addr = kgdb_break[i].bpt_addr; - error = kgdb_arch_set_breakpoint(addr, - kgdb_break[i].saved_instr); + error = kgdb_arch_set_breakpoint(&kgdb_break[i]); if (error) { ret = error; - printk(KERN_INFO "KGDB: BP install failed: %lx", addr); + printk(KERN_INFO "KGDB: BP install failed: %lx", + kgdb_break[i].bpt_addr); continue; } - kgdb_flush_swbreak_addr(addr); + kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); kgdb_break[i].state = BP_ACTIVE; } return ret; @@ -302,7 +302,6 @@ int dbg_set_sw_break(unsigned long addr) int dbg_deactivate_sw_breakpoints(void) { - unsigned long addr; int error; int ret = 0; int i; @@ -310,15 +309,14 @@ int dbg_deactivate_sw_breakpoints(void) for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { if (kgdb_break[i].state != BP_ACTIVE) continue; - addr = kgdb_break[i].bpt_addr; - error = kgdb_arch_remove_breakpoint(addr, - kgdb_break[i].saved_instr); + error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); if (error) { - printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); + printk(KERN_INFO "KGDB: BP remove failed: %lx\n", + kgdb_break[i].bpt_addr); ret = error; } - kgdb_flush_swbreak_addr(addr); + kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); kgdb_break[i].state = BP_SET; } return ret; @@ -352,7 +350,6 @@ int kgdb_isremovedbreak(unsigned long addr) int dbg_remove_all_break(void) { - unsigned long addr; int error; int i; @@ -360,12 +357,10 @@ int dbg_remove_all_break(void) for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { if (kgdb_break[i].state != BP_ACTIVE) goto setundefined; - addr = kgdb_break[i].bpt_addr; - error = kgdb_arch_remove_breakpoint(addr, - kgdb_break[i].saved_instr); + error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); if (error) printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", - addr); + kgdb_break[i].bpt_addr); setundefined: kgdb_break[i].state = BP_UNDEFINED; } -- cgit v0.10.2 From 3751d3e85cf693e10e2c47c03c8caa65e171099b Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 23 Mar 2012 09:35:05 -0500 Subject: x86,kgdb: Fix DEBUG_RODATA limitation using text_poke() There has long been a limitation using software breakpoints with a kernel compiled with CONFIG_DEBUG_RODATA going back to 2.6.26. For this particular patch, it will apply cleanly and has been tested all the way back to 2.6.36. The kprobes code uses the text_poke() function which accommodates writing a breakpoint into a read-only page. The x86 kgdb code can solve the problem similarly by overriding the default breakpoint set/remove routines and using text_poke() directly. The x86 kgdb code will first attempt to use the traditional probe_kernel_write(), and next try using a the text_poke() function. The break point install method is tracked such that the correct break point removal routine will get called later on. Cc: x86@kernel.org Cc: Thomas Gleixner Cc: Ingo Molnar Cc: H. Peter Anvin Cc: stable@vger.kernel.org # >= 2.6.36 Inspried-by: Masami Hiramatsu Signed-off-by: Jason Wessel diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index fdc37b3..b9bd9d8 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -742,6 +744,64 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) regs->ip = ip; } +int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) +{ + int err; + char opc[BREAK_INSTR_SIZE]; + + bpt->type = BP_BREAKPOINT; + err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, + BREAK_INSTR_SIZE); + if (err) + return err; + err = probe_kernel_write((char *)bpt->bpt_addr, + arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); +#ifdef CONFIG_DEBUG_RODATA + if (!err) + return err; + /* + * It is safe to call text_poke() because normal kernel execution + * is stopped on all cores, so long as the text_mutex is not locked. + */ + if (mutex_is_locked(&text_mutex)) + return -EBUSY; + text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr, + BREAK_INSTR_SIZE); + err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); + if (err) + return err; + if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE)) + return -EINVAL; + bpt->type = BP_POKE_BREAKPOINT; +#endif /* CONFIG_DEBUG_RODATA */ + return err; +} + +int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) +{ +#ifdef CONFIG_DEBUG_RODATA + int err; + char opc[BREAK_INSTR_SIZE]; + + if (bpt->type != BP_POKE_BREAKPOINT) + goto knl_write; + /* + * It is safe to call text_poke() because normal kernel execution + * is stopped on all cores, so long as the text_mutex is not locked. + */ + if (mutex_is_locked(&text_mutex)) + goto knl_write; + text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE); + err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); + if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE)) + goto knl_write; + return err; +knl_write: +#endif /* CONFIG_DEBUG_RODATA */ + return probe_kernel_write((char *)bpt->bpt_addr, + (char *)bpt->saved_instr, BREAK_INSTR_SIZE); +} + struct kgdb_arch arch_kgdb_ops = { /* Breakpoint instruction: */ .gdb_bpt_instr = { 0xcc }, diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index d087456..3aa9a96 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -968,22 +968,6 @@ static void run_singlestep_break_test(void) kgdbts_break_test(); } -static void test_debug_rodata(void) -{ -#ifdef CONFIG_DEBUG_RODATA - /* Until there is an api to write to read-only text segments, use - * HW breakpoints for the remainder of any tests, else print a - * failure message if hw breakpoints do not work. - */ - if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) { - eprintk("kgdbts: HW breakpoints BROKEN, ending tests\n"); - return; - } - force_hwbrks = 1; - v1printk("kgdbts:Using HW breakpoints for SW breakpoint tests\n"); -#endif /* CONFIG_DEBUG_RODATA */ -} - static void kgdbts_run_tests(void) { char *ptr; @@ -1016,7 +1000,6 @@ static void kgdbts_run_tests(void) v1printk("kgdbts:RUN access write breakpoint test\n"); run_hw_break_test(0); } - test_debug_rodata(); /* required internal KGDB tests */ v1printk("kgdbts:RUN plant and detach test\n"); diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index e5d689c..c4d2fc1 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -63,7 +63,8 @@ enum kgdb_bptype { BP_HARDWARE_BREAKPOINT, BP_WRITE_WATCHPOINT, BP_READ_WATCHPOINT, - BP_ACCESS_WATCHPOINT + BP_ACCESS_WATCHPOINT, + BP_POKE_BREAKPOINT, }; enum kgdb_bpstate { -- cgit v0.10.2 From f6365201d8a21fb347260f89d6e9b3e718d63c70 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 29 Mar 2012 14:49:17 -0700 Subject: x86: Remove the ancient and deprecated disable_hlt() and enable_hlt() facility The X86_32-only disable_hlt/enable_hlt mechanism was used by the 32-bit floppy driver. Its effect was to replace the use of the HLT instruction inside default_idle() with cpu_relax() - essentially it turned off the use of HLT. This workaround was commented in the code as: "disable hlt during certain critical i/o operations" "This halt magic was a workaround for ancient floppy DMA wreckage. It should be safe to remove." H. Peter Anvin additionally adds: "To the best of my knowledge, no-hlt only existed because of flaky power distributions on 386/486 systems which were sold to run DOS. Since DOS did no power management of any kind, including HLT, the power draw was fairly uniform; when exposed to the much hhigher noise levels you got when Linux used HLT caused some of these systems to fail. They were by far in the minority even back then." Alan Cox further says: "Also for the Cyrix 5510 which tended to go castors up if a HLT occurred during a DMA cycle and on a few other boxes HLT during DMA tended to go astray. Do we care ? I doubt it. The 5510 was pretty obscure, the 5520 fixed it, the 5530 is probably the oldest still in any kind of use." So, let's finally drop this. Signed-off-by: Len Brown Signed-off-by: Josh Boyer Signed-off-by: Andrew Morton Acked-by: "H. Peter Anvin" Acked-by: Alan Cox Cc: Stephen Hemminger Cc: Link: http://lkml.kernel.org/n/tip-3rhk9bzf0x9rljkv488tloib@git.kernel.org [ If anyone cares then alternative instruction patching could be used to replace HLT with a one-byte NOP instruction. Much simpler. ] Signed-off-by: Ingo Molnar diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 0cad480..7c950d4 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -6,14 +6,6 @@ be removed from this file. --------------------------- -What: x86 floppy disable_hlt -When: 2012 -Why: ancient workaround of dubious utility clutters the - code used by everybody else. -Who: Len Brown - ---------------------------- - What: CONFIG_APM_CPU_IDLE, and its ability to call APM BIOS in idle When: 2012 Why: This optional sub-feature of APM is of dubious reliability, diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 7284c9a..4fa7dcc 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -974,16 +974,6 @@ extern bool cpu_has_amd_erratum(const int *); #define cpu_has_amd_erratum(x) (false) #endif /* CONFIG_CPU_SUP_AMD */ -#ifdef CONFIG_X86_32 -/* - * disable hlt during certain critical i/o operations - */ -#define HAVE_DISABLE_HLT -#endif - -void disable_hlt(void); -void enable_hlt(void); - void cpu_idle_wait(void); extern unsigned long arch_align_stack(unsigned long sp); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index a33afaa..1d92a5a 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -362,34 +362,10 @@ void (*pm_idle)(void); EXPORT_SYMBOL(pm_idle); #endif -#ifdef CONFIG_X86_32 -/* - * This halt magic was a workaround for ancient floppy DMA - * wreckage. It should be safe to remove. - */ -static int hlt_counter; -void disable_hlt(void) -{ - hlt_counter++; -} -EXPORT_SYMBOL(disable_hlt); - -void enable_hlt(void) -{ - hlt_counter--; -} -EXPORT_SYMBOL(enable_hlt); - -static inline int hlt_use_halt(void) -{ - return (!hlt_counter && boot_cpu_data.hlt_works_ok); -} -#else static inline int hlt_use_halt(void) { return 1; } -#endif #ifndef CONFIG_SMP static inline void play_dead(void) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 76a0823..b0b00d7 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -1030,37 +1030,6 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function) return 0; } -static DEFINE_SPINLOCK(floppy_hlt_lock); -static int hlt_disabled; -static void floppy_disable_hlt(void) -{ - unsigned long flags; - - WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012"); - spin_lock_irqsave(&floppy_hlt_lock, flags); - if (!hlt_disabled) { - hlt_disabled = 1; -#ifdef HAVE_DISABLE_HLT - disable_hlt(); -#endif - } - spin_unlock_irqrestore(&floppy_hlt_lock, flags); -} - -static void floppy_enable_hlt(void) -{ - unsigned long flags; - - spin_lock_irqsave(&floppy_hlt_lock, flags); - if (hlt_disabled) { - hlt_disabled = 0; -#ifdef HAVE_DISABLE_HLT - enable_hlt(); -#endif - } - spin_unlock_irqrestore(&floppy_hlt_lock, flags); -} - static void setup_DMA(void) { unsigned long f; @@ -1105,7 +1074,6 @@ static void setup_DMA(void) fd_enable_dma(); release_dma_lock(f); #endif - floppy_disable_hlt(); } static void show_floppy(void); @@ -1707,7 +1675,6 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) fd_disable_dma(); release_dma_lock(f); - floppy_enable_hlt(); do_floppy = NULL; if (fdc >= N_FDC || FDCS->address == -1) { /* we don't even know which FDC is the culprit */ @@ -1856,8 +1823,6 @@ static void floppy_shutdown(unsigned long data) show_floppy(); cancel_activity(); - floppy_enable_hlt(); - flags = claim_dma_lock(); fd_disable_dma(); release_dma_lock(flags); @@ -4508,7 +4473,6 @@ static void floppy_release_irq_and_dma(void) #if N_FDC > 1 set_dor(1, ~8, 0); #endif - floppy_enable_hlt(); if (floppy_track_buffer && max_buffer_sectors) { tmpsize = max_buffer_sectors * 1024; -- cgit v0.10.2 From ac64a9caa55bdfd8d24784f25c68cb7919ddabe3 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Mar 2012 08:21:38 +0200 Subject: microblaze: Fix stack usage in PAGE_SIZE copy_tofrom_user If access to user space failed we need to reconstruct stack pointer and restore all register. This patch fixed problem introduces by: "microblaze: Add loop unrolling for PAGE in copy_tofrom_user" (sha1: ebe211254bfa6295f4ab0b33c7c881bdfabbab60) Signed-off-by: Michal Simek diff --git a/arch/microblaze/lib/uaccess_old.S b/arch/microblaze/lib/uaccess_old.S index f037266..f085995 100644 --- a/arch/microblaze/lib/uaccess_old.S +++ b/arch/microblaze/lib/uaccess_old.S @@ -122,22 +122,22 @@ __strnlen_user: 15: swi r24, r5, 0x0018 + offset; \ 16: swi r25, r5, 0x001C + offset; \ .section __ex_table,"a"; \ - .word 1b, 0f; \ - .word 2b, 0f; \ - .word 3b, 0f; \ - .word 4b, 0f; \ - .word 5b, 0f; \ - .word 6b, 0f; \ - .word 7b, 0f; \ - .word 8b, 0f; \ - .word 9b, 0f; \ - .word 10b, 0f; \ - .word 11b, 0f; \ - .word 12b, 0f; \ - .word 13b, 0f; \ - .word 14b, 0f; \ - .word 15b, 0f; \ - .word 16b, 0f; \ + .word 1b, 33f; \ + .word 2b, 33f; \ + .word 3b, 33f; \ + .word 4b, 33f; \ + .word 5b, 33f; \ + .word 6b, 33f; \ + .word 7b, 33f; \ + .word 8b, 33f; \ + .word 9b, 33f; \ + .word 10b, 33f; \ + .word 11b, 33f; \ + .word 12b, 33f; \ + .word 13b, 33f; \ + .word 14b, 33f; \ + .word 15b, 33f; \ + .word 16b, 33f; \ .text #define COPY_80(offset) \ @@ -190,14 +190,17 @@ w2: sw r4, r5, r3 .align 4 /* Alignment is important to keep icache happy */ page: /* Create room on stack and save registers for storign values */ - addik r1, r1, -32 - swi r19, r1, 4 - swi r20, r1, 8 - swi r21, r1, 12 - swi r22, r1, 16 - swi r23, r1, 20 - swi r24, r1, 24 - swi r25, r1, 28 + addik r1, r1, -40 + swi r5, r1, 0 + swi r6, r1, 4 + swi r7, r1, 8 + swi r19, r1, 12 + swi r20, r1, 16 + swi r21, r1, 20 + swi r22, r1, 24 + swi r23, r1, 28 + swi r24, r1, 32 + swi r25, r1, 36 loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */ /* Loop unrolling to get performance boost */ COPY_80(0x000); @@ -205,21 +208,44 @@ loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */ COPY_80(0x100); COPY_80(0x180); /* copy loop */ - addik r6, r6, 0x200 - addik r7, r7, -0x200 - bneid r7, loop - addik r5, r5, 0x200 + addik r6, r6, 0x200 + addik r7, r7, -0x200 + bneid r7, loop + addik r5, r5, 0x200 + /* Restore register content */ - lwi r19, r1, 4 - lwi r20, r1, 8 - lwi r21, r1, 12 - lwi r22, r1, 16 - lwi r23, r1, 20 - lwi r24, r1, 24 - lwi r25, r1, 28 - addik r1, r1, 32 + lwi r5, r1, 0 + lwi r6, r1, 4 + lwi r7, r1, 8 + lwi r19, r1, 12 + lwi r20, r1, 16 + lwi r21, r1, 20 + lwi r22, r1, 24 + lwi r23, r1, 28 + lwi r24, r1, 32 + lwi r25, r1, 36 + addik r1, r1, 40 /* return back */ + addik r3, r0, 0 + rtsd r15, 8 + nop + +/* Fault case - return temp count */ +33: addik r3, r7, 0 + /* Restore register content */ + lwi r5, r1, 0 + lwi r6, r1, 4 + lwi r7, r1, 8 + lwi r19, r1, 12 + lwi r20, r1, 16 + lwi r21, r1, 20 + lwi r22, r1, 24 + lwi r23, r1, 28 + lwi r24, r1, 32 + lwi r25, r1, 36 + addik r1, r1, 40 + /* return back */ rtsd r15, 8 nop -- cgit v0.10.2 From 90c0d80daa82fa9cbaa85d1a787375b33877d2d4 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Mar 2012 11:29:38 +0200 Subject: microblaze: Add missing headers caused by disintegration asm/system.h It should be the part of patch "Disintegrate asm/system.h for Microblaze" (sha1: c40d04df152a1111c5bbcb632278394dabd2b73d) Signed-off-by: Michal Simek diff --git a/arch/microblaze/include/asm/cmpxchg.h b/arch/microblaze/include/asm/cmpxchg.h index 0094859a..538afc0 100644 --- a/arch/microblaze/include/asm/cmpxchg.h +++ b/arch/microblaze/include/asm/cmpxchg.h @@ -1,6 +1,8 @@ #ifndef _ASM_MICROBLAZE_CMPXCHG_H #define _ASM_MICROBLAZE_CMPXCHG_H +#include + void __bad_xchg(volatile void *ptr, int size); static inline unsigned long __xchg(unsigned long x, volatile void *ptr, diff --git a/arch/microblaze/kernel/unwind.c b/arch/microblaze/kernel/unwind.c index 9781a52..6be4ae3 100644 --- a/arch/microblaze/kernel/unwind.c +++ b/arch/microblaze/kernel/unwind.c @@ -24,6 +24,7 @@ #include #include #include +#include struct stack_trace; -- cgit v0.10.2 From f03c4866d31e913a8dbc84f7d1459abdaf0bd326 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 30 Mar 2012 19:29:57 +0900 Subject: sh: fix up fallout from system.h disintegration. Quite a bit of fallout all over the place, nothing terribly exciting. Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index d879848..d0d6221 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * NOTE: This board has 2 physical memory maps. diff --git a/arch/sh/boards/mach-hp6xx/pm.c b/arch/sh/boards/mach-hp6xx/pm.c index adc9b4b..8b50cf7 100644 --- a/arch/sh/boards/mach-hp6xx/pm.c +++ b/arch/sh/boards/mach-hp6xx/pm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c index 7f1b70c..f8f7af5 100644 --- a/arch/sh/kernel/cpu/fpu.c +++ b/arch/sh/kernel/cpu/fpu.c @@ -2,6 +2,7 @@ #include #include #include +#include int init_fpu(struct task_struct *tsk) { diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c index 488d24e..98bbaa4 100644 --- a/arch/sh/kernel/cpu/sh2a/fpu.c +++ b/arch/sh/kernel/cpu/sh2a/fpu.c @@ -14,6 +14,7 @@ #include #include #include +#include /* The PR (precision) bit in the FP Status Register must be clear when * an frchg instruction is executed, otherwise the instruction is undefined. diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index e74cd6c..69ab4d3 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c @@ -16,6 +16,7 @@ #include #include #include +#include /* The PR (precision) bit in the FP Status Register must be clear when * an frchg instruction is executed, otherwise the instruction is undefined. diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c index a6f95ae..08d27fa 100644 --- a/arch/sh/kernel/cpu/shmobile/pm.c +++ b/arch/sh/kernel/cpu/shmobile/pm.c @@ -16,6 +16,7 @@ #include #include #include +#include /* * Notifier lists for pre/post sleep notification diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 64852ec..ee226e2 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -17,8 +17,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c index efb6d39..b117781 100644 --- a/arch/sh/kernel/kgdb.c +++ b/arch/sh/kernel/kgdb.c @@ -14,6 +14,7 @@ #include #include #include +#include /* Macros for single step instruction identification */ #define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index f72e3a9..94273aa 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -26,6 +26,7 @@ #include #include #include +#include void show_regs(struct pt_regs * regs) { diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index a17a14d..eaebdf6 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -27,6 +27,7 @@ #include #include #include +#include int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index 112fea1..0e52928 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* diff --git a/arch/sh/mm/flush-sh4.c b/arch/sh/mm/flush-sh4.c index 75a17f5..0b85dd9 100644 --- a/arch/sh/mm/flush-sh4.c +++ b/arch/sh/mm/flush-sh4.c @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/arch/sh/mm/sram.c b/arch/sh/mm/sram.c index bc156ec..2d8fa71 100644 --- a/arch/sh/mm/sram.c +++ b/arch/sh/mm/sram.c @@ -9,6 +9,7 @@ */ #include #include +#include #include /* -- cgit v0.10.2 From da47f4a3186b4f55914cceffb51adfa55ef4897e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 30 Mar 2012 19:31:22 +0900 Subject: sh: dwarf unwinder depends on SHcompact. Presently there's no SHmedia support plugged in for the dwarf unwinder. While it's trivial to provide an SHmedia version of dwarf_read_arch_reg(), the general sh64 case is more complicated in that the TLB miss handler uses a locked down set of registers for optimization (including the frame pointer) which we need for the unwind table generation. While freeing up the frame pointer for use in the TLB miss handler is reasonably straightforward, it's still more trouble than it's worth, so we simply restrict the unwinder to 32-bit for now. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index c1d5a82..5f2bb42 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -61,6 +61,7 @@ config DUMP_CODE config DWARF_UNWINDER bool "Enable the DWARF unwinder for stacktraces" select FRAME_POINTER + depends on SUPERH32 default n help Enabling this option will make stacktraces more accurate, at -- cgit v0.10.2 From 87c34ed3aba9249cb06d1a1f100cd3618f29268c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 30 Mar 2012 19:36:03 +0900 Subject: sh: dma: Fix up device attribute mismatch from sysdev fallout. This fixes up an attribute mismatch that was introduced in the sysdev->struct device migration. Signed-off-by: Paul Mundt diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index b1cb271..67ee956 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -54,7 +54,7 @@ static int __init dma_subsys_init(void) if (unlikely(ret)) return ret; - return device_create_file(dma_subsys.dev_root, &dev_attr_devices.attr); + return device_create_file(dma_subsys.dev_root, &dev_attr_devices); } postcore_initcall(dma_subsys_init); -- cgit v0.10.2 From cd34e202faa4be7f77fd2f7a59824f13dc14901b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 30 Mar 2012 19:42:26 +0900 Subject: sh: vsyscall: Fix up .eh_frame generation. Some improper formatting caused the .eh_frame generation to fail, resulting in gcc/g++ testsuite failures with regards to unwinding through the vDSO. Now that someone is actually working on this on the gcc side it's time to fix up the kernel side, too. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S index 555a64f..23af175 100644 --- a/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S +++ b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S @@ -34,6 +34,41 @@ __kernel_rt_sigreturn: 1: .short __NR_rt_sigreturn .LEND_rt_sigreturn: .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn + .previous .section .eh_frame,"a",@progbits +.LCIE1: + .ualong .LCIE1_end - .LCIE1_start +.LCIE1_start: + .ualong 0 /* CIE ID */ + .byte 0x1 /* Version number */ + .string "zRS" /* NUL-terminated augmentation string */ + .uleb128 0x1 /* Code alignment factor */ + .sleb128 -4 /* Data alignment factor */ + .byte 0x11 /* Return address register column */ + .uleb128 0x1 /* Augmentation length and data */ + .byte 0x1b /* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */ + .byte 0xc, 0xf, 0x0 /* DW_CFA_def_cfa: r15 ofs 0 */ + + .align 2 +.LCIE1_end: + + .ualong .LFDE0_end-.LFDE0_start /* Length FDE0 */ +.LFDE0_start: + .ualong .LFDE0_start-.LCIE1 /* CIE pointer */ + .ualong .LSTART_sigreturn-. /* PC-relative start address */ + .ualong .LEND_sigreturn-.LSTART_sigreturn + .uleb128 0 /* Augmentation */ + .align 2 +.LFDE0_end: + + .ualong .LFDE1_end-.LFDE1_start /* Length FDE1 */ +.LFDE1_start: + .ualong .LFDE1_start-.LCIE1 /* CIE pointer */ + .ualong .LSTART_rt_sigreturn-. /* PC-relative start address */ + .ualong .LEND_rt_sigreturn-.LSTART_rt_sigreturn + .uleb128 0 /* Augmentation */ + .align 2 +.LFDE1_end: + .previous diff --git a/arch/sh/kernel/vsyscall/vsyscall-trapa.S b/arch/sh/kernel/vsyscall/vsyscall-trapa.S index 3e70f85..0eb74d0 100644 --- a/arch/sh/kernel/vsyscall/vsyscall-trapa.S +++ b/arch/sh/kernel/vsyscall/vsyscall-trapa.S @@ -3,37 +3,34 @@ .type __kernel_vsyscall,@function __kernel_vsyscall: .LSTART_vsyscall: - /* XXX: We'll have to do something here once we opt to use the vDSO - * page for something other than the signal trampoline.. as well as - * fill out .eh_frame -- PFM. */ + trapa #0x10 + nop .LEND_vsyscall: .size __kernel_vsyscall,.-.LSTART_vsyscall + .previous .section .eh_frame,"a",@progbits - .previous .LCIE: .ualong .LCIE_end - .LCIE_start .LCIE_start: .ualong 0 /* CIE ID */ .byte 0x1 /* Version number */ - .string "zRS" /* NUL-terminated augmentation string */ + .string "zR" /* NUL-terminated augmentation string */ .uleb128 0x1 /* Code alignment factor */ .sleb128 -4 /* Data alignment factor */ .byte 0x11 /* Return address register column */ - /* Augmentation length and data (none) */ - .byte 0xc /* DW_CFA_def_cfa */ - .uleb128 0xf /* r15 */ - .uleb128 0x0 /* offset 0 */ - + .uleb128 0x1 /* Augmentation length and data */ + .byte 0x1b /* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */ + .byte 0xc,0xf,0x0 /* DW_CFA_def_cfa: r15 ofs 0 */ .align 2 .LCIE_end: .ualong .LFDE_end-.LFDE_start /* Length FDE */ .LFDE_start: - .ualong .LCIE /* CIE pointer */ - .ualong .LSTART_vsyscall-. /* start address */ + .ualong .LFDE_start-.LCIE /* CIE pointer */ + .ualong .LSTART_vsyscall-. /* PC-relative start address */ .ualong .LEND_vsyscall-.LSTART_vsyscall - .uleb128 0 + .uleb128 0 /* Augmentation */ .align 2 .LFDE_end: .previous -- cgit v0.10.2 From d9d54540147336c75f81c36c342b3bfec0d4d60d Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 30 Mar 2012 11:44:15 +0100 Subject: ARM: sa11x0: fix build errors from DMA engine API updates The recent merge of the sa11x0 code into mainline had silent conflicts with further development of the DMA engine API, leading to build errors and warnings: drivers/net/irda/sa1100_ir.c: In function 'sa1100_irda_dma_start': drivers/net/irda/sa1100_ir.c:151: error: too few arguments to function 'chan->device->device_prep_slave_sg' drivers/dma/sa11x0-dma.c: In function 'sa11x0_dma_probe': drivers/dma/sa11x0-dma.c:950: warning: assignment from incompatible pointer type Fix these. Signed-off-by: Russell King diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c index 16a6b48..ec78cce 100644 --- a/drivers/dma/sa11x0-dma.c +++ b/drivers/dma/sa11x0-dma.c @@ -585,7 +585,7 @@ static dma_cookie_t sa11x0_dma_tx_submit(struct dma_async_tx_descriptor *tx) static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sg, unsigned int sglen, - enum dma_transfer_direction dir, unsigned long flags) + enum dma_transfer_direction dir, unsigned long flags, void *context) { struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan); struct sa11x0_dma_desc *txd; diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index a0d1913..e250675 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -147,7 +147,7 @@ static void sa1100_irda_dma_start(struct sa1100_buf *buf, struct dma_async_tx_descriptor *desc; struct dma_chan *chan = buf->chan; - desc = chan->device->device_prep_slave_sg(chan, &buf->sg, 1, dir, + desc = dmaengine_prep_slave_sg(chan, &buf->sg, 1, dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (desc) { desc->callback = cb; -- cgit v0.10.2 From b12bb29f847050b8e75e445c839a2d42989213df Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 30 Mar 2012 19:50:15 +0900 Subject: serial: sh-sci: use serial_port_in/out vs sci_in/out. Follows the 8250 change for pretty much the same rationale. See commit "serial: use serial_port_in/out vs serial_in/out in 8250". Signed-off-by: Paul Mundt diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index bf461cf..3158e17 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -355,9 +355,6 @@ static void sci_serial_out(struct uart_port *p, int offset, int value) WARN(1, "Invalid register access\n"); } -#define sci_in(up, offset) (up->serial_in(up, offset)) -#define sci_out(up, offset, value) (up->serial_out(up, offset, value)) - static int sci_probe_regmap(struct plat_sci_port *cfg) { switch (cfg->type) { @@ -422,9 +419,9 @@ static int sci_poll_get_char(struct uart_port *port) int c; do { - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); if (status & SCxSR_ERRORS(port)) { - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); continue; } break; @@ -433,11 +430,11 @@ static int sci_poll_get_char(struct uart_port *port) if (!(status & SCxSR_RDxF(port))) return NO_POLL_CHAR; - c = sci_in(port, SCxRDR); + c = serial_port_in(port, SCxRDR); /* Dummy read */ - sci_in(port, SCxSR); - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); return c; } @@ -448,11 +445,11 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) unsigned short status; do { - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); } while (!(status & SCxSR_TDxE(port))); - sci_out(port, SCxTDR, c); - sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); + serial_port_out(port, SCxTDR, c); + serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); } #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ @@ -480,10 +477,10 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) ((!(cflag & CRTSCTS)))) { unsigned short status; - status = sci_in(port, SCSPTR); + status = serial_port_in(port, SCSPTR); status &= ~SCSPTR_CTSIO; status |= SCSPTR_RTSIO; - sci_out(port, SCSPTR, status); /* Set RTS = 1 */ + serial_port_out(port, SCSPTR, status); /* Set RTS = 1 */ } } @@ -493,13 +490,13 @@ static int sci_txfill(struct uart_port *port) reg = sci_getreg(port, SCTFDR); if (reg->size) - return sci_in(port, SCTFDR) & 0xff; + return serial_port_in(port, SCTFDR) & 0xff; reg = sci_getreg(port, SCFDR); if (reg->size) - return sci_in(port, SCFDR) >> 8; + return serial_port_in(port, SCFDR) >> 8; - return !(sci_in(port, SCxSR) & SCI_TDRE); + return !(serial_port_in(port, SCxSR) & SCI_TDRE); } static int sci_txroom(struct uart_port *port) @@ -513,13 +510,13 @@ static int sci_rxfill(struct uart_port *port) reg = sci_getreg(port, SCRFDR); if (reg->size) - return sci_in(port, SCRFDR) & 0xff; + return serial_port_in(port, SCRFDR) & 0xff; reg = sci_getreg(port, SCFDR); if (reg->size) - return sci_in(port, SCFDR) & ((port->fifosize << 1) - 1); + return serial_port_in(port, SCFDR) & ((port->fifosize << 1) - 1); - return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; + return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; } /* @@ -547,14 +544,14 @@ static void sci_transmit_chars(struct uart_port *port) unsigned short ctrl; int count; - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); if (!(status & SCxSR_TDxE(port))) { - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (uart_circ_empty(xmit)) ctrl &= ~SCSCR_TIE; else ctrl |= SCSCR_TIE; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); return; } @@ -573,27 +570,27 @@ static void sci_transmit_chars(struct uart_port *port) break; } - sci_out(port, SCxTDR, c); + serial_port_out(port, SCxTDR, c); port->icount.tx++; } while (--count > 0); - sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (uart_circ_empty(xmit)) { sci_stop_tx(port); } else { - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (port->type != PORT_SCI) { - sci_in(port, SCxSR); /* Dummy read */ - sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + serial_port_in(port, SCxSR); /* Dummy read */ + serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); } ctrl |= SCSCR_TIE; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } } @@ -608,7 +605,7 @@ static void sci_receive_chars(struct uart_port *port) unsigned short status; unsigned char flag; - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); if (!(status & SCxSR_RDxF(port))) return; @@ -621,7 +618,7 @@ static void sci_receive_chars(struct uart_port *port) break; if (port->type == PORT_SCI) { - char c = sci_in(port, SCxRDR); + char c = serial_port_in(port, SCxRDR); if (uart_handle_sysrq_char(port, c) || sci_port->break_flag) count = 0; @@ -629,9 +626,9 @@ static void sci_receive_chars(struct uart_port *port) tty_insert_flip_char(tty, c, TTY_NORMAL); } else { for (i = 0; i < count; i++) { - char c = sci_in(port, SCxRDR); + char c = serial_port_in(port, SCxRDR); - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); #if defined(CONFIG_CPU_SH3) /* Skip "chars" during break */ if (sci_port->break_flag) { @@ -672,8 +669,8 @@ static void sci_receive_chars(struct uart_port *port) } } - sci_in(port, SCxSR); /* dummy read */ - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); /* dummy read */ + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); copied += count; port->icount.rx += count; @@ -683,8 +680,8 @@ static void sci_receive_chars(struct uart_port *port) /* Tell the rest of the system the news. New characters! */ tty_flip_buffer_push(tty); } else { - sci_in(port, SCxSR); /* dummy read */ - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); /* dummy read */ + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } } @@ -726,7 +723,7 @@ static void sci_break_timer(unsigned long data) static int sci_handle_errors(struct uart_port *port) { int copied = 0; - unsigned short status = sci_in(port, SCxSR); + unsigned short status = serial_port_in(port, SCxSR); struct tty_struct *tty = port->state->port.tty; struct sci_port *s = to_sci_port(port); @@ -804,8 +801,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port) if (!reg->size) return 0; - if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { - sci_out(port, SCLSR, 0); + if ((serial_port_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { + serial_port_out(port, SCLSR, 0); port->icount.overrun++; @@ -822,7 +819,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port) static int sci_handle_breaks(struct uart_port *port) { int copied = 0; - unsigned short status = sci_in(port, SCxSR); + unsigned short status = serial_port_in(port, SCxSR); struct tty_struct *tty = port->state->port.tty; struct sci_port *s = to_sci_port(port); @@ -859,8 +856,8 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) struct sci_port *s = to_sci_port(port); if (s->chan_rx) { - u16 scr = sci_in(port, SCSCR); - u16 ssr = sci_in(port, SCxSR); + u16 scr = serial_port_in(port, SCSCR); + u16 ssr = serial_port_in(port, SCxSR); /* Disable future Rx interrupts */ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { @@ -869,9 +866,9 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) } else { scr &= ~SCSCR_RIE; } - sci_out(port, SCSCR, scr); + serial_port_out(port, SCSCR, scr); /* Clear current interrupt */ - sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); + serial_port_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n", jiffies, s->rx_timeout); mod_timer(&s->rx_timer, jiffies + s->rx_timeout); @@ -909,15 +906,15 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr) if (port->type == PORT_SCI) { if (sci_handle_errors(port)) { /* discard character in rx buffer */ - sci_in(port, SCxSR); - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } } else { sci_handle_fifo_overrun(port); sci_rx_interrupt(irq, ptr); } - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); /* Kick the transmission */ sci_tx_interrupt(irq, ptr); @@ -931,7 +928,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) /* Handle BREAKs */ sci_handle_breaks(port); - sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); return IRQ_HANDLED; } @@ -955,8 +952,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) struct sci_port *s = to_sci_port(port); irqreturn_t ret = IRQ_NONE; - ssr_status = sci_in(port, SCxSR); - scr_status = sci_in(port, SCSCR); + ssr_status = serial_port_in(port, SCxSR); + scr_status = serial_port_in(port, SCSCR); err_enabled = scr_status & port_rx_irq_mask(port); /* Tx Interrupt */ @@ -1170,7 +1167,7 @@ static void sci_free_gpios(struct sci_port *port) static unsigned int sci_tx_empty(struct uart_port *port) { - unsigned short status = sci_in(port, SCxSR); + unsigned short status = serial_port_in(port, SCxSR); unsigned short in_tx_fifo = sci_txfill(port); return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0; @@ -1198,7 +1195,7 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) */ reg = sci_getreg(port, SCFCR); if (reg->size) - sci_out(port, SCFCR, sci_in(port, SCFCR) | 1); + serial_port_out(port, SCFCR, serial_port_in(port, SCFCR) | 1); } } @@ -1240,8 +1237,8 @@ static void sci_dma_tx_complete(void *arg) } else { s->cookie_tx = -EINVAL; if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { - u16 ctrl = sci_in(port, SCSCR); - sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); + u16 ctrl = serial_port_in(port, SCSCR); + serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE); } } @@ -1494,13 +1491,13 @@ static void sci_start_tx(struct uart_port *port) #ifdef CONFIG_SERIAL_SH_SCI_DMA if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { - u16 new, scr = sci_in(port, SCSCR); + u16 new, scr = serial_port_in(port, SCSCR); if (s->chan_tx) new = scr | 0x8000; else new = scr & ~0x8000; if (new != scr) - sci_out(port, SCSCR, new); + serial_port_out(port, SCSCR, new); } if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && @@ -1512,8 +1509,8 @@ static void sci_start_tx(struct uart_port *port) if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ - ctrl = sci_in(port, SCSCR); - sci_out(port, SCSCR, ctrl | SCSCR_TIE); + ctrl = serial_port_in(port, SCSCR); + serial_port_out(port, SCSCR, ctrl | SCSCR_TIE); } } @@ -1522,40 +1519,40 @@ static void sci_stop_tx(struct uart_port *port) unsigned short ctrl; /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x8000; ctrl &= ~SCSCR_TIE; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } static void sci_start_rx(struct uart_port *port) { unsigned short ctrl; - ctrl = sci_in(port, SCSCR) | port_rx_irq_mask(port); + ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x4000; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } static void sci_stop_rx(struct uart_port *port) { unsigned short ctrl; - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x4000; ctrl &= ~port_rx_irq_mask(port); - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } static void sci_enable_ms(struct uart_port *port) @@ -1589,13 +1586,13 @@ static void rx_timer_fn(unsigned long arg) { struct sci_port *s = (struct sci_port *)arg; struct uart_port *port = &s->port; - u16 scr = sci_in(port, SCSCR); + u16 scr = serial_port_in(port, SCSCR); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { scr &= ~0x4000; enable_irq(s->cfg->irqs[1]); } - sci_out(port, SCSCR, scr | SCSCR_RIE); + serial_port_out(port, SCSCR, scr | SCSCR_RIE); dev_dbg(port->dev, "DMA Rx timed out\n"); schedule_work(&s->work_rx); } @@ -1776,14 +1773,14 @@ static void sci_reset(struct uart_port *port) unsigned int status; do { - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); } while (!(status & SCxSR_TEND(port))); - sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ + serial_port_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ reg = sci_getreg(port, SCFCR); if (reg->size) - sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); + serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); } static void sci_set_termios(struct uart_port *port, struct ktermios *termios, @@ -1812,7 +1809,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_reset(port); - smr_val = sci_in(port, SCSMR) & 3; + smr_val = serial_port_in(port, SCSMR) & 3; if ((termios->c_cflag & CSIZE) == CS7) smr_val |= 0x40; @@ -1825,19 +1822,19 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, uart_update_timeout(port, termios->c_cflag, baud); - sci_out(port, SCSMR, smr_val); + serial_port_out(port, SCSMR, smr_val); dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, s->cfg->scscr); if (t > 0) { if (t >= 256) { - sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1); + serial_port_out(port, SCSMR, (serial_port_in(port, SCSMR) & ~3) | 1); t >>= 2; } else - sci_out(port, SCSMR, sci_in(port, SCSMR) & ~3); + serial_port_out(port, SCSMR, serial_port_in(port, SCSMR) & ~3); - sci_out(port, SCBRR, t); + serial_port_out(port, SCBRR, t); udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ } @@ -1845,7 +1842,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, reg = sci_getreg(port, SCFCR); if (reg->size) { - unsigned short ctrl = sci_in(port, SCFCR); + unsigned short ctrl = serial_port_in(port, SCFCR); if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) { if (termios->c_cflag & CRTSCTS) @@ -1861,10 +1858,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, */ ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST); - sci_out(port, SCFCR, ctrl); + serial_port_out(port, SCFCR, ctrl); } - sci_out(port, SCSCR, s->cfg->scscr); + serial_port_out(port, SCSCR, s->cfg->scscr); #ifdef CONFIG_SERIAL_SH_SCI_DMA /* @@ -2166,7 +2163,7 @@ static void serial_console_write(struct console *co, const char *s, /* wait until fifo is empty and last bit has been transmitted */ bits = SCxSR_TDxE(port) | SCxSR_TEND(port); - while ((sci_in(port, SCxSR) & bits) != bits) + while ((serial_port_in(port, SCxSR) & bits) != bits) cpu_relax(); sci_port_disable(sci_port); @@ -2260,12 +2257,12 @@ static int sci_runtime_suspend(struct device *dev) if (uart_console(port)) { struct plat_sci_reg *reg; - sci_port->saved_smr = sci_in(port, SCSMR); - sci_port->saved_brr = sci_in(port, SCBRR); + sci_port->saved_smr = serial_port_in(port, SCSMR); + sci_port->saved_brr = serial_port_in(port, SCBRR); reg = sci_getreg(port, SCFCR); if (reg->size) - sci_port->saved_fcr = sci_in(port, SCFCR); + sci_port->saved_fcr = serial_port_in(port, SCFCR); else sci_port->saved_fcr = 0; } @@ -2279,13 +2276,13 @@ static int sci_runtime_resume(struct device *dev) if (uart_console(port)) { sci_reset(port); - sci_out(port, SCSMR, sci_port->saved_smr); - sci_out(port, SCBRR, sci_port->saved_brr); + serial_port_out(port, SCSMR, sci_port->saved_smr); + serial_port_out(port, SCBRR, sci_port->saved_brr); if (sci_port->saved_fcr) - sci_out(port, SCFCR, sci_port->saved_fcr); + serial_port_out(port, SCFCR, sci_port->saved_fcr); - sci_out(port, SCSCR, sci_port->cfg->scscr); + serial_port_out(port, SCSCR, sci_port->cfg->scscr); } return 0; } diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index a1a2d36..4c22a15 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -20,10 +20,10 @@ defined(CONFIG_ARCH_SH7372) || \ defined(CONFIG_ARCH_R8A7740) -# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc) -# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73) -# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf) -# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3) +# define SCxSR_RDxF_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfffc) +# define SCxSR_ERROR_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfd73) +# define SCxSR_TDxE_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffdf) +# define SCxSR_BREAK_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffe3) #else # define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc) # define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073) -- cgit v0.10.2 From fa0d1dbf7fb6b6f1af85d298a4054fe9edc914c9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 30 Mar 2012 11:51:46 +0100 Subject: ARM: fix missing bug.h include in arch/arm/kernel/insn.c arch/arm/kernel/insn.c: In function '__arm_gen_branch_thumb2': arch/arm/kernel/insn.c:13: error: implicit declaration of function 'WARN_ON_ONCE' Signed-off-by: Russell King diff --git a/arch/arm/kernel/insn.c b/arch/arm/kernel/insn.c index ab312e5..b760340 100644 --- a/arch/arm/kernel/insn.c +++ b/arch/arm/kernel/insn.c @@ -1,3 +1,4 @@ +#include #include #include -- cgit v0.10.2 From 3248877ea1796915419fba7c89315fdbf00cb56a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 25 Nov 2011 15:21:02 +0000 Subject: drm: base prime/dma-buf support (v5) This adds the basic drm dma-buf interface layer, called PRIME. This commit doesn't add any driver support, it is simply and agreed upon starting point so we can work towards merging driver support for the next merge window. Current drivers with work done are nouveau, i915, udl, exynos and omap. The main APIs exposed to userspace allow translating a 32-bit object handle to a file descriptor, and a file descriptor to a 32-bit object handle. The flags value is currently limited to O_CLOEXEC. Acknowledgements: Daniel Vetter: lots of review Rob Clark: cleaned up lots of the internals and did lifetime review. v2: rename some functions after Chris preferred a green shed fix IS_ERR_OR_NULL -> IS_ERR v3: Fix Ville pointed out using buffer + kmalloc v4: add locking as per ickle review v5: allow re-exporting the original dma-buf (Daniel) Reviewed-by: Daniel Vetter Reviewed-by: Rob Clark Reviewed-by: Sumit Semwal Reviewed-by: Inki Dae Acked-by: Ben Widawsky Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index cc11488..e354bc0 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -9,6 +9,7 @@ menuconfig DRM depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU select I2C select I2C_ALGOBIT + select DMA_SHARED_BUFFER help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a858532..c20da5b 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -12,7 +12,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ - drm_trace_points.o drm_global.o + drm_trace_points.o drm_global.o drm_prime.o drm-$(CONFIG_COMPAT) += drm_ioc32.o diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 0b65fbc..6116e3b 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -136,6 +136,10 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), + + DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 7348a3d..cdfbf27 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -271,6 +271,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp, if (dev->driver->driver_features & DRIVER_GEM) drm_gem_open(dev, priv); + if (drm_core_check_feature(dev, DRIVER_PRIME)) + drm_prime_init_file_private(&priv->prime); + if (dev->driver->open) { ret = dev->driver->open(dev, priv); if (ret < 0) @@ -571,6 +574,10 @@ int drm_release(struct inode *inode, struct file *filp) if (dev->driver->postclose) dev->driver->postclose(dev, file_priv); + + if (drm_core_check_feature(dev, DRIVER_PRIME)) + drm_prime_destroy_file_private(&file_priv->prime); + kfree(file_priv); /* ======================================================== diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 0ef358e..83114b5 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "drmP.h" /** @file drm_gem.c @@ -232,6 +233,10 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); + if (obj->import_attach) + drm_prime_remove_imported_buf_handle(&filp->prime, + obj->import_attach->dmabuf); + if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, filp); drm_gem_object_handle_unreference_unlocked(obj); @@ -527,6 +532,10 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) struct drm_gem_object *obj = ptr; struct drm_device *dev = obj->dev; + if (obj->import_attach) + drm_prime_remove_imported_buf_handle(&file_priv->prime, + obj->import_attach->dmabuf); + if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c new file mode 100644 index 0000000..1bdf2b5 --- /dev/null +++ b/drivers/gpu/drm/drm_prime.c @@ -0,0 +1,304 @@ +/* + * Copyright © 2012 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Dave Airlie + * Rob Clark + * + */ + +#include +#include +#include "drmP.h" + +/* + * DMA-BUF/GEM Object references and lifetime overview: + * + * On the export the dma_buf holds a reference to the exporting GEM + * object. It takes this reference in handle_to_fd_ioctl, when it + * first calls .prime_export and stores the exporting GEM object in + * the dma_buf priv. This reference is released when the dma_buf + * object goes away in the driver .release function. + * + * On the import the importing GEM object holds a reference to the + * dma_buf (which in turn holds a ref to the exporting GEM object). + * It takes that reference in the fd_to_handle ioctl. + * It calls dma_buf_get, creates an attachment to it and stores the + * attachment in the GEM object. When this attachment is destroyed + * when the imported object is destroyed, we remove the attachment + * and drop the reference to the dma_buf. + * + * Thus the chain of references always flows in one direction + * (avoiding loops): importing_gem -> dmabuf -> exporting_gem + * + * Self-importing: if userspace is using PRIME as a replacement for flink + * then it will get a fd->handle request for a GEM object that it created. + * Drivers should detect this situation and return back the gem object + * from the dma-buf private. + */ + +struct drm_prime_member { + struct list_head entry; + struct dma_buf *dma_buf; + uint32_t handle; +}; + +int drm_gem_prime_handle_to_fd(struct drm_device *dev, + struct drm_file *file_priv, uint32_t handle, uint32_t flags, + int *prime_fd) +{ + struct drm_gem_object *obj; + void *buf; + + obj = drm_gem_object_lookup(dev, file_priv, handle); + if (!obj) + return -ENOENT; + + mutex_lock(&file_priv->prime.lock); + /* re-export the original imported object */ + if (obj->import_attach) { + get_dma_buf(obj->import_attach->dmabuf); + *prime_fd = dma_buf_fd(obj->import_attach->dmabuf, flags); + drm_gem_object_unreference_unlocked(obj); + mutex_unlock(&file_priv->prime.lock); + return 0; + } + + if (obj->export_dma_buf) { + get_dma_buf(obj->export_dma_buf); + *prime_fd = dma_buf_fd(obj->export_dma_buf, flags); + drm_gem_object_unreference_unlocked(obj); + } else { + buf = dev->driver->gem_prime_export(dev, obj, flags); + if (IS_ERR(buf)) { + /* normally the created dma-buf takes ownership of the ref, + * but if that fails then drop the ref + */ + drm_gem_object_unreference_unlocked(obj); + mutex_unlock(&file_priv->prime.lock); + return PTR_ERR(buf); + } + obj->export_dma_buf = buf; + *prime_fd = dma_buf_fd(buf, flags); + } + mutex_unlock(&file_priv->prime.lock); + return 0; +} +EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); + +int drm_gem_prime_fd_to_handle(struct drm_device *dev, + struct drm_file *file_priv, int prime_fd, uint32_t *handle) +{ + struct dma_buf *dma_buf; + struct drm_gem_object *obj; + int ret; + + dma_buf = dma_buf_get(prime_fd); + if (IS_ERR(dma_buf)) + return PTR_ERR(dma_buf); + + mutex_lock(&file_priv->prime.lock); + + ret = drm_prime_lookup_imported_buf_handle(&file_priv->prime, + dma_buf, handle); + if (!ret) { + ret = 0; + goto out_put; + } + + /* never seen this one, need to import */ + obj = dev->driver->gem_prime_import(dev, dma_buf); + if (IS_ERR(obj)) { + ret = PTR_ERR(obj); + goto out_put; + } + + ret = drm_gem_handle_create(file_priv, obj, handle); + drm_gem_object_unreference_unlocked(obj); + if (ret) + goto out_put; + + ret = drm_prime_add_imported_buf_handle(&file_priv->prime, + dma_buf, *handle); + if (ret) + goto fail; + + mutex_unlock(&file_priv->prime.lock); + return 0; + +fail: + /* hmm, if driver attached, we are relying on the free-object path + * to detach.. which seems ok.. + */ + drm_gem_object_handle_unreference_unlocked(obj); +out_put: + dma_buf_put(dma_buf); + mutex_unlock(&file_priv->prime.lock); + return ret; +} +EXPORT_SYMBOL(drm_gem_prime_fd_to_handle); + +int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_prime_handle *args = data; + uint32_t flags; + + if (!drm_core_check_feature(dev, DRIVER_PRIME)) + return -EINVAL; + + if (!dev->driver->prime_handle_to_fd) + return -ENOSYS; + + /* check flags are valid */ + if (args->flags & ~DRM_CLOEXEC) + return -EINVAL; + + /* we only want to pass DRM_CLOEXEC which is == O_CLOEXEC */ + flags = args->flags & DRM_CLOEXEC; + + return dev->driver->prime_handle_to_fd(dev, file_priv, + args->handle, flags, &args->fd); +} + +int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_prime_handle *args = data; + + if (!drm_core_check_feature(dev, DRIVER_PRIME)) + return -EINVAL; + + if (!dev->driver->prime_fd_to_handle) + return -ENOSYS; + + return dev->driver->prime_fd_to_handle(dev, file_priv, + args->fd, &args->handle); +} + +/* + * drm_prime_pages_to_sg + * + * this helper creates an sg table object from a set of pages + * the driver is responsible for mapping the pages into the + * importers address space + */ +struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages) +{ + struct sg_table *sg = NULL; + struct scatterlist *iter; + int i; + int ret; + + sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sg) + goto out; + + ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL); + if (ret) + goto out; + + for_each_sg(sg->sgl, iter, nr_pages, i) + sg_set_page(iter, pages[i], PAGE_SIZE, 0); + + return sg; +out: + kfree(sg); + return NULL; +} +EXPORT_SYMBOL(drm_prime_pages_to_sg); + +/* helper function to cleanup a GEM/prime object */ +void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) +{ + struct dma_buf_attachment *attach; + struct dma_buf *dma_buf; + attach = obj->import_attach; + if (sg) + dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); + dma_buf = attach->dmabuf; + dma_buf_detach(attach->dmabuf, attach); + /* remove the reference */ + dma_buf_put(dma_buf); +} +EXPORT_SYMBOL(drm_prime_gem_destroy); + +void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) +{ + INIT_LIST_HEAD(&prime_fpriv->head); + mutex_init(&prime_fpriv->lock); +} +EXPORT_SYMBOL(drm_prime_init_file_private); + +void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) +{ + struct drm_prime_member *member, *safe; + list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { + list_del(&member->entry); + kfree(member); + } +} +EXPORT_SYMBOL(drm_prime_destroy_file_private); + +int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) +{ + struct drm_prime_member *member; + + member = kmalloc(sizeof(*member), GFP_KERNEL); + if (!member) + return -ENOMEM; + + member->dma_buf = dma_buf; + member->handle = handle; + list_add(&member->entry, &prime_fpriv->head); + return 0; +} +EXPORT_SYMBOL(drm_prime_add_imported_buf_handle); + +int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle) +{ + struct drm_prime_member *member; + + list_for_each_entry(member, &prime_fpriv->head, entry) { + if (member->dma_buf == dma_buf) { + *handle = member->handle; + return 0; + } + } + return -ENOENT; +} +EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle); + +void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) +{ + struct drm_prime_member *member, *safe; + + mutex_lock(&prime_fpriv->lock); + list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { + if (member->dma_buf == dma_buf) { + list_del(&member->entry); + kfree(member); + } + } + mutex_unlock(&prime_fpriv->lock); +} +EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle); diff --git a/include/drm/drm.h b/include/drm/drm.h index 34a7b89..64ff02d 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -617,6 +617,17 @@ struct drm_get_cap { __u64 value; }; +#define DRM_CLOEXEC O_CLOEXEC +struct drm_prime_handle { + __u32 handle; + + /** Flags.. only applicable for handle->fd */ + __u32 flags; + + /** Returned dmabuf file descriptor */ + __s32 fd; +}; + #include "drm_mode.h" #define DRM_IOCTL_BASE 'd' @@ -673,7 +684,8 @@ struct drm_get_cap { #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) -#define DRM_IOCTL_GEM_PRIME_OPEN DRM_IOWR(0x2e, struct drm_gem_open) +#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) +#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) #define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 574bd1c..dd73104 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -91,6 +91,7 @@ struct drm_device; #define DRM_UT_CORE 0x01 #define DRM_UT_DRIVER 0x02 #define DRM_UT_KMS 0x04 +#define DRM_UT_PRIME 0x08 /* * Three debug levels are defined. * drm_core, drm_driver, drm_kms @@ -150,6 +151,7 @@ int drm_err(const char *func, const char *format, ...); #define DRIVER_IRQ_VBL2 0x800 #define DRIVER_GEM 0x1000 #define DRIVER_MODESET 0x2000 +#define DRIVER_PRIME 0x4000 #define DRIVER_BUS_PCI 0x1 #define DRIVER_BUS_PLATFORM 0x2 @@ -215,6 +217,11 @@ int drm_err(const char *func, const char *format, ...); drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME, \ __func__, fmt, ##args); \ } while (0) +#define DRM_DEBUG_PRIME(fmt, args...) \ + do { \ + drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME, \ + __func__, fmt, ##args); \ + } while (0) #define DRM_LOG(fmt, args...) \ do { \ drm_ut_debug_printk(DRM_UT_CORE, NULL, \ @@ -238,6 +245,7 @@ int drm_err(const char *func, const char *format, ...); #else #define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0) #define DRM_DEBUG_KMS(fmt, args...) do { } while (0) +#define DRM_DEBUG_PRIME(fmt, args...) do { } while (0) #define DRM_DEBUG(fmt, arg...) do { } while (0) #define DRM_LOG(fmt, arg...) do { } while (0) #define DRM_LOG_KMS(fmt, args...) do { } while (0) @@ -410,6 +418,12 @@ struct drm_pending_event { void (*destroy)(struct drm_pending_event *event); }; +/* initial implementaton using a linked list - todo hashtab */ +struct drm_prime_file_private { + struct list_head head; + struct mutex lock; +}; + /** File private data */ struct drm_file { int authenticated; @@ -437,6 +451,8 @@ struct drm_file { wait_queue_head_t event_wait; struct list_head event_list; int event_space; + + struct drm_prime_file_private prime; }; /** Wait queue */ @@ -652,6 +668,12 @@ struct drm_gem_object { uint32_t pending_write_domain; void *driver_private; + + /* dma buf exported from this GEM object */ + struct dma_buf *export_dma_buf; + + /* dma buf attachment backing this object */ + struct dma_buf_attachment *import_attach; }; #include "drm_crtc.h" @@ -890,6 +912,20 @@ struct drm_driver { int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); + /* prime: */ + /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */ + int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd); + /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */ + int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, + int prime_fd, uint32_t *handle); + /* export GEM -> dmabuf */ + struct dma_buf * (*gem_prime_export)(struct drm_device *dev, + struct drm_gem_object *obj, int flags); + /* import dmabuf -> GEM */ + struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, + struct dma_buf *dma_buf); + /* vga arb irq handler */ void (*vgaarb_irq)(struct drm_device *dev, bool state); @@ -1509,6 +1545,32 @@ extern int drm_vblank_info(struct seq_file *m, void *data); extern int drm_clients_info(struct seq_file *m, void* data); extern int drm_gem_name_info(struct seq_file *m, void *data); + +extern int drm_gem_prime_handle_to_fd(struct drm_device *dev, + struct drm_file *file_priv, uint32_t handle, uint32_t flags, + int *prime_fd); +extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, + struct drm_file *file_priv, int prime_fd, uint32_t *handle); + +extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages); +extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); + + +void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv); +void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv); +int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle); +int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle); +void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf); + +int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj); +int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf, + struct drm_gem_object **obj); + #if DRM_DEBUG_CODE extern int drm_vma_info(struct seq_file *m, void *data); #endif -- cgit v0.10.2 From 5a4f5da543b169d555a19e889850780ddceb8f98 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 21 Feb 2012 12:29:03 +0100 Subject: ARM: 7337/1: ptrace: fix ptrace_read_user for !CONFIG_MMU platforms Commit 68b7f715 ("nommu: ptrace support") added definitions for PT_TEXT_ADDR and friends, as well as adding ptrace support for reading from these magic offsets. Unfortunately, this has probably never worked, since ptrace_read_user predicates reading on off < sizeof(struct user), returning -EIO otherwise. This patch moves the offset size check until after we have tried to match it against either a magic value or an offset into pt_regs. Cc: Paul Brook Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 45956c9..80abafb 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -256,7 +256,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, { unsigned long tmp; - if (off & 3 || off >= sizeof(struct user)) + if (off & 3) return -EIO; tmp = 0; @@ -268,6 +268,8 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, tmp = tsk->mm->end_code; else if (off < sizeof(struct pt_regs)) tmp = get_user_reg(tsk, off >> 2); + else if (off >= sizeof(struct user)) + return -EIO; return put_user(tmp, ret); } -- cgit v0.10.2 From c0e9afc0da6cb0f11497e5ea83377b3c451450e0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 28 Mar 2012 11:51:17 -0700 Subject: x86: Use -mno-avx when available On gccs that support AVX it's a good idea to disable that too, similar to how SSE2, SSE1 etc. are already disabled. This prevents the compiler from generating AVX ever implicitely. No failure observed, just from review. [ hpa: Marking this for urgent and stable, simply because the patch will either have absolutely no effect *or* it will avoid potentially very hard to debug failures. ] Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1332960678-11879-1-git-send-email-andi@firstfloor.org Signed-off-by: H. Peter Anvin Cc: diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 968dbe2..41a7237 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -129,6 +129,7 @@ KBUILD_CFLAGS += -Wno-sign-compare KBUILD_CFLAGS += -fno-asynchronous-unwind-tables # prevent gcc from generating any FP code by mistake KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) +KBUILD_CFLAGS += $(call cc-option,-mno-avx,) KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) -- cgit v0.10.2 From 3eb8d7099064ae61fa821d690d085abb8b7c4810 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 30 Mar 2012 21:03:54 +0100 Subject: ARM: fix bios32.c build warning arch/arm/kernel/bios32.c: In function 'pcibios_fixup_bus': arch/arm/kernel/bios32.c:302: warning: unused variable 'root' caused by 9f786d033 (arm/PCI: get rid of device resource fixups) Signed-off-by: Russell King diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 632df9a..ede5f77 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -299,7 +299,6 @@ static inline int pdev_bad_for_parity(struct pci_dev *dev) */ void pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_sys_data *root = bus->sysdata; struct pci_dev *dev; u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK; -- cgit v0.10.2 From 6d008893e45ad5957a9a31afa00c4c6582504fe5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 31 Mar 2012 09:07:30 +0100 Subject: ARM: fix more fallout from 9f97da78bf (Disintegrate asm/system.h for ARM) arch/arm/kernel/io.c: In function '_memcpy_toio': arch/arm/kernel/io.c:29: error: implicit declaration of function 'outer_sync' arch/arm/mach-omap2/omap_l3_noc.c: In function 'l3_interrupt_handler': arch/arm/mach-omap2/omap_l3_noc.c:100: error: implicit declaration of function 'outer_sync' kernel/irq/generic-chip.c: In function 'irq_gc_mask_disable_reg': kernel/irq/generic-chip.c:45: error: implicit declaration of function 'outer_sync' kernel/sched/rt.c: In function 'rt_set_overload': kernel/sched/rt.c:248: error: implicit declaration of function 'outer_sync' ... Signed-off-by: Russell King diff --git a/arch/arm/mach-omap2/include/mach/barriers.h b/arch/arm/mach-omap2/include/mach/barriers.h index 4fa72c7..1c582a8 100644 --- a/arch/arm/mach-omap2/include/mach/barriers.h +++ b/arch/arm/mach-omap2/include/mach/barriers.h @@ -22,6 +22,8 @@ #ifndef __MACH_BARRIERS_H #define __MACH_BARRIERS_H +#include + extern void omap_bus_sync(void); #define rmb() dsb() -- cgit v0.10.2 From 6308191f6f55d3629c7dbe72dfb856ad9fa560fd Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 30 Mar 2012 18:26:36 +0200 Subject: tracing, sched, vfs: Fix 'old_pid' usage in trace_sched_process_exec() 1. TRACE_EVENT(sched_process_exec) forgets to actually use the old pid argument, it sets ->old_pid = p->pid. 2. search_binary_handler() uses the wrong pid number. tracepoint needs the global pid_t from the root namespace, while old_pid is the virtual pid number as it seen by the tracer/parent. With this patch we have two pid_t's in search_binary_handler(), not really nice. Perhaps we should switch to "struct pid*", but in this case it would be better to cleanup the current code first and move the "depth == 0" code outside. Signed-off-by: Oleg Nesterov Cc: David Smith Cc: Peter Zijlstra Cc: Steven Rostedt Cc: Denys Vlasenko Link: http://lkml.kernel.org/r/20120330162636.GA4857@redhat.com Signed-off-by: Ingo Molnar diff --git a/fs/exec.c b/fs/exec.c index 23559c2..644f6c4 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1370,7 +1370,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) unsigned int depth = bprm->recursion_depth; int try,retval; struct linux_binfmt *fmt; - pid_t old_pid; + pid_t old_pid, old_vpid; retval = security_bprm_check(bprm); if (retval) @@ -1381,8 +1381,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) return retval; /* Need to fetch pid before load_binary changes it */ + old_pid = current->pid; rcu_read_lock(); - old_pid = task_pid_nr_ns(current, task_active_pid_ns(current->parent)); + old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent)); rcu_read_unlock(); retval = -ENOENT; @@ -1405,7 +1406,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) if (retval >= 0) { if (depth == 0) { trace_sched_process_exec(current, old_pid, bprm); - ptrace_event(PTRACE_EVENT_EXEC, old_pid); + ptrace_event(PTRACE_EVENT_EXEC, old_vpid); } put_binfmt(fmt); allow_write_access(bprm->file); diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index fbc7b1a..ea7a203 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -295,7 +295,7 @@ TRACE_EVENT(sched_process_exec, TP_fast_assign( __assign_str(filename, bprm->filename); __entry->pid = p->pid; - __entry->old_pid = p->pid; + __entry->old_pid = old_pid; ), TP_printk("filename=%s pid=%d old_pid=%d", __get_str(filename), -- cgit v0.10.2 From 5f12760d289fd2da685cb54eebb08c107b146872 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 31 Mar 2012 16:33:31 +0800 Subject: regulator: fix sysfs name collision between dummy and fixed dummy regulator When regulator_register_fixed() is being used to register fixed dummy regulator, the following line will be seen in the boot log. And the sysfs entry for fixed dummy regulator is not shown. dummy: Failed to create debugfs directory The patch renames the fixed dummy supply to "fixed-dummy" to avoid the name collision with dummy regulator. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c index 30d0a15..efb52dc 100644 --- a/drivers/regulator/fixed-helper.c +++ b/drivers/regulator/fixed-helper.c @@ -32,7 +32,7 @@ struct platform_device *regulator_register_fixed(int id, if (!data) return NULL; - data->cfg.supply_name = "dummy"; + data->cfg.supply_name = "fixed-dummy"; data->cfg.microvolts = 0; data->cfg.gpio = -EINVAL; data->cfg.enabled_at_boot = 1; -- cgit v0.10.2 From 546e78452a3f81eb45ae5c671c71db05389d42c8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 19 Mar 2012 12:22:10 +0800 Subject: regulator: Fix setting new voltage in s5m8767_set_voltage Current code does not really update the register with new value, fix it. I rename the variable i to sel for better readability. Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 58447db..4ca2db0 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -311,8 +311,7 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); const struct s5m_voltage_desc *desc; int reg_id = rdev_get_id(rdev); - int reg, mask, ret; - int i; + int sel, reg, mask, ret; u8 val; switch (reg_id) { @@ -333,19 +332,20 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, desc = reg_voltage_map[reg_id]; - i = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); - if (i < 0) - return i; + sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); + if (sel < 0) + return sel; ret = s5m8767_get_voltage_register(rdev, ®); if (ret) return ret; s5m_reg_read(s5m8767->iodev, reg, &val); - val = val & mask; + val &= ~mask; + val |= sel; ret = s5m_reg_write(s5m8767->iodev, reg, val); - *selector = i; + *selector = sel; return ret; } -- cgit v0.10.2 From d49fe3c4cd22965de7422dd81d46110fc3d4deef Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Wed, 21 Mar 2012 22:19:45 -0700 Subject: regulator: Remove non-existent parameter from fixed-helper.c kernel doc Signed-off-by: Russ Dill Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c index efb52dc..cacd33c 100644 --- a/drivers/regulator/fixed-helper.c +++ b/drivers/regulator/fixed-helper.c @@ -18,7 +18,6 @@ static void regulator_fixed_release(struct device *dev) /** * regulator_register_fixed - register a no-op fixed regulator - * @name: supply name * @id: platform device id * @supplies: consumers for this regulator * @num_supplies: number of consumers -- cgit v0.10.2 From b5efb978469d152c2c7c0a09746fb0bfc6171868 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Tue, 27 Mar 2012 15:36:15 +0400 Subject: CIFS: Fix VFS lock usage for oplocked files We can deadlock if we have a write oplock and two processes use the same file handle. In this case the first process can't unlock its lock if another process blocked on the lock in the same time. Fix this by removing lock_mutex protection from waiting on a blocked lock and protect only posix_lock_file call. Cc: stable@kernel.org Signed-off-by: Pavel Shilovsky Acked-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 460d87b..0a11dbb 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -671,6 +671,21 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock) } } +/* + * Copied from fs/locks.c with small changes. + * Remove waiter from blocker's block list. + * When blocker ends up pointing to itself then the list is empty. + */ +static void +cifs_locks_delete_block(struct file_lock *waiter) +{ + lock_flocks(); + list_del_init(&waiter->fl_block); + list_del_init(&waiter->fl_link); + waiter->fl_next = NULL; + unlock_flocks(); +} + static bool __cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, __u8 type, __u16 netfid, @@ -820,6 +835,39 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) return rc; } +/* Called with locked lock_mutex, return with unlocked. */ +static int +cifs_posix_lock_file_wait_locked(struct file *file, struct file_lock *flock) +{ + struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); + int rc; + + while (true) { + rc = posix_lock_file(file, flock, NULL); + mutex_unlock(&cinode->lock_mutex); + if (rc != FILE_LOCK_DEFERRED) + break; + rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); + if (!rc) { + mutex_lock(&cinode->lock_mutex); + continue; + } + cifs_locks_delete_block(flock); + break; + } + return rc; +} + +static int +cifs_posix_lock_file_wait(struct file *file, struct file_lock *flock) +{ + struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); + + mutex_lock(&cinode->lock_mutex); + /* lock_mutex will be released by the function below */ + return cifs_posix_lock_file_wait_locked(file, flock); +} + /* * Set the byte-range lock (posix style). Returns: * 1) 0, if we set the lock and don't need to request to the server; @@ -840,9 +888,9 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) mutex_unlock(&cinode->lock_mutex); return rc; } - rc = posix_lock_file_wait(file, flock); - mutex_unlock(&cinode->lock_mutex); - return rc; + + /* lock_mutex will be released by the function below */ + return cifs_posix_lock_file_wait_locked(file, flock); } static int @@ -1338,7 +1386,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, out: if (flock->fl_flags & FL_POSIX) - posix_lock_file_wait(file, flock); + cifs_posix_lock_file_wait(file, flock); return rc; } -- cgit v0.10.2 From b2a3ad9ca502169fc4c11296fa20f56059c7c031 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 26 Mar 2012 09:55:29 -0400 Subject: cifs: silence compiler warnings showing up with gcc-4.7.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc-4.7.0 has started throwing these warnings when building cifs.ko. CC [M] fs/cifs/cifssmb.o fs/cifs/cifssmb.c: In function ‘CIFSSMBSetCIFSACL’: fs/cifs/cifssmb.c:3905:9: warning: array subscript is above array bounds [-Warray-bounds] fs/cifs/cifssmb.c: In function ‘CIFSSMBSetFileInfo’: fs/cifs/cifssmb.c:5711:8: warning: array subscript is above array bounds [-Warray-bounds] fs/cifs/cifssmb.c: In function ‘CIFSSMBUnixSetFileInfo’: fs/cifs/cifssmb.c:6001:25: warning: array subscript is above array bounds [-Warray-bounds] This patch cleans up the code a bit by using the offsetof macro instead of the funky "&pSMB->hdr.Protocol" construct. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 8fecc99..f52c5ab 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3892,13 +3892,12 @@ CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, int rc = 0; int bytes_returned = 0; SET_SEC_DESC_REQ *pSMB = NULL; - NTRANSACT_RSP *pSMBr = NULL; + void *pSMBr; setCifsAclRetry: - rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr); if (rc) - return (rc); + return rc; pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; @@ -3926,9 +3925,8 @@ setCifsAclRetry: pSMB->AclFlags = cpu_to_le32(aclflag); if (pntsd && acllen) { - memcpy((char *) &pSMBr->hdr.Protocol + data_offset, - (char *) pntsd, - acllen); + memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) + + data_offset, pntsd, acllen); inc_rfc1001_len(pSMB, byte_count + data_count); } else inc_rfc1001_len(pSMB, byte_count); @@ -5708,7 +5706,8 @@ CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + data_offset = (char *)pSMB + + offsetof(struct smb_hdr, Protocol) + offset; count = sizeof(FILE_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); @@ -5977,7 +5976,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, u16 fid, u32 pid_of_opener) { struct smb_com_transaction2_sfi_req *pSMB = NULL; - FILE_UNIX_BASIC_INFO *data_offset; + char *data_offset; int rc = 0; u16 params, param_offset, offset, byte_count, count; @@ -5999,8 +5998,9 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (FILE_UNIX_BASIC_INFO *) - ((char *)(&pSMB->hdr.Protocol) + offset); + data_offset = (char *)pSMB + + offsetof(struct smb_hdr, Protocol) + offset; + count = sizeof(FILE_UNIX_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); @@ -6022,7 +6022,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, inc_rfc1001_len(pSMB, byte_count); pSMB->ByteCount = cpu_to_le16(byte_count); - cifs_fill_unix_set_info(data_offset, args); + cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args); rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); if (rc) -- cgit v0.10.2 From 2545e0720a5a4bf8ebccc6f793f97a246cf3f18d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 1 Mar 2012 10:06:52 +0300 Subject: cifs: writing past end of struct in cifs_convert_address() "s6->sin6_scope_id" is an int bits but strict_strtoul() writes a long so this can corrupt memory on 64 bit systems. Signed-off-by: Dan Carpenter Reviewed-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index dd23a32..581c225 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -197,8 +197,7 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) memcpy(scope_id, pct + 1, slen); scope_id[slen] = '\0'; - rc = strict_strtoul(scope_id, 0, - (unsigned long *)&s6->sin6_scope_id); + rc = kstrtouint(scope_id, 0, &s6->sin6_scope_id); rc = (rc == 0) ? 1 : 0; } -- cgit v0.10.2 From f47166d2b0001fcb752b40c5a2d4db986dfbea68 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Mar 2012 15:00:50 +0000 Subject: drm/i915: Sanitize BIOS debugging bits from PIPECONF Quoting the BSpec from time immemorial: PIPEACONF, bits 28:27: Frame Start Delay (Debug) Used to delay the frame start signal that is sent to the display planes. Care must be taken to insure that there are enough lines during VBLANK to support this setting. An instance of the BIOS leaving these bits set was found in the wild, where it caused our modesetting to go all squiffy and skewiff. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47271 Reported-and-tested-by: Eva Wang Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43012 Reported-and-tested-by: Carl Richell Cc: stable@kernel.org Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3886cf0..2abf4eb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2385,6 +2385,7 @@ #define PIPECONF_DISABLE 0 #define PIPECONF_DOUBLE_WIDE (1<<30) #define I965_PIPECONF_ACTIVE (1<<30) +#define PIPECONF_FRAME_START_DELAY_MASK (3<<27) #define PIPECONF_SINGLE_WIDE 0 #define PIPECONF_PIPE_UNLOCKED 0 #define PIPECONF_PIPE_LOCKED (1<<25) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d514719..0784773 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7580,6 +7580,12 @@ static void intel_sanitize_modesetting(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; u32 reg, val; + /* Clear any frame start delays used for debugging left by the BIOS */ + for_each_pipe(pipe) { + reg = PIPECONF(pipe); + I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); + } + if (HAS_PCH_SPLIT(dev)) return; -- cgit v0.10.2 From 55a254ac63a3ac1867d1501030e7fba69c7d4aeb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 22 Mar 2012 00:14:43 +0100 Subject: drm/i915: properly restore the ppgtt page directory on resume The ppgtt page directory lives in a snatched part of the gtt pte range. Which naturally gets cleared on hibernate when we pull the power. Suspend to ram (which is what I've tested) works because despite the fact that this is a mmio region, it is actually back by system ram. Fix this by moving the page directory setup code to the ppgtt init code (which gets called on resume). This fixes hibernate on my ivb and snb. Reviewed-by: Ben Widawsky Signed-Off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1f441f5..97e6599 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3754,12 +3754,32 @@ void i915_gem_init_ppgtt(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; uint32_t pd_offset; struct intel_ring_buffer *ring; + struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; + uint32_t __iomem *pd_addr; + uint32_t pd_entry; int i; if (!dev_priv->mm.aliasing_ppgtt) return; - pd_offset = dev_priv->mm.aliasing_ppgtt->pd_offset; + + pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t); + for (i = 0; i < ppgtt->num_pd_entries; i++) { + dma_addr_t pt_addr; + + if (dev_priv->mm.gtt->needs_dmar) + pt_addr = ppgtt->pt_dma_addr[i]; + else + pt_addr = page_to_phys(ppgtt->pt_pages[i]); + + pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); + pd_entry |= GEN6_PDE_VALID; + + writel(pd_entry, pd_addr + i); + } + readl(pd_addr); + + pd_offset = ppgtt->pd_offset; pd_offset /= 64; /* in cachelines, */ pd_offset <<= 16; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2eacd78..a135c61 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -65,9 +65,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_ppgtt *ppgtt; - uint32_t pd_entry; unsigned first_pd_entry_in_global_pt; - uint32_t __iomem *pd_addr; int i; int ret = -ENOMEM; @@ -100,7 +98,6 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) goto err_pt_alloc; } - pd_addr = dev_priv->mm.gtt->gtt + first_pd_entry_in_global_pt; for (i = 0; i < ppgtt->num_pd_entries; i++) { dma_addr_t pt_addr; if (dev_priv->mm.gtt->needs_dmar) { @@ -117,13 +114,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) ppgtt->pt_dma_addr[i] = pt_addr; } else pt_addr = page_to_phys(ppgtt->pt_pages[i]); - - pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); - pd_entry |= GEN6_PDE_VALID; - - writel(pd_entry, pd_addr + i); } - readl(pd_addr); ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma; -- cgit v0.10.2 From 7dd4906586274f3945f2aeaaa5a33b451c3b4bba Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Mar 2012 10:48:18 +0000 Subject: drm/i915: Mark untiled BLT commands as fenced on gen2/3 The BLT commands on gen2/3 utilize the fence registers and so we cannot modify any fences for the object whilst those commands are in flight. Currently we marked tiled commands as occupying a fence, but forgot to restrict the untiled commands from preventing a fence being assigned before they were completed. One side-effect is that we ten have to double check that a fence was allocated for a fenced buffer during move-to-active. Reported-by: Jiri Slaby Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=43427 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47990 Reviewed-by: Daniel Vetter Testcase: i-g-t/tests/gem_tiled_after_untiled_blt Tested-by: Daniel Vetter Signed-off-by: Chris Wilson Cc: stable@kernel.org Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 97e6599..4c65c63 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1472,16 +1472,19 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, list_move_tail(&obj->ring_list, &ring->active_list); obj->last_rendering_seqno = seqno; - if (obj->fenced_gpu_access) { - struct drm_i915_fence_reg *reg; - - BUG_ON(obj->fence_reg == I915_FENCE_REG_NONE); + if (obj->fenced_gpu_access) { obj->last_fenced_seqno = seqno; obj->last_fenced_ring = ring; - reg = &dev_priv->fence_regs[obj->fence_reg]; - list_move_tail(®->lru_list, &dev_priv->mm.fence_list); + /* Bump MRU to take account of the delayed flush */ + if (obj->fence_reg != I915_FENCE_REG_NONE) { + struct drm_i915_fence_reg *reg; + + reg = &dev_priv->fence_regs[obj->fence_reg]; + list_move_tail(®->lru_list, + &dev_priv->mm.fence_list); + } } } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 81687af..f51a696 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -498,8 +498,8 @@ pin_and_fence_object(struct drm_i915_gem_object *obj, if (ret) goto err_unpin; } + obj->pending_fenced_gpu_access = true; } - obj->pending_fenced_gpu_access = need_fence; } entry->offset = obj->gtt_offset; -- cgit v0.10.2 From 83b7f9ac9126f0532ca34c14e4f0582c565c6b0d Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Fri, 23 Mar 2012 11:57:18 -0300 Subject: drm/i915: allow to select rc6 modes via kernel parameter This allows to select which rc6 modes are to be used via kernel parameter, via a bitmask parameter. E.g.: - to enable rc6, i915_enable_rc6=1 - to enable rc6 and deep rc6, i915_enable_rc6=3 - to enable rc6 and deepest rc6, use i915_enable_rc6=5 - to enable rc6, deep and deepest rc6, use i915_enable_rc6=7 Please keep in mind that the deepest RC6 state really should NOT be used by default, as it could potentially worsen the issues with deep RC6. So do enable it only when you know what you are doing. However, having it around could help solving possible future rc6-related issues and their debugging on user machines. Note that this changes behavior - previously, value of 1 would enable both RC6 and deep RC6. Now it should only enable RC6 and deep/deepest RC6 stages must be enabled manually. v2: address Chris Wilson comments and clean up the code. References: https://bugs.freedesktop.org/show_bug.cgi?id=42579 Reviewed-by: Chris Wilson Reviewed-by: Ben Widawsky Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1a7559b..c7d689e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -66,7 +66,11 @@ MODULE_PARM_DESC(semaphores, int i915_enable_rc6 __read_mostly = -1; module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); MODULE_PARM_DESC(i915_enable_rc6, - "Enable power-saving render C-state 6 (default: -1 (use per-chip default)"); + "Enable power-saving render C-state 6. " + "Different stages can be selected via bitmask values " + "(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). " + "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " + "default: -1 (use per-chip default)"); int i915_enable_fbc __read_mostly = -1; module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c0f19f5..2c19227 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1053,6 +1053,27 @@ struct drm_i915_file_private { #include "i915_trace.h" +/** + * RC6 is a special power stage which allows the GPU to enter an very + * low-voltage mode when idle, using down to 0V while at this stage. This + * stage is entered automatically when the GPU is idle when RC6 support is + * enabled, and as soon as new workload arises GPU wakes up automatically as well. + * + * There are different RC6 modes available in Intel GPU, which differentiate + * among each other with the latency required to enter and leave RC6 and + * voltage consumed by the GPU in different states. + * + * The combination of the following flags define which states GPU is allowed + * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and + * RC6pp is deepest RC6. Their support by hardware varies according to the + * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one + * which brings the most power savings; deeper states save more power, but + * require higher latency to switch to and wake up. + */ +#define INTEL_RC6_ENABLE (1<<0) +#define INTEL_RC6p_ENABLE (1<<1) +#define INTEL_RC6pp_ENABLE (1<<2) + extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc __always_unused; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0784773..a0a4e3b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8221,7 +8221,7 @@ void intel_init_emon(struct drm_device *dev) dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); } -static bool intel_enable_rc6(struct drm_device *dev) +static int intel_enable_rc6(struct drm_device *dev) { /* * Respect the kernel parameter if it is set @@ -8253,6 +8253,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) u32 pcu_mbox, rc6_mask = 0; u32 gtfifodbg; int cur_freq, min_freq, max_freq; + int rc6_mode; int i; /* Here begins a magic sequence of register writes to enable @@ -8290,9 +8291,20 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ - if (intel_enable_rc6(dev_priv->dev)) - rc6_mask = GEN6_RC_CTL_RC6_ENABLE | - ((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0); + rc6_mode = intel_enable_rc6(dev_priv->dev); + if (rc6_mode & INTEL_RC6_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; + + if (rc6_mode & INTEL_RC6p_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; + + if (rc6_mode & INTEL_RC6pp_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; + + DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", + (rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off", + (rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off", + (rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off"); I915_WRITE(GEN6_RC_CONTROL, rc6_mask | -- cgit v0.10.2 From aa46419186992e6b8b8010319f0ca7f40a0d13f5 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Fri, 23 Mar 2012 11:57:19 -0300 Subject: drm/i915: enable plain RC6 on Sandy Bridge by default This is yet another chapter in the ongoing saga of bringing RC6 to Sandy Bridge machines by default. Now that we have discovered that RC6 issues are triggered by RC6+ state, let's try to disable it by default. Plain RC6 is the one responsible for most energy savings, and so far it haven't given any problems - at least, none we are aware of. So with this, when i915_enable_rc6=-1 (e.g., the default value), we'll attempt to enable plain RC6 only on SNB. For Ivy Bridge, the behavior stays the same as always - we enable both RC6 and deep RC6. Note that while this exact patch does not has explicit tested-by's, the equivalent settings were fixed in 3.3 kernel by a smaller patch. And it has also received considerable testing through Canonical RC6 task-force testing at https://wiki.ubuntu.com/Kernel/PowerManagementRC6. Up to date, it looks like all the known issues are gone. v2: improve description and reference a couple of open bugs related to RC6 which seem to be fixed with this change. References: https://bugs.freedesktop.org/show_bug.cgi?id=41682 References: https://bugs.freedesktop.org/show_bug.cgi?id=38567 References: https://bugs.freedesktop.org/show_bug.cgi?id=44867 Acked-by: Chris Wilson Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a0a4e3b..ec6ea92 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8239,11 +8239,11 @@ static int intel_enable_rc6(struct drm_device *dev) * Disable rc6 on Sandybridge */ if (INTEL_INFO(dev)->gen == 6) { - DRM_DEBUG_DRIVER("Sandybridge: RC6 disabled\n"); - return 0; + DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); + return INTEL_RC6_ENABLE; } - DRM_DEBUG_DRIVER("RC6 enabled\n"); - return 1; + DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); + return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); } void gen6_enable_rps(struct drm_i915_private *dev_priv) -- cgit v0.10.2 From 25e341cfc33d94435472983825163e97fe370a6c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 24 Mar 2012 23:51:30 +0100 Subject: drm/i915: quirk away broken OpRegion VBT Somehow the BIOS manages to screw things up when copying the VBT around, because the one we scrap from the VBIOS rom actually works. Cc: stable@kernel.org Tested-by: Markus Heinz Acked-by: Chris Wilson Reviewed-by: Rodrigo Vivi Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=28812 Signed-Off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 8168d8f..b48fc2a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -24,6 +24,7 @@ * Eric Anholt * */ +#include #include #include "drmP.h" #include "drm.h" @@ -621,6 +622,26 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) dev_priv->edp.bpp = 18; } +static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) +{ + DRM_DEBUG_KMS("Falling back to manually reading VBT from " + "VBIOS ROM for %s\n", + id->ident); + return 1; +} + +static const struct dmi_system_id intel_no_opregion_vbt[] = { + { + .callback = intel_no_opregion_vbt_callback, + .ident = "ThinkCentre A57", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"), + }, + }, + { } +}; + /** * intel_parse_bios - find VBT and initialize settings from the BIOS * @dev: DRM device @@ -641,7 +662,7 @@ intel_parse_bios(struct drm_device *dev) init_vbt_defaults(dev_priv); /* XXX Should this validation be moved to intel_opregion.c? */ - if (dev_priv->opregion.vbt) { + if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) { struct vbt_header *vbt = dev_priv->opregion.vbt; if (memcmp(vbt->signature, "$VBT", 4) == 0) { DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n", -- cgit v0.10.2 From 1c7eaac737e4cca24703531ebcb566afc3ed285f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 27 Mar 2012 09:31:24 +0200 Subject: drm/i915: apply CS reg readback trick against missed IRQ on snb Ben Widawsky reported missed IRQ issues and this patch here helps. We have one other missed IRQ report still left on snb, reported by QA: https://bugs.freedesktop.org/show_bug.cgi?id=46145 This is _not_ a regression due to the forcewake voodoo though, it started showing up before that was applied and has been on-and-off for the past few weeks. According to QA this patch does not help. But the missed IRQ is always from the blt ring (despite running piglit, so also render activity expected), so I'm hopefully that this is an issue with the blt ring itself. Tested-by: Ben Widawsky Signed-Off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index fc66af6..e25581a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -626,7 +626,7 @@ gen6_ring_get_seqno(struct intel_ring_buffer *ring) /* Workaround to force correct ordering between irq and seqno writes on * ivb (and maybe also on snb) by reading from a CS register (like * ACTHD) before reading the status page. */ - if (IS_GEN7(dev)) + if (IS_GEN6(dev) || IS_GEN7(dev)) intel_ring_get_active_head(ring); return intel_read_status_page(ring, I915_GEM_HWS_INDEX); } -- cgit v0.10.2 From e77166b5a653728f312d07e60a80819d1c54fca4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 30 Mar 2012 22:14:05 +0200 Subject: drm/i915: properly clear SSC1 bit in the pch refclock init code Noticed by staring at intel_reg_dumper diffs. Unfortunately it does not seem to completely fix the bug. Still, it's good to get this right, and maybe it helps someplace else. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47117 Signed-Off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ec6ea92..91b35fd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5539,7 +5539,8 @@ void ironlake_init_pch_refclk(struct drm_device *dev) if (intel_panel_use_ssc(dev_priv) && can_ssc) { DRM_DEBUG_KMS("Using SSC on panel\n"); temp |= DREF_SSC1_ENABLE; - } + } else + temp &= ~DREF_SSC1_ENABLE; /* Get SSC going before enabling the outputs */ I915_WRITE(PCH_DREF_CONTROL, temp); -- cgit v0.10.2 From 4b4e9e43fd210e0cd2a5d29357e7c000e13e08ae Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Mar 2012 11:04:57 +0100 Subject: regmap: rbtree: Fix register default look-up in sync The code currently passes the register offset in the current block to regcache_lookup_reg. This works fine as long as there is only one block and with base register of 0, but in all other cases it will look-up the default for a wrong register, which can cause unnecessary register writes. This patch fixes it by passing the actual register number to regcache_lookup_reg. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 5157fa0..fb14a63 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -396,7 +396,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min, map->cache_word_size); /* Is this the hardware default? If so skip. */ - ret = regcache_lookup_reg(map, i); + ret = regcache_lookup_reg(map, regtmp); if (ret >= 0 && val == map->reg_defaults[ret].def) continue; -- cgit v0.10.2 From c1a1260244d8ffe017fbb3199f65c842e4d42fe6 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 20 Mar 2012 23:06:34 -0400 Subject: hwmon: (gpio-fan) Fix Kconfig dependencies gpio-fan depends on GPIOLIB, not on GENERIC_GPIO. This fixes the following build error, seen if GPIOLIB is not defined: src/drivers/hwmon/gpio-fan.c: error: implicit declaration of function 'gpio_direction_output': => 372:3 src/drivers/hwmon/gpio-fan.c: error: implicit declaration of function 'gpio_free': => 130:2 src/drivers/hwmon/gpio-fan.c: error: implicit declaration of function 'gpio_get_value': => 79:2 src/drivers/hwmon/gpio-fan.c: error: implicit declaration of function 'gpio_request': => 98:2 src/drivers/hwmon/gpio-fan.c: error: implicit declaration of function 'gpio_set_value': => 156:3 src/drivers/hwmon/gpio-fan.c: error: implicit declaration of function 'gpio_to_irq': => 114:2 Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Acked-by: Simon Guinot diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5b32d56..496f80d 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -425,7 +425,7 @@ config SENSORS_GL520SM config SENSORS_GPIO_FAN tristate "GPIO fan" - depends on GENERIC_GPIO + depends on GPIOLIB help If you say yes here you get support for fans connected to GPIO lines. -- cgit v0.10.2 From be45d422d96ba22ecd0e34690644099d172e9c6d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 20 Mar 2012 23:06:35 -0400 Subject: hwmon: (sht15) Fix Kconfig dependencies sht15 depends on GPIOLIB, not on GENERIC_GPIO. This fixes the following build error, seen if GPIOLIB is not defined: src/drivers/hwmon/sht15.c: error: implicit declaration of function 'gpio_direction_input': => 293:2 src/drivers/hwmon/sht15.c: error: implicit declaration of function 'gpio_direction_output': => 216:2 src/drivers/hwmon/sht15.c: error: implicit declaration of function 'gpio_free': => 1000:2 src/drivers/hwmon/sht15.c: error: implicit declaration of function 'gpio_get_value': => 296:2 src/drivers/hwmon/sht15.c: error: implicit declaration of function 'gpio_request': => 946:2 src/drivers/hwmon/sht15.c: error: implicit declaration of function 'gpio_set_value': => 218:2 src/drivers/hwmon/sht15.c: error: implicit declaration of function 'gpio_to_irq': => 514:2 Signed-off-by: Guenter Roeck Acked-by: Jean Delvare diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 496f80d..670f274 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -883,7 +883,7 @@ source drivers/hwmon/pmbus/Kconfig config SENSORS_SHT15 tristate "Sensiron humidity and temperature sensors. SHT15 and compat." - depends on GENERIC_GPIO + depends on GPIOLIB help If you say yes here you get support for the Sensiron SHT10, SHT11, SHT15, SHT71, SHT75 humidity and temperature sensors. -- cgit v0.10.2 From 52f30f77171f934cb9562908cb279178b890a048 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 22 Mar 2012 16:23:58 -0400 Subject: hwmon: (max6639) Convert to dev_pm_ops The I2C specific PM operations have been deprecated and printing a warning on boot for over a year now. Signed-off-by: Mark Brown [guenter.roeck@ericsson.com: Added missing #ifdef around pm functions] Cc: stable@vger.kernel.org # 3.0+ Signed-off-by: Guenter Roeck diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index 193067e..de8f7ad 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -596,8 +596,10 @@ static int max6639_remove(struct i2c_client *client) return 0; } -static int max6639_suspend(struct i2c_client *client, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int max6639_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG); if (data < 0) return data; @@ -606,8 +608,9 @@ static int max6639_suspend(struct i2c_client *client, pm_message_t mesg) MAX6639_REG_GCONFIG, data | MAX6639_GCONFIG_STANDBY); } -static int max6639_resume(struct i2c_client *client) +static int max6639_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG); if (data < 0) return data; @@ -615,6 +618,7 @@ static int max6639_resume(struct i2c_client *client) return i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG, data & ~MAX6639_GCONFIG_STANDBY); } +#endif /* CONFIG_PM_SLEEP */ static const struct i2c_device_id max6639_id[] = { {"max6639", 0}, @@ -623,15 +627,18 @@ static const struct i2c_device_id max6639_id[] = { MODULE_DEVICE_TABLE(i2c, max6639_id); +static const struct dev_pm_ops max6639_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(max6639_suspend, max6639_resume) +}; + static struct i2c_driver max6639_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "max6639", + .pm = &max6639_pm_ops, }, .probe = max6639_probe, .remove = max6639_remove, - .suspend = max6639_suspend, - .resume = max6639_resume, .id_table = max6639_id, .detect = max6639_detect, .address_list = normal_i2c, -- cgit v0.10.2 From 6394011d65b7e74666f07cca98747601cf8298fa Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 24 Mar 2012 08:38:21 -0700 Subject: hwmon: (f75375s) Fix warning message seen in some configurations In some configurations, BUG() does not result in an endless loop but returns to the caller. This results in the following compiler warning: drivers/hwmon/f75375s.c: In function 'duty_mode_enabled': drivers/hwmon/f75375s.c:280: warning: control reaches end of non-void function drivers/hwmon/f75375s.c: In function 'auto_mode_enabled': drivers/hwmon/f75375s.c:295: warning: control reaches end of non-void function Fix the warning by returning something sensible after BUG(). Cc: Nikolaus Schulz Cc: Riku Voipio Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Signed-off-by: Guenter Roeck diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 729499e..ece4159 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -276,6 +276,7 @@ static bool duty_mode_enabled(u8 pwm_enable) return false; default: BUG(); + return true; } } @@ -291,6 +292,7 @@ static bool auto_mode_enabled(u8 pwm_enable) return true; default: BUG(); + return false; } } -- cgit v0.10.2 From ce15a81da33b961852f6e6a55305ccc60856de25 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 24 Mar 2012 08:51:05 -0700 Subject: hwmon: (adm1031) Fix compiler warning Some configurations produce the following compile warning: drivers/hwmon/adm1031.c: In function 'set_fan_auto_channel': drivers/hwmon/adm1031.c:292: warning: 'reg' may be used uninitialized in this function While this is a false positive, it can easily be fixed by overloading the return value from get_fan_auto_nearest with both register value and error return code (the register value is never negative). Coincidentially, that also reduces module size by a few bytes. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index ff37363..44e1fd7 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -233,18 +233,15 @@ static const auto_chan_table_t auto_channel_select_table_adm1030 = { * nearest match if no exact match where found. */ static int -get_fan_auto_nearest(struct adm1031_data *data, - int chan, u8 val, u8 reg, u8 *new_reg) +get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg) { int i; int first_match = -1, exact_match = -1; u8 other_reg_val = (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1]; - if (val == 0) { - *new_reg = 0; + if (val == 0) return 0; - } for (i = 0; i < 8; i++) { if ((val == (*data->chan_select_table)[i][chan]) && @@ -264,13 +261,11 @@ get_fan_auto_nearest(struct adm1031_data *data, } if (exact_match >= 0) - *new_reg = exact_match; + return exact_match; else if (first_match >= 0) - *new_reg = first_match; - else - return -EINVAL; + return first_match; - return 0; + return -EINVAL; } static ssize_t show_fan_auto_channel(struct device *dev, @@ -301,11 +296,12 @@ set_fan_auto_channel(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); - ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®); - if (ret) { + ret = get_fan_auto_nearest(data, nr, val, data->conf1); + if (ret < 0) { mutex_unlock(&data->update_lock); return ret; } + reg = ret; data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^ (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { -- cgit v0.10.2 From 31e354ee653c3d85e802a372f27224130fc95011 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 28 Mar 2012 15:11:47 -0400 Subject: hwmon: (acpi_power_meter) fix lockdep spew due to non-static lock class Similar to a30dcb4f which fixed asus_atk0110.ko, I recently received a bug report from someone hitting the same issue in acpi_power_meter. [ 13.963168] power_meter ACPI000D:00: Found ACPI power meter. [ 13.963900] BUG: key ffff8802161f3920 not in .data! [ 13.963904] ------------[ cut here ]------------ [ 13.963915] WARNING: at kernel/lockdep.c:2986 lockdep_init_map+0x52f/0x560() So let's fix that up for them by statically declaring the lockdep_class_key. Signed-off-by: Kyle McMartin Cc: stable@vger.kernel.org # 3.0+ Signed-off-by: Guenter Roeck diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 554f046..145f135 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -632,6 +632,7 @@ static int register_ro_attrs(struct acpi_power_meter_resource *resource, sensors->dev_attr.show = ro->show; sensors->index = ro->index; + sysfs_attr_init(&sensors->dev_attr.attr); res = device_create_file(dev, &sensors->dev_attr); if (res) { sensors->dev_attr.attr.name = NULL; @@ -661,6 +662,7 @@ static int register_rw_attrs(struct acpi_power_meter_resource *resource, sensors->dev_attr.store = rw->set; sensors->index = rw->index; + sysfs_attr_init(&sensors->dev_attr.attr); res = device_create_file(dev, &sensors->dev_attr); if (res) { sensors->dev_attr.attr.name = NULL; -- cgit v0.10.2 From 6f7805a8d9dc6fa8af999f8603188157505558d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 30 Mar 2012 16:04:55 -0400 Subject: hwmon: (w83627ehf) mark const init data with __initconst instead of __initdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As long as there is no other non-const variable marked __initdata in the same compilation unit it doesn't hurt. If there were one however compilation would fail with error: $variablename causes a section type conflict because a section containing const variables is marked read only and so cannot contain non-const variables. Signed-off-by: Uwe Kleine-König Cc: Jean Delvare Cc: Guenter Roeck Cc: lm-sensors@lm-sensors.org Signed-off-by: Guenter Roeck diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index a25350c..54922ed 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -2619,15 +2619,15 @@ static struct platform_driver w83627ehf_driver = { static int __init w83627ehf_find(int sioaddr, unsigned short *addr, struct w83627ehf_sio_data *sio_data) { - static const char __initdata sio_name_W83627EHF[] = "W83627EHF"; - static const char __initdata sio_name_W83627EHG[] = "W83627EHG"; - static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; - static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P"; - static const char __initdata sio_name_W83627UHG[] = "W83627UHG"; - static const char __initdata sio_name_W83667HG[] = "W83667HG"; - static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B"; - static const char __initdata sio_name_NCT6775[] = "NCT6775F"; - static const char __initdata sio_name_NCT6776[] = "NCT6776F"; + static const char sio_name_W83627EHF[] __initconst = "W83627EHF"; + static const char sio_name_W83627EHG[] __initconst = "W83627EHG"; + static const char sio_name_W83627DHG[] __initconst = "W83627DHG"; + static const char sio_name_W83627DHG_P[] __initconst = "W83627DHG-P"; + static const char sio_name_W83627UHG[] __initconst = "W83627UHG"; + static const char sio_name_W83667HG[] __initconst = "W83667HG"; + static const char sio_name_W83667HG_B[] __initconst = "W83667HG-B"; + static const char sio_name_NCT6775[] __initconst = "NCT6775F"; + static const char sio_name_NCT6776[] __initconst = "NCT6776F"; u16 val; const char *sio_name; -- cgit v0.10.2 From fbc729a446f7d80ec8b73fe90d8c0cc3e95ad277 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 30 Mar 2012 16:48:20 -0400 Subject: hwmon: (k10temp) Add support for AMD Trinity CPUs The on-chip northbridge's temperature sensor of the upcoming AMD Trinity CPUs works the same as for the previous CPUs. Since it has a different PCI-ID, we just add the new one to the list supported by k10temp. This allows to use the k10temp driver on those CPUs. Signed-off-by: Andre Przywara Cc: stable@vger.kernel.org # 3.0+ Signed-off-by: Guenter Roeck diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp index a10f736..90956b6 100644 --- a/Documentation/hwmon/k10temp +++ b/Documentation/hwmon/k10temp @@ -11,7 +11,7 @@ Supported chips: Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra) * AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series) * AMD Family 14h processors: "Brazos" (C/E/G/Z-Series) -* AMD Family 15h processors: "Bulldozer" +* AMD Family 15h processors: "Bulldozer" (FX-Series), "Trinity" Prefix: 'k10temp' Addresses scanned: PCI space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 670f274..8deedc1 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -253,7 +253,8 @@ config SENSORS_K10TEMP If you say yes here you get support for the temperature sensor(s) inside your CPU. Supported are later revisions of the AMD Family 10h and all revisions of the AMD Family 11h, - 12h (Llano), 14h (Brazos) and 15h (Bulldozer) microarchitectures. + 12h (Llano), 14h (Brazos) and 15h (Bulldozer/Trinity) + microarchitectures. This driver can also be built as a module. If so, the module will be called k10temp. diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index aba29d6..307bb32 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -33,6 +33,9 @@ static bool force; module_param(force, bool, 0444); MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); +/* PCI-IDs for Northbridge devices not used anywhere else */ +#define PCI_DEVICE_ID_AMD_15H_M10H_NB_F3 0x1403 + /* CPUID function 0x80000001, ebx */ #define CPUID_PKGTYPE_MASK 0xf0000000 #define CPUID_PKGTYPE_F 0x00000000 @@ -210,6 +213,7 @@ static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_NB_F3) }, {} }; MODULE_DEVICE_TABLE(pci, k10temp_id_table); -- cgit v0.10.2 From 9ebb389d0a03b4415fe9014f6922a2412cb1109c Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 1 Apr 2012 13:52:54 -0500 Subject: Revert "CIFS: Fix VFS lock usage for oplocked files" Revert previous version of patch to incorporate feedback so that we can merge version 3 of the patch instead.w This reverts commit b5efb978469d152c2c7c0a09746fb0bfc6171868. diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 0a11dbb..460d87b 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -671,21 +671,6 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock) } } -/* - * Copied from fs/locks.c with small changes. - * Remove waiter from blocker's block list. - * When blocker ends up pointing to itself then the list is empty. - */ -static void -cifs_locks_delete_block(struct file_lock *waiter) -{ - lock_flocks(); - list_del_init(&waiter->fl_block); - list_del_init(&waiter->fl_link); - waiter->fl_next = NULL; - unlock_flocks(); -} - static bool __cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, __u8 type, __u16 netfid, @@ -835,39 +820,6 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) return rc; } -/* Called with locked lock_mutex, return with unlocked. */ -static int -cifs_posix_lock_file_wait_locked(struct file *file, struct file_lock *flock) -{ - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - int rc; - - while (true) { - rc = posix_lock_file(file, flock, NULL); - mutex_unlock(&cinode->lock_mutex); - if (rc != FILE_LOCK_DEFERRED) - break; - rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); - if (!rc) { - mutex_lock(&cinode->lock_mutex); - continue; - } - cifs_locks_delete_block(flock); - break; - } - return rc; -} - -static int -cifs_posix_lock_file_wait(struct file *file, struct file_lock *flock) -{ - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - - mutex_lock(&cinode->lock_mutex); - /* lock_mutex will be released by the function below */ - return cifs_posix_lock_file_wait_locked(file, flock); -} - /* * Set the byte-range lock (posix style). Returns: * 1) 0, if we set the lock and don't need to request to the server; @@ -888,9 +840,9 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) mutex_unlock(&cinode->lock_mutex); return rc; } - - /* lock_mutex will be released by the function below */ - return cifs_posix_lock_file_wait_locked(file, flock); + rc = posix_lock_file_wait(file, flock); + mutex_unlock(&cinode->lock_mutex); + return rc; } static int @@ -1386,7 +1338,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, out: if (flock->fl_flags & FL_POSIX) - cifs_posix_lock_file_wait(file, flock); + posix_lock_file_wait(file, flock); return rc; } -- cgit v0.10.2 From 66189be74ff5f9f3fd6444315b85be210d07cef2 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Wed, 28 Mar 2012 21:56:19 +0400 Subject: CIFS: Fix VFS lock usage for oplocked files We can deadlock if we have a write oplock and two processes use the same file handle. In this case the first process can't unlock its lock if the second process blocked on the lock in the same time. Fix it by using posix_lock_file rather than posix_lock_file_wait under cinode->lock_mutex. If we request a blocking lock and posix_lock_file indicates that there is another lock that prevents us, wait untill that lock is released and restart our call. Cc: stable@kernel.org Acked-by: Jeff Layton Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 460d87b..fae765d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -835,13 +835,21 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) if ((flock->fl_flags & FL_POSIX) == 0) return rc; +try_again: mutex_lock(&cinode->lock_mutex); if (!cinode->can_cache_brlcks) { mutex_unlock(&cinode->lock_mutex); return rc; } - rc = posix_lock_file_wait(file, flock); + + rc = posix_lock_file(file, flock, NULL); mutex_unlock(&cinode->lock_mutex); + if (rc == FILE_LOCK_DEFERRED) { + rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); + if (!rc) + goto try_again; + locks_delete_block(flock); + } return rc; } diff --git a/fs/locks.c b/fs/locks.c index 637694b..0d68f1f 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -510,12 +510,13 @@ static void __locks_delete_block(struct file_lock *waiter) /* */ -static void locks_delete_block(struct file_lock *waiter) +void locks_delete_block(struct file_lock *waiter) { lock_flocks(); __locks_delete_block(waiter); unlock_flocks(); } +EXPORT_SYMBOL(locks_delete_block); /* Insert waiter into blocker's block list. * We use a circular list so that processes can be easily woken up in diff --git a/include/linux/fs.h b/include/linux/fs.h index 135693e..5286118 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1215,6 +1215,7 @@ extern int vfs_setlease(struct file *, long, struct file_lock **); extern int lease_modify(struct file_lock **, int); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); extern int lock_may_write(struct inode *, loff_t start, unsigned long count); +extern void locks_delete_block(struct file_lock *waiter); extern void lock_flocks(void); extern void unlock_flocks(void); #else /* !CONFIG_FILE_LOCKING */ @@ -1359,6 +1360,10 @@ static inline int lock_may_write(struct inode *inode, loff_t start, return 1; } +static inline void locks_delete_block(struct file_lock *waiter) +{ +} + static inline void lock_flocks(void) { } -- cgit v0.10.2 From 67378563df2e168d32a4054616f244a91aec462d Mon Sep 17 00:00:00 2001 From: David Ward Date: Tue, 27 Mar 2012 09:01:52 +0000 Subject: net/garp: avoid infinite loop if attribute already exists An infinite loop occurred if garp_attr_create was called with the values of an existing attribute. This might happen if a previous leave request for the attribute has not yet been followed by a PDU transmission (or, if the application previously issued a join request for the attribute and is now issuing another one, without having issued a leave request). If garp_attr_create finds an existing attribute having the same values, return the address to it. Its state will then get updated (i.e., if it was in a leaving state, it will move into a non-leaving state and not get deleted during the next PDU transmission). To accomplish this fix, collapse garp_attr_insert into garp_attr_create (which is its only caller). Thanks to Jorge Boncompte [DTI2] for contributing to this fix. Signed-off-by: David Ward Acked-by: Jorge Boncompte [DTI2] Signed-off-by: David S. Miller diff --git a/net/802/garp.c b/net/802/garp.c index 8e21b6d..a5c2248 100644 --- a/net/802/garp.c +++ b/net/802/garp.c @@ -167,7 +167,8 @@ static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app, return NULL; } -static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new) +static struct garp_attr *garp_attr_create(struct garp_applicant *app, + const void *data, u8 len, u8 type) { struct rb_node *parent = NULL, **p = &app->gid.rb_node; struct garp_attr *attr; @@ -176,21 +177,16 @@ static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new) while (*p) { parent = *p; attr = rb_entry(parent, struct garp_attr, node); - d = garp_attr_cmp(attr, new->data, new->dlen, new->type); + d = garp_attr_cmp(attr, data, len, type); if (d < 0) p = &parent->rb_left; else if (d > 0) p = &parent->rb_right; + else { + /* The attribute already exists; re-use it. */ + return attr; + } } - rb_link_node(&new->node, parent, p); - rb_insert_color(&new->node, &app->gid); -} - -static struct garp_attr *garp_attr_create(struct garp_applicant *app, - const void *data, u8 len, u8 type) -{ - struct garp_attr *attr; - attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC); if (!attr) return attr; @@ -198,7 +194,9 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app, attr->type = type; attr->dlen = len; memcpy(attr->data, data, len); - garp_attr_insert(app, attr); + + rb_link_node(&attr->node, parent, p); + rb_insert_color(&attr->node, &app->gid); return attr; } -- cgit v0.10.2 From 464b57da56910c8737ede75ad820b9a7afc46b3e Mon Sep 17 00:00:00 2001 From: Kenth Eriksson Date: Tue, 27 Mar 2012 22:05:54 +0000 Subject: Fix non TBI PHY access; a bad merge undid bug fix in a previous commit. The merge done in commit b26e478f undid bug fix in commit c3e072f8 ("net: fsl_pq_mdio: fix non tbi phy access"), with the result that non TBI (e.g. MDIO) PHYs cannot be accessed. Signed-off-by: Kenth Eriksson Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 9eb8159..f7f0bf5 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -356,13 +356,13 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) if (prop) tbiaddr = *prop; - } - if (tbiaddr == -1) { - err = -EBUSY; - goto err_free_irqs; - } else { - out_be32(tbipa, tbiaddr); + if (tbiaddr == -1) { + err = -EBUSY; + goto err_free_irqs; + } else { + out_be32(tbipa, tbiaddr); + } } err = of_mdiobus_register(new_bus, np); -- cgit v0.10.2 From 81213b5e8ae68e204aa7a3f83c4f9100405dbff9 Mon Sep 17 00:00:00 2001 From: "danborkmann@iogearbox.net" Date: Tue, 27 Mar 2012 22:47:43 +0000 Subject: rose_dev: fix memcpy-bug in rose_set_mac_address If both addresses equal, nothing needs to be done. If the device is down, then we simply copy the new address to dev->dev_addr. If the device is up, then we add another loopback device with the new address, and if that does not fail, we remove the loopback device with the old address. And only then, we update the dev->dev_addr. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 178ff4f..2679507 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -96,11 +96,11 @@ static int rose_set_mac_address(struct net_device *dev, void *addr) struct sockaddr *sa = addr; int err; - if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len)) + if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len)) return 0; if (dev->flags & IFF_UP) { - err = rose_add_loopback_node((rose_address *)dev->dev_addr); + err = rose_add_loopback_node((rose_address *)sa->sa_data); if (err) return err; -- cgit v0.10.2 From 6523cf9a460c488c681b7e4ecef2395491de1d4e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 28 Mar 2012 12:10:57 +0000 Subject: net/netfilter/nfnetlink_acct.c: use linux/atomic.h There's no known problem here, but this is one of only two non-arch files in the kernel which use asm/atomic.h instead of linux/atomic.h. Acked-by: Pablo Neira Ayuso Cc: Patrick McHardy Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index 3eb348b..d98c868 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -17,7 +18,6 @@ #include #include #include -#include #include #include -- cgit v0.10.2 From cdaf0b835df04177397b90214f8b457fd23b67e0 Mon Sep 17 00:00:00 2001 From: "stigge@antcom.de" Date: Wed, 28 Mar 2012 12:36:26 +0000 Subject: net: lpc_eth: Fix rename of dev_hw_addr_random In parallel to the integration of lpc_eth.c, dev_hw_addr_random() has been renamed to eth_hw_addr_random(). This patch fixes it also in the new driver lpc_eth.c. Signed-off-by: Roland Stigge Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 6944424..6dfc26d 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1441,7 +1441,7 @@ static int lpc_eth_drv_probe(struct platform_device *pdev) } #endif if (!is_valid_ether_addr(ndev->dev_addr)) - dev_hw_addr_random(ndev, ndev->dev_addr); + eth_hw_addr_random(ndev); /* Reset the ethernet controller */ __lpc_eth_reset(pldat); -- cgit v0.10.2 From 7224c0d1045327d637dab2c90777b6d5ec6d6804 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Fri, 30 Mar 2012 15:52:09 +1000 Subject: m68k: include asm/cmpxchg.h in our m68k atomic.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit 9ffc93f203c18a70623f21950f1dd473c9ec48cd ("Remove all CC init/main.o In file included from include/linux/mm.h:15:0, from include/linux/ring_buffer.h:5, from include/linux/ftrace_event.h:4, from include/trace/syscall.h:6, from include/linux/syscalls.h:78, from init/main.c:16: include/linux/debug_locks.h: In function ‘__debug_locks_off’: include/linux/debug_locks.h:16:2: error: implicit declaration of function ‘xchg’ There is no indirect inclusions of the new asm/cmpxchg.h for m68k here. Looking at most other architectures they include asm/cmpxchg.h in their asm/atomic.h. M68k currently does not do this. Including this in atomic.h fixes all m68k build problems. Signed-off-by: Greg Ungerer Acked-by: David Howells Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h index 336e617..f4e32de 100644 --- a/arch/m68k/include/asm/atomic.h +++ b/arch/m68k/include/asm/atomic.h @@ -3,6 +3,7 @@ #include #include +#include /* * Atomic operations that C can't guarantee us. Useful for -- cgit v0.10.2 From 6cfeba53911d6d2f17ebbd1246893557d5ff5aeb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 18 Mar 2012 13:21:38 +0100 Subject: m68k/mac: Add missing platform check before registering platform devices On multi-platform kernels, the Mac platform devices should be registered when running on Mac only. Else it may crash later. Signed-off-by: Geert Uytterhoeven Cc: stable@vger.kernel.org diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 96fa6ed..d9f62e0 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -980,6 +980,9 @@ int __init mac_platform_init(void) { u8 *swim_base; + if (!MACH_IS_MAC) + return -ENODEV; + /* * Serial devices */ -- cgit v0.10.2 From 450aed725c9a53282483c48ebd012feefae94a07 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 18 Mar 2012 13:20:27 +0100 Subject: m68k/q40: Add missing platform check before registering platform devices On multi-platform kernels, the Q40/Q60 platform devices should be registered when running on Q40/Q60 only. Else it may crash later. Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 512adb6..8a1ce32 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -334,6 +334,9 @@ static __init int q40_add_kbd_device(void) { struct platform_device *pdev; + if (!MACH_IS_Q40) + return -ENODEV; + pdev = platform_device_register_simple("q40kbd", -1, NULL, 0); if (IS_ERR(pdev)) return PTR_ERR(pdev); -- cgit v0.10.2 From 2533e824153b51bda27fe41ed1a5512047f42707 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 1 Apr 2012 08:54:38 +0000 Subject: sparc: pgtable_64: change include order Fix the following build breakage in v3.4-rc1: CC arch/sparc/kernel/cpu.o In file included from /home/aaro/git/linux/arch/sparc/include/asm/pgtable_64.h:15:0, from /home/aaro/git/linux/arch/sparc/include/asm/pgtable.h:4, from arch/sparc/kernel/cpu.c:15: include/asm-generic/pgtable-nopud.h:13:16: error: unknown type name 'pgd_t' include/asm-generic/pgtable-nopud.h:25:28: error: unknown type name 'pgd_t' include/asm-generic/pgtable-nopud.h:26:27: error: unknown type name 'pgd_t' include/asm-generic/pgtable-nopud.h:27:31: error: unknown type name 'pgd_t' include/asm-generic/pgtable-nopud.h:28:30: error: unknown type name 'pgd_t' include/asm-generic/pgtable-nopud.h:38:34: error: unknown type name 'pgd_t' In file included from /home/aaro/git/linux/arch/sparc/include/asm/pgtable_64.h:783:0, from /home/aaro/git/linux/arch/sparc/include/asm/pgtable.h:4, from arch/sparc/kernel/cpu.c:15: include/asm-generic/pgtable.h: In function 'pgd_none_or_clear_bad': include/asm-generic/pgtable.h:258:2: error: implicit declaration of function 'pgd_none' [-Werror=implicit-function-declaration] include/asm-generic/pgtable.h:260:2: error: implicit declaration of function 'pgd_bad' [-Werror=implicit-function-declaration] include/asm-generic/pgtable.h: In function 'pud_none_or_clear_bad': include/asm-generic/pgtable.h:269:6: error: request for member 'pgd' in something not a structure or union Reported-by: Meelis Roos Signed-off-by: Aaro Koskinen Signed-off-by: David S. Miller diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 6fa2f79..76e4a52 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -12,8 +12,6 @@ * the SpitFire page tables. */ -#include - #include #include #include @@ -22,6 +20,8 @@ #include #include +#include + /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). * The page copy blockops can use 0x6000000 to 0x8000000. * The TSB is mapped in the 0x8000000 to 0xa000000 range. -- cgit v0.10.2 From 72331bc0cd072c3f4b670cd1256e47681fc53b80 Mon Sep 17 00:00:00 2001 From: Shmulik Ladkani Date: Sun, 1 Apr 2012 04:03:45 +0000 Subject: ipv6: Fix RTM_GETROUTE's interpretation of RTA_IIF to be consistent with ipv4 In IPv4, if an RTA_IIF attribute is specified within an RTM_GETROUTE message, then a route is searched as if a packet was received on the specified 'iif' interface. However in IPv6, RTA_IIF is not interpreted in the same way: 'inet6_rtm_getroute()' always calls 'ip6_route_output()', regardless the RTA_IIF attribute. As a result, in IPv6 there's no way to use RTM_GETROUTE in order to look for a route as if a packet was received on a specific interface. Fix 'inet6_rtm_getroute()' so that RTA_IIF is interpreted as "lookup a route as if a packet was received on the specified interface", similar to IPv4's 'inet_rtm_getroute()' interpretation. Reported-by: Ami Koren Signed-off-by: Shmulik Ladkani Signed-off-by: David S. Miller diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 496b627..3992e26 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -881,6 +881,16 @@ static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table * return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags); } +static struct dst_entry *ip6_route_input_lookup(struct net *net, + struct net_device *dev, + struct flowi6 *fl6, int flags) +{ + if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG) + flags |= RT6_LOOKUP_F_IFACE; + + return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input); +} + void ip6_route_input(struct sk_buff *skb) { const struct ipv6hdr *iph = ipv6_hdr(skb); @@ -895,10 +905,7 @@ void ip6_route_input(struct sk_buff *skb) .flowi6_proto = iph->nexthdr, }; - if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) - flags |= RT6_LOOKUP_F_IFACE; - - skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input)); + skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags)); } static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, @@ -2537,7 +2544,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void struct sk_buff *skb; struct rtmsg *rtm; struct flowi6 fl6; - int err, iif = 0; + int err, iif = 0, oif = 0; err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); if (err < 0) @@ -2564,15 +2571,29 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void iif = nla_get_u32(tb[RTA_IIF]); if (tb[RTA_OIF]) - fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]); + oif = nla_get_u32(tb[RTA_OIF]); if (iif) { struct net_device *dev; + int flags = 0; + dev = __dev_get_by_index(net, iif); if (!dev) { err = -ENODEV; goto errout; } + + fl6.flowi6_iif = iif; + + if (!ipv6_addr_any(&fl6.saddr)) + flags |= RT6_LOOKUP_F_HAS_SADDR; + + rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6, + flags); + } else { + fl6.flowi6_oif = oif; + + rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6); } skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); @@ -2587,7 +2608,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void skb_reset_mac_header(skb); skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); - rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6); skb_dst_set(skb, &rt->dst); err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, -- cgit v0.10.2 From 8551f3ff49aeda57c6c204a4a4769395fa679fb8 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Thu, 29 Mar 2012 08:55:48 +0900 Subject: ARM: S3C24XX: fix missing common.h in mach-s3c24xx/ This patch fixes missing mach-s3c24xx/common.h which has been lost when regarding s3c24xx directories merged. Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h new file mode 100644 index 0000000..c2f596e --- /dev/null +++ b/arch/arm/mach-s3c24xx/common.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Common Header for S3C24XX SoCs + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ARCH_ARM_MACH_S3C24XX_COMMON_H +#define __ARCH_ARM_MACH_S3C24XX_COMMON_H __FILE__ + +void s3c2410_restart(char mode, const char *cmd); +void s3c244x_restart(char mode, const char *cmd); + +#endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */ -- cgit v0.10.2 From 98d5561bfbc3c7a53d6abc1812a2bd5344d36fa3 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Mon, 2 Apr 2012 09:48:37 +1000 Subject: md/linear: If md_integrity_register() fails, linear_run() must free the mem. Signed-off-by: majianpeng Signed-off-by: NeilBrown diff --git a/drivers/md/linear.c b/drivers/md/linear.c index b0fcc7d..fa211d8 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -198,6 +198,7 @@ out: static int linear_run (struct mddev *mddev) { struct linear_conf *conf; + int ret; if (md_check_no_bitmap(mddev)) return -EINVAL; @@ -211,7 +212,13 @@ static int linear_run (struct mddev *mddev) blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->backing_dev_info.congested_fn = linear_congested; mddev->queue->backing_dev_info.congested_data = mddev; - return md_integrity_register(mddev); + + ret = md_integrity_register(mddev); + if (ret) { + kfree(conf); + mddev->private = NULL; + } + return ret; } static int linear_add(struct mddev *mddev, struct md_rdev *rdev) -- cgit v0.10.2 From 0366ef847581d692e197b88825867ca9ee00e358 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Mon, 2 Apr 2012 09:48:37 +1000 Subject: md/raid0: If md_integrity_register() fails, raid0_run() must free the mem. Signed-off-by: majianpeng Signed-off-by: NeilBrown diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 6f31f55..c980945 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -407,6 +407,8 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks return array_sectors; } +static int raid0_stop(struct mddev *mddev); + static int raid0_run(struct mddev *mddev) { struct r0conf *conf; @@ -454,7 +456,12 @@ static int raid0_run(struct mddev *mddev) blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec); dump_zones(mddev); - return md_integrity_register(mddev); + + ret = md_integrity_register(mddev); + if (ret) + raid0_stop(mddev); + + return ret; } static int raid0_stop(struct mddev *mddev) -- cgit v0.10.2 From 5220ea1e640869e70f894837678315c878c651fd Mon Sep 17 00:00:00 2001 From: majianpeng Date: Mon, 2 Apr 2012 09:48:38 +1000 Subject: md/raid1: If md_integrity_register() failed,run() must free the mem Signed-off-by: majianpeng Signed-off-by: NeilBrown diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4a40a20..2424408 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2636,11 +2636,13 @@ static struct r1conf *setup_conf(struct mddev *mddev) return ERR_PTR(err); } +static int stop(struct mddev *mddev); static int run(struct mddev *mddev) { struct r1conf *conf; int i; struct md_rdev *rdev; + int ret; if (mddev->level != 1) { printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n", @@ -2705,7 +2707,11 @@ static int run(struct mddev *mddev) mddev->queue->backing_dev_info.congested_data = mddev; blk_queue_merge_bvec(mddev->queue, raid1_mergeable_bvec); } - return md_integrity_register(mddev); + + ret = md_integrity_register(mddev); + if (ret) + stop(mddev); + return ret; } static int stop(struct mddev *mddev) -- cgit v0.10.2 From 3f8c91a7398b9266fbe7abcbe4bd5dffef907643 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Sun, 1 Apr 2012 12:35:00 +0000 Subject: via-rhine: fix wait-bit inversion. Bug appeared in a384a33bb1c9ec2d99db2046b41f57023fa7d77b ("via-rhine: RHINE_WAIT_FOR macro removal). It can be noticed during suspend/resume. Signed-off-by: Andreas Mohr Acked-by: Francois Romieu Cc: David Lv Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 39b8cf3..fcfa01f 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -503,30 +503,32 @@ static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid); static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); static void rhine_restart_tx(struct net_device *dev); -static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high) +static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool low) { void __iomem *ioaddr = rp->base; int i; for (i = 0; i < 1024; i++) { - if (high ^ !!(ioread8(ioaddr + reg) & mask)) + bool has_mask_bits = !!(ioread8(ioaddr + reg) & mask); + + if (low ^ has_mask_bits) break; udelay(10); } if (i > 64) { netif_dbg(rp, hw, rp->dev, "%s bit wait (%02x/%02x) cycle " - "count: %04d\n", high ? "high" : "low", reg, mask, i); + "count: %04d\n", low ? "low" : "high", reg, mask, i); } } static void rhine_wait_bit_high(struct rhine_private *rp, u8 reg, u8 mask) { - rhine_wait_bit(rp, reg, mask, true); + rhine_wait_bit(rp, reg, mask, false); } static void rhine_wait_bit_low(struct rhine_private *rp, u8 reg, u8 mask) { - rhine_wait_bit(rp, reg, mask, false); + rhine_wait_bit(rp, reg, mask, true); } static u32 rhine_get_events(struct rhine_private *rp) -- cgit v0.10.2 From acc656323ab904803393acefdc8e1b78cde752e5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 30 Mar 2012 01:01:46 +0000 Subject: rionet: fix page allocation order of rionet_active rionet_active is allocated from the page allocator and the allocation order is calculated on the assumption that the page size is 4KB, so it wastes memory on more than 4K page systems. Signed-off-by: Akinobu Mita Cc: Matt Porter Cc: Alexandre Bounine Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index a57f057..91d2588 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -375,8 +375,8 @@ static void rionet_remove(struct rio_dev *rdev) struct net_device *ndev = rio_get_drvdata(rdev); struct rionet_peer *peer, *tmp; - free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? - __fls(sizeof(void *)) + 4 : 0); + free_pages((unsigned long)rionet_active, get_order(sizeof(void *) * + RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size))); unregister_netdev(ndev); free_netdev(ndev); @@ -432,15 +432,16 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) int rc = 0; struct rionet_private *rnet; u16 device_id; + const size_t rionet_active_bytes = sizeof(void *) * + RIO_MAX_ROUTE_ENTRIES(mport->sys_size); rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, - mport->sys_size ? __fls(sizeof(void *)) + 4 : 0); + get_order(rionet_active_bytes)); if (!rionet_active) { rc = -ENOMEM; goto out; } - memset((void *)rionet_active, 0, sizeof(void *) * - RIO_MAX_ROUTE_ENTRIES(mport->sys_size)); + memset((void *)rionet_active, 0, rionet_active_bytes); /* Set up private area */ rnet = netdev_priv(ndev); -- cgit v0.10.2 From 6bafd6436e99d08e8def37ae9f790e1aff871bae Mon Sep 17 00:00:00 2001 From: huajun li Date: Fri, 30 Mar 2012 00:11:05 +0000 Subject: usb/rtl8150 : Remove duplicated definitions There exist duplicated macro definitions in rtl8150.c, remove them. Signed-off-by: Huajun Li Signed-off-by: David S. Miller diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 6dda2fe..d363b31 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -85,32 +85,6 @@ #define INT_CRERR_CNT 0x06 #define INT_COL_CNT 0x07 -/* Transmit status register errors */ -#define TSR_ECOL (1<<5) -#define TSR_LCOL (1<<4) -#define TSR_LOSS_CRS (1<<3) -#define TSR_JBR (1<<2) -#define TSR_ERRORS (TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR) -/* Receive status register errors */ -#define RSR_CRC (1<<2) -#define RSR_FAE (1<<1) -#define RSR_ERRORS (RSR_CRC | RSR_FAE) - -/* Media status register definitions */ -#define MSR_DUPLEX (1<<4) -#define MSR_SPEED (1<<3) -#define MSR_LINK (1<<2) - -/* Interrupt pipe data */ -#define INT_TSR 0x00 -#define INT_RSR 0x01 -#define INT_MSR 0x02 -#define INT_WAKSR 0x03 -#define INT_TXOK_CNT 0x04 -#define INT_RXLOST_CNT 0x05 -#define INT_CRERR_CNT 0x06 -#define INT_COL_CNT 0x07 - #define RTL8150_MTU 1540 #define RTL8150_TX_TIMEOUT (HZ) -- cgit v0.10.2 From 10b9194f959608368ed89df1937f17cfe6bd6d84 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 29 Mar 2012 19:32:08 +0000 Subject: net: sh_eth: fix endian check for architecture independent SuperH has the "CONFIG_CPU_LITTLE_ENDIAN" and the "__LITTLE_ENDIAN__". But, other architecture doesn't have them. So, this patch fixes it. Signed-off-by: Yoshihiro Shimoda Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 8bdf070..d63e09b 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -804,7 +804,7 @@ static int sh_eth_dev_init(struct net_device *ndev) /* all sh_eth int mask */ sh_eth_write(ndev, 0, EESIPR); -#if defined(__LITTLE_ENDIAN__) +#if defined(__LITTLE_ENDIAN) if (mdp->cd->hw_swap) sh_eth_write(ndev, EDMR_EL, EDMR); else diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index e66de18..0fa14afc 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -693,7 +693,7 @@ enum TSU_FWSLC_BIT { */ struct sh_eth_txdesc { u32 status; /* TD0 */ -#if defined(CONFIG_CPU_LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) u16 pad0; /* TD1 */ u16 buffer_length; /* TD1 */ #else @@ -710,7 +710,7 @@ struct sh_eth_txdesc { */ struct sh_eth_rxdesc { u32 status; /* RD0 */ -#if defined(CONFIG_CPU_LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) u16 frame_length; /* RD1 */ u16 buffer_length; /* RD1 */ #else -- cgit v0.10.2 From 78fb72f7936c01d5b426c03a691eca082b03f2b9 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 29 Mar 2012 07:15:15 +0000 Subject: net: usb: cdc_eem: fix mtu Make CDC EEM recalculate the hard_mtu after adjusting the hard_header_len. Without this, usbnet adjusts the MTU down to 1494 bytes, and the host is unable to receive standard 1500-byte frames from the device. Tested with the Linux USB Ethernet gadget. Cc: Oliver Neukum Signed-off-by: Rabin Vincent Signed-off-by: David S. Miller diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index 439690b..685a4e2 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -93,6 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf) /* no jumbogram (16K) support for now */ dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; return 0; } -- cgit v0.10.2 From 059378e3ff36094dccdd55600c3ad67a88c302aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 30 Mar 2012 10:05:00 +0000 Subject: powerpc: Mark const init data with __initconst instead of __initdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As long as there is no other non-const variable marked __initdata in the same compilation unit it doesn't hurt. If there were one however compilation would fail with error: $variablename causes a section type conflict because a section containing const variables is marked read only and so cannot contain non-const variables. Signed-off-by: Uwe Kleine-König Cc: Josh Boyer Cc: Matt Porter Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Anatolij Gustschin Cc: Kumar Gala Cc: Arnd Bergmann Cc: linuxppc-dev@lists.ozlabs.org Cc: cbe-oss-dev@lists.ozlabs.org Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index bfb11e0..e2d401a 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -93,7 +93,7 @@ struct mpc52xx_pci { }; /* MPC5200 device tree match tables */ -const struct of_device_id mpc52xx_pci_ids[] __initdata = { +const struct of_device_id mpc52xx_pci_ids[] __initconst = { { .type = "pci", .compatible = "fsl,mpc5200-pci", }, { .type = "pci", .compatible = "mpc5200-pci", }, {} diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c index 7f9b674..6e3409d 100644 --- a/arch/powerpc/platforms/cell/qpace_setup.c +++ b/arch/powerpc/platforms/cell/qpace_setup.c @@ -61,7 +61,7 @@ static void qpace_progress(char *s, unsigned short hex) printk("*** %04x : %s\n", hex, s ? s : ""); } -static const struct of_device_id qpace_bus_ids[] __initdata = { +static const struct of_device_id qpace_bus_ids[] __initconst = { { .type = "soc", }, { .compatible = "soc", }, { .type = "spider", }, diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index fa3e294..4ab0876 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -140,7 +140,7 @@ static int __devinit cell_setup_phb(struct pci_controller *phb) return 0; } -static const struct of_device_id cell_bus_ids[] __initdata = { +static const struct of_device_id cell_bus_ids[] __initconst = { { .type = "soc", }, { .compatible = "soc", }, { .type = "spider", }, -- cgit v0.10.2 From cad3c8346b94edd68e4b9c2c0056a5f61411af1a Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 30 Mar 2012 14:01:07 +0000 Subject: powerpc: Fix fallout from system.h split up Signed-off-by: Stephen Rothwell Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index cfe7a38..18bdf74 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include static struct fw_dump fw_dump; static struct fadump_mem_struct fdm; diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 76a6e40..782bd0a 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * This table contains the mapping between PowerPC hardware trap types, and -- cgit v0.10.2 From 95327d08fd5fc686b35ac21050a1b74f9bce3abe Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 1 Apr 2012 17:35:53 +0000 Subject: powerpc/kvm: Fallout from system.h disintegration Add a missing include to fix build Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index f1950d1..135663a 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c @@ -21,6 +21,7 @@ #include #include #include +#include #define OP_19_XOP_RFID 18 #define OP_19_XOP_RFI 50 diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c index e70ef2d..a59a25a 100644 --- a/arch/powerpc/kvm/book3s_paired_singles.c +++ b/arch/powerpc/kvm/book3s_paired_singles.c @@ -24,6 +24,7 @@ #include #include #include +#include #include /* #define DEBUG */ diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 7340e10..642d885 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From 37ef9bd48af6ab9a3d1fd28df4f929abc19f2cc3 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 28 Mar 2012 12:20:57 +0000 Subject: powerpc/eeh: Remove eeh_event_handler()->daemonize() daemonize() is only needed when a user-space task does kernel_thread(). eeh_event_handler() thread is created by the worker kthread, and thus it doesn't need the soon-to-be-deprecated daemonize(). Signed-off-by: Oleg Nesterov Acked-by: Linas Vepstas Acked-by: Tejun Heo Acked-by: Matt Fleming Signed-off-by: Andrew Morton Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 4a47525..92dd84c 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -59,7 +59,7 @@ static int eeh_event_handler(void * dummy) struct eeh_event *event; struct eeh_dev *edev; - daemonize("eehd"); + set_task_comm(current, "eehd"); set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&eeh_eventlist_lock, flags); -- cgit v0.10.2 From 9b218f63e50e590fe0c7724a0838d7eaa6dae5ce Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 28 Mar 2012 12:20:58 +0000 Subject: powerpc/eeh: Fix use of set_current_state() in eeh event handling set_current_state() wart That set_current_state() won't work very well: the subsequent mutex_lock() might flip the task back into TASK_RUNNING. Attempt to put it somewhere where it might have been meant to be, and attempt to describe why it might have been added. Signed-off-by: Andrew Morton Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 92dd84c..4cb375c 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -60,7 +60,6 @@ static int eeh_event_handler(void * dummy) struct eeh_dev *edev; set_task_comm(current, "eehd"); - set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&eeh_eventlist_lock, flags); event = NULL; @@ -83,6 +82,7 @@ static int eeh_event_handler(void * dummy) printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", eeh_pci_name(edev->pdev)); + set_current_state(TASK_INTERRUPTIBLE); /* Don't add to load average */ edev = handle_eeh_events(event); eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING); -- cgit v0.10.2 From eb26e877771ece01ca755c1bb34a2636a0758223 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 20 Mar 2012 00:09:58 -0300 Subject: ARM: mach-mx35_3ds: Fix build warning due to the lack of 'const' annotation Fix the following build warning: arch/arm/mach-imx/mach-mx35_3ds.c: In function 'mx35_3ds_lcd_set_power': arch/arm/mach-imx/mach-mx35_3ds.c:112: warning: passing argument 2 of 'gpiochip_find' from incompatible pointer type include/asm-generic/gpio.h:145: note: expected 'int (*)(struct gpio_chip *, const void *)' but argument is of type 'int (*)(struct gpio_chip *, void *)' Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index e14291d..6ae51c6 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -97,7 +97,7 @@ static struct i2c_board_info __initdata i2c_devices_3ds[] = { static int lcd_power_gpio = -ENXIO; static int mc9s08dz60_gpiochip_match(struct gpio_chip *chip, - void *data) + const void *data) { return !strcmp(chip->label, data); } -- cgit v0.10.2 From 31e1a4e8b6b356bb7cc24e64d18f25e1b01e5a42 Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Wed, 21 Mar 2012 16:19:41 +0100 Subject: MX2: Fix mx2_camera clock regression. The following patch breaks mx2_camera driver: http://git.linuxtv.org/media_tree.git?a=commitdiff;h=52f1a845e25dc0c6435153aca1a170e20b282429 This change fixes the problem. Signed-off-by: Javier Martin Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c index b9a95ed..98e04f5 100644 --- a/arch/arm/mach-imx/clock-imx27.c +++ b/arch/arm/mach-imx/clock-imx27.c @@ -662,6 +662,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "dma", dma_clk) _REGISTER_CLOCK(NULL, "rtic", rtic_clk) _REGISTER_CLOCK(NULL, "brom", brom_clk) + _REGISTER_CLOCK(NULL, "emma", emma_clk) _REGISTER_CLOCK("m2m-emmaprp.0", NULL, emma_clk) _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk) _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) -- cgit v0.10.2 From f0df87541888fe3408fa71132d2b35c575586f89 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 26 Mar 2012 15:53:57 -0300 Subject: ARM: 3ds_debugboard: Fix smsc911x driver probe Fix smsc911x id field in order to fix smsc911x driver probe error: smsc911x smsc911x.0: Failed to get supply 'vdd33a': -517 smsc911x smsc911x.0: (unregistered net_device): couldn't get regulators -517 platform smsc911x.0: Driver smsc911x requests probe deferral Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/plat-mxc/3ds_debugboard.c b/arch/arm/plat-mxc/3ds_debugboard.c index d1e31fa..5cac2c5 100644 --- a/arch/arm/plat-mxc/3ds_debugboard.c +++ b/arch/arm/plat-mxc/3ds_debugboard.c @@ -80,7 +80,7 @@ static struct smsc911x_platform_config smsc911x_config = { static struct platform_device smsc_lan9217_device = { .name = "smsc911x", - .id = 0, + .id = -1, .dev = { .platform_data = &smsc911x_config, }, -- cgit v0.10.2 From bfb5f5530c8b3efd3f5e58ab14258bf2a9b34096 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 6 Mar 2012 10:35:53 -0300 Subject: ARM: mx35: Fix registration of camera clock Fix registration of camera clock so that mx3-camera driver can get its clock correctly. Reported-by: Alex Gershgorin Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c index 1e279af..e56c1a8 100644 --- a/arch/arm/mach-imx/clock-imx35.c +++ b/arch/arm/mach-imx/clock-imx35.c @@ -483,7 +483,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk) _REGISTER_CLOCK(NULL, "max", max_clk) _REGISTER_CLOCK(NULL, "audmux", audmux_clk) - _REGISTER_CLOCK(NULL, "csi", csi_clk) + _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk) _REGISTER_CLOCK(NULL, "iim", iim_clk) _REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk) _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) -- cgit v0.10.2 From 0eb043d0eec44cd083ea6910b1db2f77eb212ebd Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 31 Mar 2012 23:41:07 -0700 Subject: Subject: [PATCH] tags.sh: Add missing quotes When $remove_structs is empty a test for empty string will turn into test -n with no arguments meaning true. Add quotes so an empty string is tested and so that make cscope works again. Reported-and-tested-by: Jike Song Reported-by: Prarit Bhargava Acked-by: Yang Bai Signed-off-by: Stephen Boyd Signed-off-by: Michal Marek diff --git a/scripts/tags.sh b/scripts/tags.sh index 0d6004e..cf7b12f 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -254,6 +254,6 @@ case "$1" in esac # Remove structure forward declarations. -if [ -n $remove_structs ]; then +if [ -n "$remove_structs" ]; then LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' $1 fi -- cgit v0.10.2 From 40c61046ee3007d73f141e96aa2f3dd56ee321c6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Apr 2012 10:45:49 +0100 Subject: drm/nouveau: select POWER_SUPPLY Ben H. reported that building nouveau into the kernel and power supply as a module was broken. Just have nouveau select it, like radeon does. Reported-by: Benjamin Herrenschmidt Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index ca16399..97a8126 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -13,6 +13,7 @@ config DRM_NOUVEAU select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT select ACPI_WMI if ACPI select MXM_WMI if ACPI + select POWER_SUPPLY help Choose this option for open-source nVidia support. -- cgit v0.10.2 From 7bd9523969299f4c845615eade5e523f840dc34c Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 20 Mar 2012 15:58:12 +0100 Subject: ARM: at91/at91sam9x5: add clkdev entries for DMA controllers Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index b6831ee..13c8cae 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -223,6 +223,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk), CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk), + CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk), + CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk), CLKDEV_CON_ID("pioA", &pioAB_clk), CLKDEV_CON_ID("pioB", &pioAB_clk), CLKDEV_CON_ID("pioC", &pioCD_clk), -- cgit v0.10.2 From ea71f98d680c9ac768a7849d26d7ce4744064510 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 2 Apr 2012 13:37:13 +1000 Subject: nouveau: Fix crash when pci_ram_rom() returns a size of 0 From b15b244d6e6e20964bd4b85306722cb60c3c0809 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 2 Apr 2012 13:28:18 +1000 Subject: Under some circumstances, pci_map_rom() can return a valid mapping but a size of 0 (if it cannot find an image in the header). This causes nouveau to try to kmalloc() a 0 sized pointer and dereference it, which crashes. Signed-off-by: Benjamin Herrenschmidt Acked-by: Ben Skeggs Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 637afe7..80963d0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -177,14 +177,15 @@ bios_shadow_pci(struct nvbios *bios) if (!pci_enable_rom(pdev)) { void __iomem *rom = pci_map_rom(pdev, &length); - if (rom) { + if (rom && length) { bios->data = kmalloc(length, GFP_KERNEL); if (bios->data) { memcpy_fromio(bios->data, rom, length); bios->length = length; } - pci_unmap_rom(pdev, rom); } + if (rom) + pci_unmap_rom(pdev, rom); pci_disable_rom(pdev); } -- cgit v0.10.2 From d06221c0617ab6d0bc41c4980cefdd9c8cc9a1c1 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 2 Apr 2012 13:38:19 +1000 Subject: nouveau/bios: Fix tracking of BIOS image data The code tries various methods for retreiving the BIOS data. However it doesn't clear the bios->data pointer between the iterations. In some cases, the shadow() method will fail and not update bios->data at all, which will cause us to "score" the old data and incorrectly attribute that score to the new method. This can cause double frees later when disposing of the unused data. Additionally, we were not freeing the data for methods that fail the score test (we only freed when a "best" is superseeded, not when the new method has a lower score than the exising "best"). Fix that as well. Signed-off-by: Benjamin Herrenschmidt Acked-by: Ben Skeggs Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 80963d0..1947d61 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -273,6 +273,7 @@ bios_shadow(struct drm_device *dev) mthd->score = score_vbios(bios, mthd->rw); mthd->size = bios->length; mthd->data = bios->data; + bios->data = NULL; } while (mthd->score != 3 && (++mthd)->shadow); mthd = shadow_methods; @@ -281,7 +282,8 @@ bios_shadow(struct drm_device *dev) if (mthd->score > best->score) { kfree(best->data); best = mthd; - } + } else + kfree(mthd->data); } while ((++mthd)->shadow); if (best->score) { -- cgit v0.10.2 From 402976fe51b2d1a58a29ba06fa1ca5ace3a4cdcd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 29 Mar 2012 19:04:08 -0400 Subject: drm/radeon/kms: fix fans after resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On pre-R600 asics, the SpeedFanControl table is not executed as part of ASIC_Init as it is on newer asics. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=29412 Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index d1bd239..5ce9bf5 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -1306,8 +1306,11 @@ struct atom_context *atom_parse(struct card_info *card, void *bios) int atom_asic_init(struct atom_context *ctx) { + struct radeon_device *rdev = ctx->card->dev->dev_private; int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR); uint32_t ps[16]; + int ret; + memset(ps, 0, 64); ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR)); @@ -1317,7 +1320,17 @@ int atom_asic_init(struct atom_context *ctx) if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT)) return 1; - return atom_execute_table(ctx, ATOM_CMD_INIT, ps); + ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps); + if (ret) + return ret; + + memset(ps, 0, 64); + + if (rdev->family < CHIP_R600) { + if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL)) + atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps); + } + return ret; } void atom_destroy(struct atom_context *ctx) diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index 93cfe20..25fea63 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h @@ -44,6 +44,7 @@ #define ATOM_CMD_SETSCLK 0x0A #define ATOM_CMD_SETMCLK 0x0B #define ATOM_CMD_SETPCLK 0x0C +#define ATOM_CMD_SPDFANCNTL 0x39 #define ATOM_DATA_FWI_PTR 0xC #define ATOM_DATA_IIO_PTR 0x32 -- cgit v0.10.2 From fa9e855025b19e96e493ee00de7d933a9794f742 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Sat, 31 Mar 2012 13:29:25 +0400 Subject: mm, drm/udl: fixup vma flags on mmap There should be VM_MIXEDMAP, not VM_PFNMAP, because udl_gem_fault() inserts pages via vm_insert_page(). Other drm/gem drivers already do this. Signed-off-by: Konstantin Khlebnikov Cc: Dave Airlie Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 5340c5f..5367390 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -47,7 +47,7 @@ static struct vm_operations_struct udl_gem_vm_ops = { static const struct file_operations udl_driver_fops = { .owner = THIS_MODULE, .open = drm_open, - .mmap = drm_gem_mmap, + .mmap = udl_drm_gem_mmap, .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 1612954..96820d0 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -121,6 +121,7 @@ struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, int udl_gem_vmap(struct udl_gem_object *obj); void udl_gem_vunmap(struct udl_gem_object *obj); +int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 852642d..92f19ef 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -71,6 +71,20 @@ int udl_dumb_destroy(struct drm_file *file, struct drm_device *dev, return drm_gem_handle_delete(file, handle); } +int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + + ret = drm_gem_mmap(filp, vma); + if (ret) + return ret; + + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_flags |= VM_MIXEDMAP; + + return ret; +} + int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct udl_gem_object *obj = to_udl_bo(vma->vm_private_data); -- cgit v0.10.2 From e199fd422420d1620cf64fd9bdd4ff8bc255cc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 29 Mar 2012 16:47:43 +0200 Subject: drm/radeon: Don't dereference possibly-NULL pointer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Dan Carpenter Signed-off-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 6f70158..df6a4db 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -241,7 +241,8 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, domain_start = bo->rdev->mc.vram_start; else domain_start = bo->rdev->mc.gtt_start; - WARN_ON_ONCE((*gpu_addr - domain_start) > max_offset); + WARN_ON_ONCE(max_offset < + (radeon_bo_gpu_offset(bo) - domain_start)); } return 0; -- cgit v0.10.2 From 0fc7374bb5df938ef3d386e48ac9797d7651e9cc Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 2 Apr 2012 12:50:54 +0200 Subject: microblaze: Do not use tlb_skip in early_printk tlb_skip is valid only for MMU system. Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c index ec48587..aba1f9a9 100644 --- a/arch/microblaze/kernel/early_printk.c +++ b/arch/microblaze/kernel/early_printk.c @@ -176,6 +176,7 @@ void __init remap_early_printk(void) base_addr = (u32) ioremap(base_addr, PAGE_SIZE); printk(KERN_CONT "0x%x\n", base_addr); +#ifdef CONFIG_MMU /* * Early console is on the top of skipped TLB entries * decrease tlb_skip size ensure that hardcoded TLB entry will be @@ -189,6 +190,7 @@ void __init remap_early_printk(void) * cmp rX, orig_base_addr */ tlb_skip -= 1; +#endif } void __init disable_early_printk(void) -- cgit v0.10.2 From 0dd90aa9d6222e12201f05c0058e8741b7f66474 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 2 Apr 2012 12:55:47 +0200 Subject: microblaze: Fix ret_from_fork declaration ret_from_fork is used by noMMU system too. It should be the part of patch "Disintegrate asm/system.h for Microblaze" (sha1: c40d04df152a1111c5bbcb632278394dabd2b73d) Signed-off-by: Michal Simek diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index 510a8e1..bffb545 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h @@ -31,6 +31,8 @@ extern const struct seq_operations cpuinfo_op; /* Do necessary setup to start up a newly executed thread. */ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); +extern void ret_from_fork(void); + # endif /* __ASSEMBLY__ */ # ifndef CONFIG_MMU @@ -143,8 +145,6 @@ static inline void exit_thread(void) unsigned long get_wchan(struct task_struct *p); -extern void ret_from_fork(void); - /* The size allocated for kernel stacks. This _must_ be a power of two! */ # define KERNEL_STACK_SIZE 0x2000 -- cgit v0.10.2 From dba69d1092e291e257fb5673a3ad0e4c87878ebc Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Sun, 1 Apr 2012 13:53:36 -0300 Subject: x86, kvm: Call restore_sched_clock_state() only after %gs is initialized s2ram broke due to this KVM commit: b74f05d61b73 x86: kvmclock: abstract save/restore sched_clock_state restore_sched_clock_state() methods use percpu data, therefore they must run after %gs is initialized, but before mtrr_bp_restore() (due to lockstat using sched_clock). Move it to the correct place. Reported-and-tested-by: Konstantin Khlebnikov Signed-off-by: Marcelo Tosatti Cc: Avi Kivity Signed-off-by: Ingo Molnar diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 4793683..218cdb1 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -225,13 +225,13 @@ static void __restore_processor_state(struct saved_context *ctxt) fix_processor_context(); do_fpu_end(); + x86_platform.restore_sched_clock_state(); mtrr_bp_restore(); } /* Needed by apm.c */ void restore_processor_state(void) { - x86_platform.restore_sched_clock_state(); __restore_processor_state(&saved_context); } #ifdef CONFIG_X86_32 -- cgit v0.10.2 From cc22a938fc1db0c8ef5e693a69b159c4b851dab3 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Thu, 29 Mar 2012 20:55:48 -0300 Subject: drm/i915: add Ivy Bridge GT2 Server entries This adds PCI ID for IVB GT2 server variant which we were missing. Signed-off-by: Eugeni Dodonov [danvet: fix up conflict because the patch has been diffed against next. tsk.] Signed-Off-by: Daniel Vetter diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 5da67f1..7ea18a5 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -234,6 +234,7 @@ #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG 0x0166 #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB 0x0158 /* Server */ #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG 0x015A +#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A int intel_gmch_probe(struct pci_dev *pdev, struct agp_bridge_data *bridge); diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 5cf47ac..f493546 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1459,6 +1459,8 @@ static const struct intel_gtt_driver_description { "Ivybridge", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG, "Ivybridge", &sandybridge_gtt_driver }, + { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG, + "Ivybridge", &sandybridge_gtt_driver }, { 0, NULL, NULL } }; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c7d689e..77afd31 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -296,6 +296,7 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */ INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */ INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */ + INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */ {0, 0, 0} }; -- cgit v0.10.2 From 650dc07ec3b0eba8ff21da706d2b1876ada59fc3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Apr 2012 10:08:35 +0200 Subject: drm/i915: disable ppgtt on snb when dmar is enabled Totally unexpected that this regressed. Luckily it sounds like we just need to have dmar disable on the igfx, not the entire system. At least that's what a few days of testing between Tony Vroon and me indicates. Reported-by: Tony Vroon Cc: Tony Vroon Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43024 Acked-by: Chris Wilson Signed-Off-by: Daniel Vetter diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index f493546..7f025fb 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1190,7 +1190,6 @@ static inline int needs_idle_maps(void) { #ifdef CONFIG_INTEL_IOMMU const unsigned short gpu_devid = intel_private.pcidev->device; - extern int intel_iommu_gfx_mapped; /* Query intel_iommu to see if we need the workaround. Presumably that * was loaded first. diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9341eb8..8a62285 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1183,6 +1183,21 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) return can_switch; } +static bool +intel_enable_ppgtt(struct drm_device *dev) +{ + if (i915_enable_ppgtt >= 0) + return i915_enable_ppgtt; + +#ifdef CONFIG_INTEL_IOMMU + /* Disable ppgtt on SNB if VT-d is on. */ + if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) + return false; +#endif + + return true; +} + static int i915_load_gem_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1197,7 +1212,7 @@ static int i915_load_gem_init(struct drm_device *dev) drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size); mutex_lock(&dev->struct_mutex); - if (i915_enable_ppgtt && HAS_ALIASING_PPGTT(dev)) { + if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) { /* PPGTT pdes are stolen from global gtt ptes, so shrink the * aperture accordingly when using aliasing ppgtt. */ gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 77afd31..19d55bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -107,8 +107,8 @@ MODULE_PARM_DESC(enable_hangcheck, "WARNING: Disabling this can cause system wide hangs. " "(default: true)"); -bool i915_enable_ppgtt __read_mostly = 1; -module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, bool, 0600); +int i915_enable_ppgtt __read_mostly = -1; +module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600); MODULE_PARM_DESC(i915_enable_ppgtt, "Enable PPGTT (default: true)"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2c19227..5fabc6c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1086,7 +1086,7 @@ extern int i915_vbt_sdvo_panel_type __read_mostly; extern int i915_enable_rc6 __read_mostly; extern int i915_enable_fbc __read_mostly; extern bool i915_enable_hangcheck __read_mostly; -extern bool i915_enable_ppgtt __read_mostly; +extern int i915_enable_ppgtt __read_mostly; extern int i915_suspend(struct drm_device *dev, pm_message_t state); extern int i915_resume(struct drm_device *dev); diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 0a0001b..923afb5 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -44,4 +44,8 @@ void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, /* flag for GFDT type */ #define AGP_USER_CACHED_MEMORY_GFDT (1 << 3) +#ifdef CONFIG_INTEL_IOMMU +extern int intel_iommu_gfx_mapped; +#endif + #endif -- cgit v0.10.2 From fd36dfb89fa080255ddca0ddbab62b64c9288e78 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Apr 2012 10:39:43 -0300 Subject: ARM: mx53ard: Fix smsc911x driver probe Fix smsc911x driver probe by adding a fixed dummy regulator. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c index 753f4fc..0564198 100644 --- a/arch/arm/mach-imx/mach-mx53_ard.c +++ b/arch/arm/mach-imx/mach-mx53_ard.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -214,6 +216,11 @@ static int weim_cs_config(void) return 0; } +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vdd33a", "smsc911x"), + REGULATOR_SUPPLY("vddvario", "smsc911x"), +}; + void __init imx53_ard_common_init(void) { mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads, @@ -232,6 +239,7 @@ static void __init mx53_ard_board_init(void) imx53_ard_common_init(); mx53_ard_io_init(); + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); platform_add_devices(devices, ARRAY_SIZE(devices)); imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data); -- cgit v0.10.2 From da21d4dc1795be22d244fa29ea757f3994511880 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Apr 2012 10:39:44 -0300 Subject: ARM: mx31lite: Fix smsc911x driver probe Fix smsc911x driver probe by adding a fixed dummy regulator. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index ef80751..0abef5f 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -226,6 +228,11 @@ void __init mx31lite_map_io(void) static int mx31lite_baseboard; core_param(mx31lite_baseboard, mx31lite_baseboard, int, 0444); +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vdd33a", "smsc911x"), + REGULATOR_SUPPLY("vddvario", "smsc911x"), +}; + static void __init mx31lite_init(void) { int ret; @@ -259,6 +266,8 @@ static void __init mx31lite_init(void) if (usbh2_pdata.otg) imx31_add_mxc_ehci_hs(2, &usbh2_pdata); + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + /* SMSC9117 IRQ pin */ ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq"); if (ret) -- cgit v0.10.2 From 954c59acd3f9df6899f908004e3ff349a7cecd7b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Apr 2012 10:39:45 -0300 Subject: ARM: mx31lilly: Fix smsc911x driver probe Fix smsc911x driver probe by adding a fixed dummy regulator. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c index 02401bb..83714b0 100644 --- a/arch/arm/mach-imx/mach-mx31lilly.c +++ b/arch/arm/mach-imx/mach-mx31lilly.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -242,6 +244,11 @@ static struct platform_device *devices[] __initdata = { static int mx31lilly_baseboard; core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444); +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vdd33a", "smsc911x"), + REGULATOR_SUPPLY("vddvario", "smsc911x"), +}; + static void __init mx31lilly_board_init(void) { imx31_soc_init(); @@ -280,6 +287,8 @@ static void __init mx31lilly_board_init(void) imx31_add_spi_imx1(&spi1_pdata); spi_register_board_info(&mc13783_dev, 1); + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + platform_add_devices(devices, ARRAY_SIZE(devices)); /* USB */ -- cgit v0.10.2 From ccdf327843d1f61ffb7463ae5cdf4ca5f09f631b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Apr 2012 10:39:46 -0300 Subject: ARM: kzm_arm11_01: Fix smsc911x driver probe Fix smsc911x driver probe by adding a fixed dummy regulator. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c index fc78e80..15a26e9 100644 --- a/arch/arm/mach-imx/mach-kzm_arm11_01.c +++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -166,6 +168,11 @@ static struct platform_device kzm_smsc9118_device = { }, }; +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vdd33a", "smsc911x"), + REGULATOR_SUPPLY("vddvario", "smsc911x"), +}; + static int __init kzm_init_smsc9118(void) { /* @@ -175,6 +182,8 @@ static int __init kzm_init_smsc9118(void) gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2), "smsc9118-int"); gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2)); + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + return platform_device_register(&kzm_smsc9118_device); } #else -- cgit v0.10.2 From 7a4302a6a123e09b26fd7eae387e88e2d4dbc8c4 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Apr 2012 10:39:47 -0300 Subject: ARM: armadillo5x0: Fix smsc911x driver probe Fix smsc911x driver probe by adding a fixed dummy regulator. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index 27bc27e..c650145 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include @@ -479,6 +481,11 @@ static struct platform_device *devices[] __initdata = { &armadillo5x0_smc911x_device, }; +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vdd33a", "smsc911x"), + REGULATOR_SUPPLY("vddvario", "smsc911x"), +}; + /* * Perform board specific initializations */ @@ -489,6 +496,8 @@ static void __init armadillo5x0_init(void) mxc_iomux_setup_multiple_pins(armadillo5x0_pins, ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0"); + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + platform_add_devices(devices, ARRAY_SIZE(devices)); imx_add_gpio_keys(&armadillo5x0_button_data); imx31_add_imx_i2c1(NULL); -- cgit v0.10.2 From 83e3fa6f0193299f8b7180db588edd5ca61a3b82 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:37 -0400 Subject: irq_work: fix compile failure on MIPS from system.h split Builds of the MIPS platform ip32_defconfig fails as of commit 0195c00244dc ("Merge tag 'split-asm_system_h ...") because MIPS xchg() macro uses BUILD_BUG_ON and it was moved in commit b81947c646bf ("Disintegrate asm/system.h for MIPS"). The root cause is that the system.h split wasn't tested on a baseline with commit 6c03438edeb5 ("kernel.h: doesn't explicitly use bug.h, so don't include it.") Since this file uses BUG code in several other places besides the xchg call, simply make the inclusion explicit. Signed-off-by: Paul Gortmaker Acked-by: David Howells Signed-off-by: Linus Torvalds diff --git a/kernel/irq_work.c b/kernel/irq_work.c index c3c46c7..0c56d44 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -5,6 +5,7 @@ * context. The enqueueing is NMI-safe. */ +#include #include #include #include -- cgit v0.10.2 From 34f2c0ac111aaf090c7d2432dab532640870733a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:46 -0400 Subject: tile: fix multiple build failures from system.h dismantle Commit bd119c69239322caafdb64517a806037d0d0c70a "Disintegrate asm/system.h for Tile" created the asm/switch_to.h file, but did not add an include of it to all its users. Also, commit b4816afa3986704d1404fc48e931da5135820472 "Move the asm-generic/system.h xchg() implementation to asm-generic/cmpxchg.h" introduced the concept of asm/cmpxchg.h but the tile arch never got one. Fork the cmpxchg content out of the asm/atomic.h file to create one. Acked-by: David Howells Signed-off-by: Paul Gortmaker Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h index bb696da..f246142 100644 --- a/arch/tile/include/asm/atomic.h +++ b/arch/tile/include/asm/atomic.h @@ -17,6 +17,8 @@ #ifndef _ASM_TILE_ATOMIC_H #define _ASM_TILE_ATOMIC_H +#include + #ifndef __ASSEMBLY__ #include @@ -121,54 +123,6 @@ static inline int atomic_read(const atomic_t *v) */ #define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0) -/* Nonexistent functions intended to cause link errors. */ -extern unsigned long __xchg_called_with_bad_pointer(void); -extern unsigned long __cmpxchg_called_with_bad_pointer(void); - -#define xchg(ptr, x) \ - ({ \ - typeof(*(ptr)) __x; \ - switch (sizeof(*(ptr))) { \ - case 4: \ - __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \ - (atomic_t *)(ptr), \ - (u32)(typeof((x)-(x)))(x)); \ - break; \ - case 8: \ - __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \ - (atomic64_t *)(ptr), \ - (u64)(typeof((x)-(x)))(x)); \ - break; \ - default: \ - __xchg_called_with_bad_pointer(); \ - } \ - __x; \ - }) - -#define cmpxchg(ptr, o, n) \ - ({ \ - typeof(*(ptr)) __x; \ - switch (sizeof(*(ptr))) { \ - case 4: \ - __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \ - (atomic_t *)(ptr), \ - (u32)(typeof((o)-(o)))(o), \ - (u32)(typeof((n)-(n)))(n)); \ - break; \ - case 8: \ - __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \ - (atomic64_t *)(ptr), \ - (u64)(typeof((o)-(o)))(o), \ - (u64)(typeof((n)-(n)))(n)); \ - break; \ - default: \ - __cmpxchg_called_with_bad_pointer(); \ - } \ - __x; \ - }) - -#define tas(ptr) (xchg((ptr), 1)) - #endif /* __ASSEMBLY__ */ #ifndef __tilegx__ diff --git a/arch/tile/include/asm/cmpxchg.h b/arch/tile/include/asm/cmpxchg.h new file mode 100644 index 0000000..276f067 --- /dev/null +++ b/arch/tile/include/asm/cmpxchg.h @@ -0,0 +1,73 @@ +/* + * cmpxchg.h -- forked from asm/atomic.h with this copyright: + * + * Copyright 2010 Tilera Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + * + */ + +#ifndef _ASM_TILE_CMPXCHG_H +#define _ASM_TILE_CMPXCHG_H + +#ifndef __ASSEMBLY__ + +/* Nonexistent functions intended to cause link errors. */ +extern unsigned long __xchg_called_with_bad_pointer(void); +extern unsigned long __cmpxchg_called_with_bad_pointer(void); + +#define xchg(ptr, x) \ + ({ \ + typeof(*(ptr)) __x; \ + switch (sizeof(*(ptr))) { \ + case 4: \ + __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \ + (atomic_t *)(ptr), \ + (u32)(typeof((x)-(x)))(x)); \ + break; \ + case 8: \ + __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \ + (atomic64_t *)(ptr), \ + (u64)(typeof((x)-(x)))(x)); \ + break; \ + default: \ + __xchg_called_with_bad_pointer(); \ + } \ + __x; \ + }) + +#define cmpxchg(ptr, o, n) \ + ({ \ + typeof(*(ptr)) __x; \ + switch (sizeof(*(ptr))) { \ + case 4: \ + __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \ + (atomic_t *)(ptr), \ + (u32)(typeof((o)-(o)))(o), \ + (u32)(typeof((n)-(n)))(n)); \ + break; \ + case 8: \ + __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \ + (atomic64_t *)(ptr), \ + (u64)(typeof((o)-(o)))(o), \ + (u64)(typeof((n)-(n)))(n)); \ + break; \ + default: \ + __cmpxchg_called_with_bad_pointer(); \ + } \ + __x; \ + }) + +#define tas(ptr) (xchg((ptr), 1)) + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_TILE_CMPXCHG_H */ diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 30caeca..ee01b1c 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index 37ee4d0..0be6b01 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From 8d6951439ef524683057251f1231df232046b6b6 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 27 Mar 2012 13:47:57 -0400 Subject: arch/tile/Kconfig: remove pointless "!M386" test. Looks like a cut and paste bug from the x86 version. Signed-off-by: Chris Metcalf diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 11270ca..30413c1 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -12,7 +12,7 @@ config TILE select GENERIC_PENDING_IRQ if SMP select GENERIC_IRQ_SHOW select SYS_HYPERVISOR - select ARCH_HAVE_NMI_SAFE_CMPXCHG if !M386 + select ARCH_HAVE_NMI_SAFE_CMPXCHG # FIXME: investigate whether we need/want these options. # select HAVE_IOREMAP_PROT -- cgit v0.10.2 From 3d1e8a81cc81e62d13731e48c40760e60f31b0d5 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 27 Mar 2012 13:53:30 -0400 Subject: arch/tile/Kconfig: rename tile_defconfig to tilepro_defconfig We switched to using "tilepro" for the 32-bit stuff a while ago, but missed this one usage. Signed-off-by: Chris Metcalf diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 30413c1..30393aa 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -69,6 +69,9 @@ config ARCH_PHYS_ADDR_T_64BIT config ARCH_DMA_ADDR_T_64BIT def_bool y +config NEED_DMA_MAP_STATE + def_bool y + config LOCKDEP_SUPPORT def_bool y @@ -118,7 +121,7 @@ config 64BIT config ARCH_DEFCONFIG string - default "arch/tile/configs/tile_defconfig" if !TILEGX + default "arch/tile/configs/tilepro_defconfig" if !TILEGX default "arch/tile/configs/tilegx_defconfig" if TILEGX source "init/Kconfig" -- cgit v0.10.2 From 884197f7ea93dc2faf399060dc29cb0dbbda6937 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 27 Mar 2012 13:56:04 -0400 Subject: arch/tile/Kconfig: don't specify CONFIG_PAGE_OFFSET for 64-bit builds It's fixed at half the VA space and there's no point in configuring it. Signed-off-by: Chris Metcalf diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 30393aa..96033e2 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -243,6 +243,7 @@ endchoice config PAGE_OFFSET hex + depends on !64BIT default 0xF0000000 if VMSPLIT_3_75G default 0xE0000000 if VMSPLIT_3_5G default 0xB0000000 if VMSPLIT_2_75G -- cgit v0.10.2 From 327e8b6b25588ab906856a4e506b28c59422f11b Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 27 Mar 2012 14:04:57 -0400 Subject: arch/tile: fix typo in We aren't yet using this definition in the kernel, but fix it up before someone goes looking for it. Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/arch/spr_def.h b/arch/tile/include/arch/spr_def.h index f548efe..d6ba449 100644 --- a/arch/tile/include/arch/spr_def.h +++ b/arch/tile/include/arch/spr_def.h @@ -60,8 +60,8 @@ _concat4(SPR_IPI_EVENT_, CONFIG_KERNEL_PL,,) #define SPR_IPI_EVENT_RESET_K \ _concat4(SPR_IPI_EVENT_RESET_, CONFIG_KERNEL_PL,,) -#define SPR_IPI_MASK_SET_K \ - _concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,) +#define SPR_IPI_EVENT_SET_K \ + _concat4(SPR_IPI_EVENT_SET_, CONFIG_KERNEL_PL,,) #define INT_IPI_K \ _concat4(INT_IPI_, CONFIG_KERNEL_PL,,) -- cgit v0.10.2 From 07feea877d18453bbe4ad47fe2a365eebf56a7af Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 27 Mar 2012 14:10:03 -0400 Subject: arch/tile: revert comment for atomic64_add_unless(). It still returns whether @v was not @u, not the old value, unlike __atomic_add_unless(). Signed-off-by: Chris Metcalf Acked-by: Arun Sharma diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h index 466dc4a..54d1da8 100644 --- a/arch/tile/include/asm/atomic_32.h +++ b/arch/tile/include/asm/atomic_32.h @@ -200,7 +200,7 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v) * @u: ...unless v is equal to u. * * Atomically adds @a to @v, so long as @v was not already @u. - * Returns the old value of @v. + * Returns non-zero if @v was not @u, and zero otherwise. */ static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u) { -- cgit v0.10.2 From 664c100bce0070148131f8d49518015476c03cae Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 27 Mar 2012 14:17:05 -0400 Subject: arch/tile: fix gcc 4.6 warnings in Fix some signedness and variable usage warnings in change_bit() and test_and_change_bit(). Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/asm/bitops_64.h b/arch/tile/include/asm/bitops_64.h index 58d021a..60b87ee 100644 --- a/arch/tile/include/asm/bitops_64.h +++ b/arch/tile/include/asm/bitops_64.h @@ -38,10 +38,10 @@ static inline void clear_bit(unsigned nr, volatile unsigned long *addr) static inline void change_bit(unsigned nr, volatile unsigned long *addr) { - unsigned long old, mask = (1UL << (nr % BITS_PER_LONG)); - long guess, oldval; + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + unsigned long guess, oldval; addr += nr / BITS_PER_LONG; - old = *addr; + oldval = *addr; do { guess = oldval; oldval = atomic64_cmpxchg((atomic64_t *)addr, @@ -85,7 +85,7 @@ static inline int test_and_change_bit(unsigned nr, volatile unsigned long *addr) { unsigned long mask = (1UL << (nr % BITS_PER_LONG)); - long guess, oldval = *addr; + unsigned long guess, oldval; addr += nr / BITS_PER_LONG; oldval = *addr; do { -- cgit v0.10.2 From cbe224705e573cead57c4d4bed0c91efb564a344 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 27 Mar 2012 15:21:00 -0400 Subject: arch/tile: use 0 for IRQ_RESCHEDULE instead of 1 This avoids assigning IRQ 0 to PCI devices, because we've seen that doesn't always work well. Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/asm/irq.h b/arch/tile/include/asm/irq.h index f80f8ce..33cff9a 100644 --- a/arch/tile/include/asm/irq.h +++ b/arch/tile/include/asm/irq.h @@ -21,7 +21,7 @@ #define NR_IRQS 32 /* IRQ numbers used for linux IPIs. */ -#define IRQ_RESCHEDULE 1 +#define IRQ_RESCHEDULE 0 #define irq_canonicalize(irq) (irq) -- cgit v0.10.2 From b287f69676a34a9fc341de4d79a9c74e1959dec6 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 14:02:52 -0400 Subject: arch/tile: avoid false corrupt frame warning in early boot With lockstat we can end up trying to get a backtrace before "high_memory" is initialized, so don't worry about range testing if it is zero. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index ee01b1c..2d5ef61 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -286,7 +286,7 @@ struct task_struct *validate_current(void) static struct task_struct corrupt = { .comm = "" }; struct task_struct *tsk = current; if (unlikely((unsigned long)tsk < PAGE_OFFSET || - (void *)tsk > high_memory || + (high_memory && (void *)tsk > high_memory) || ((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) { pr_err("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer); tsk = &corrupt; -- cgit v0.10.2 From efb734d8ed040b053f53fd53589ed5d9c9b5cd04 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 14:05:04 -0400 Subject: arch/tile: make sure to build memcpy_user_64 without frame pointer Add a comment explaining why this is important, and add a CFLAGS_REMOVE clause to the Makefile to make sure it happens. Signed-off-by: Chris Metcalf diff --git a/arch/tile/lib/Makefile b/arch/tile/lib/Makefile index 0c26086..985f598 100644 --- a/arch/tile/lib/Makefile +++ b/arch/tile/lib/Makefile @@ -7,6 +7,7 @@ lib-y = cacheflush.o checksum.o cpumask.o delay.o uaccess.o \ strchr_$(BITS).o strlen_$(BITS).o ifeq ($(CONFIG_TILEGX),y) +CFLAGS_REMOVE_memcpy_user_64.o = -fno-omit-frame-pointer lib-y += memcpy_user_64.o else lib-y += atomic_32.o atomic_asm_32.o memcpy_tile64.o diff --git a/arch/tile/lib/memcpy_user_64.c b/arch/tile/lib/memcpy_user_64.c index 4763b3a..37440ca 100644 --- a/arch/tile/lib/memcpy_user_64.c +++ b/arch/tile/lib/memcpy_user_64.c @@ -14,7 +14,13 @@ * Do memcpy(), but trap and return "n" when a load or store faults. * * Note: this idiom only works when memcpy() compiles to a leaf function. - * If "sp" is updated during memcpy, the "jrp lr" will be incorrect. + * Here leaf function not only means it does not have calls, but also + * requires no stack operations (sp, stack frame pointer) and no + * use of callee-saved registers, else "jrp lr" will be incorrect since + * unwinding stack frame is bypassed. Since memcpy() is not complex so + * these conditions are satisfied here, but we need to be careful when + * modifying this file. This is not a clean solution but is the best + * one so far. * * Also note that we are capturing "n" from the containing scope here. */ -- cgit v0.10.2 From 5f639fdcd8c186c8128c616e94a7e7b159c968ae Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 14:06:14 -0400 Subject: arch/tile: various bugs in stack backtracer Fix a long-standing bug in the stack backtracer where we would print garbage to the console instead of kernel function names, if the kernel wasn't built with symbol support (e.g. mboot). Make sure to tag every line of userspace backtrace output if we actually have the mmap_sem, since that way if there's no tag, we know that it's because we couldn't trylock the semaphore. Stop doing a TLB flush and examining page tables during backtrace. Instead, just trust that __copy_from_user_inatomic() will properly fault and return a failure, which it should do in all cases. Fix a latent bug where the backtracer would directly examine a signal context in user space, rather than copying it safely to kernel memory first. This meant that a race with another thread could potentially have caused a kernel panic. Guard against unaligned sp when trying to restart backtrace at an interrupt or signal handler point in the kernel backtracer. Report kernel symbolic information for the call instruction rather than for the following instruction. We still report the actual numeric address corresponding to the instruction after the call, for the sake of consistency with the normal expectations for stack backtracers. Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/asm/stack.h b/arch/tile/include/asm/stack.h index 4d97a2d..0e9d382a 100644 --- a/arch/tile/include/asm/stack.h +++ b/arch/tile/include/asm/stack.h @@ -25,7 +25,6 @@ struct KBacktraceIterator { BacktraceIterator it; struct task_struct *task; /* task we are backtracing */ - pte_t *pgtable; /* page table for user space access */ int end; /* iteration complete. */ int new_context; /* new context is starting */ int profile; /* profiling, so stop on async intrpt */ diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index 0be6b01..b2f44c2 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c @@ -21,9 +21,10 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -45,72 +46,23 @@ static int in_kernel_stack(struct KBacktraceIterator *kbt, unsigned long sp) return sp >= kstack_base && sp < kstack_base + THREAD_SIZE; } -/* Is address valid for reading? */ -static int valid_address(struct KBacktraceIterator *kbt, unsigned long address) -{ - HV_PTE *l1_pgtable = kbt->pgtable; - HV_PTE *l2_pgtable; - unsigned long pfn; - HV_PTE pte; - struct page *page; - - if (l1_pgtable == NULL) - return 0; /* can't read user space in other tasks */ - -#ifdef CONFIG_64BIT - /* Find the real l1_pgtable by looking in the l0_pgtable. */ - pte = l1_pgtable[HV_L0_INDEX(address)]; - if (!hv_pte_get_present(pte)) - return 0; - pfn = hv_pte_get_pfn(pte); - if (pte_huge(pte)) { - if (!pfn_valid(pfn)) { - pr_err("L0 huge page has bad pfn %#lx\n", pfn); - return 0; - } - return hv_pte_get_present(pte) && hv_pte_get_readable(pte); - } - page = pfn_to_page(pfn); - BUG_ON(PageHighMem(page)); /* No HIGHMEM on 64-bit. */ - l1_pgtable = (HV_PTE *)pfn_to_kaddr(pfn); -#endif - pte = l1_pgtable[HV_L1_INDEX(address)]; - if (!hv_pte_get_present(pte)) - return 0; - pfn = hv_pte_get_pfn(pte); - if (pte_huge(pte)) { - if (!pfn_valid(pfn)) { - pr_err("huge page has bad pfn %#lx\n", pfn); - return 0; - } - return hv_pte_get_present(pte) && hv_pte_get_readable(pte); - } - - page = pfn_to_page(pfn); - if (PageHighMem(page)) { - pr_err("L2 page table not in LOWMEM (%#llx)\n", - HV_PFN_TO_CPA(pfn)); - return 0; - } - l2_pgtable = (HV_PTE *)pfn_to_kaddr(pfn); - pte = l2_pgtable[HV_L2_INDEX(address)]; - return hv_pte_get_present(pte) && hv_pte_get_readable(pte); -} - /* Callback for backtracer; basically a glorified memcpy */ static bool read_memory_func(void *result, unsigned long address, unsigned int size, void *vkbt) { int retval; struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt; + + if (address == 0) + return 0; if (__kernel_text_address(address)) { /* OK to read kernel code. */ } else if (address >= PAGE_OFFSET) { /* We only tolerate kernel-space reads of this task's stack */ if (!in_kernel_stack(kbt, address)) return 0; - } else if (!valid_address(kbt, address)) { - return 0; /* invalid user-space address */ + } else if (!kbt->is_current) { + return 0; /* can't read from other user address spaces */ } pagefault_disable(); retval = __copy_from_user_inatomic(result, @@ -128,6 +80,8 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) unsigned long sp = kbt->it.sp; struct pt_regs *p; + if (sp % sizeof(long) != 0) + return NULL; if (!in_kernel_stack(kbt, sp)) return NULL; if (!in_kernel_stack(kbt, sp + C_ABI_SAVE_AREA_SIZE + PTREGS_SIZE-1)) @@ -170,27 +124,27 @@ static int is_sigreturn(unsigned long pc) } /* Return a pt_regs pointer for a valid signal handler frame */ -static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt) +static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt, + struct rt_sigframe* kframe) { BacktraceIterator *b = &kbt->it; - if (b->pc == VDSO_BASE) { - struct rt_sigframe *frame; - unsigned long sigframe_top = - b->sp + sizeof(struct rt_sigframe) - 1; - if (!valid_address(kbt, b->sp) || - !valid_address(kbt, sigframe_top)) { - if (kbt->verbose) - pr_err(" (odd signal: sp %#lx?)\n", - (unsigned long)(b->sp)); + if (b->pc == VDSO_BASE && b->sp < PAGE_OFFSET && + b->sp % sizeof(long) == 0) { + int retval; + pagefault_disable(); + retval = __copy_from_user_inatomic( + kframe, (void __user __force *)b->sp, + sizeof(*kframe)); + pagefault_enable(); + if (retval != 0 || + (unsigned int)(kframe->info.si_signo) >= _NSIG) return NULL; - } - frame = (struct rt_sigframe *)b->sp; if (kbt->verbose) { pr_err(" \n", - frame->info.si_signo); + kframe->info.si_signo); } - return (struct pt_regs *)&frame->uc.uc_mcontext; + return (struct pt_regs *)&kframe->uc.uc_mcontext; } return NULL; } @@ -203,10 +157,11 @@ static int KBacktraceIterator_is_sigreturn(struct KBacktraceIterator *kbt) static int KBacktraceIterator_restart(struct KBacktraceIterator *kbt) { struct pt_regs *p; + struct rt_sigframe kframe; p = valid_fault_handler(kbt); if (p == NULL) - p = valid_sigframe(kbt); + p = valid_sigframe(kbt, &kframe); if (p == NULL) return 0; backtrace_init(&kbt->it, read_memory_func, kbt, @@ -266,41 +221,19 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt, /* * Set up callback information. We grab the kernel stack base - * so we will allow reads of that address range, and if we're - * asking about the current process we grab the page table - * so we can check user accesses before trying to read them. - * We flush the TLB to avoid any weird skew issues. + * so we will allow reads of that address range. */ - is_current = (t == NULL); + is_current = (t == NULL || t == current); kbt->is_current = is_current; if (is_current) t = validate_current(); kbt->task = t; - kbt->pgtable = NULL; kbt->verbose = 0; /* override in caller if desired */ kbt->profile = 0; /* override in caller if desired */ kbt->end = KBT_ONGOING; - kbt->new_context = 0; - if (is_current) { - HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; - if (pgdir_pa == (unsigned long)swapper_pg_dir - PAGE_OFFSET) { - /* - * Not just an optimization: this also allows - * this to work at all before va/pa mappings - * are set up. - */ - kbt->pgtable = swapper_pg_dir; - } else { - struct page *page = pfn_to_page(PFN_DOWN(pgdir_pa)); - if (!PageHighMem(page)) - kbt->pgtable = __va(pgdir_pa); - else - pr_err("page table not in LOWMEM" - " (%#llx)\n", pgdir_pa); - } - local_flush_tlb_all(); + kbt->new_context = 1; + if (is_current) validate_stack(regs); - } if (regs == NULL) { if (is_current || t->state == TASK_RUNNING) { @@ -346,6 +279,78 @@ void KBacktraceIterator_next(struct KBacktraceIterator *kbt) } EXPORT_SYMBOL(KBacktraceIterator_next); +static void describe_addr(struct KBacktraceIterator *kbt, + unsigned long address, + int have_mmap_sem, char *buf, size_t bufsize) +{ + struct vm_area_struct *vma; + size_t namelen, remaining; + unsigned long size, offset, adjust; + char *p, *modname; + const char *name; + int rc; + + /* + * Look one byte back for every caller frame (i.e. those that + * aren't a new context) so we look up symbol data for the + * call itself, not the following instruction, which may be on + * a different line (or in a different function). + */ + adjust = !kbt->new_context; + address -= adjust; + + if (address >= PAGE_OFFSET) { + /* Handle kernel symbols. */ + BUG_ON(bufsize < KSYM_NAME_LEN); + name = kallsyms_lookup(address, &size, &offset, + &modname, buf); + if (name == NULL) { + buf[0] = '\0'; + return; + } + namelen = strlen(buf); + remaining = (bufsize - 1) - namelen; + p = buf + namelen; + rc = snprintf(p, remaining, "+%#lx/%#lx ", + offset + adjust, size); + if (modname && rc < remaining) + snprintf(p + rc, remaining - rc, "[%s] ", modname); + buf[bufsize-1] = '\0'; + return; + } + + /* If we don't have the mmap_sem, we can't show any more info. */ + buf[0] = '\0'; + if (!have_mmap_sem) + return; + + /* Find vma info. */ + vma = find_vma(kbt->task->mm, address); + if (vma == NULL || address < vma->vm_start) { + snprintf(buf, bufsize, "[unmapped address] "); + return; + } + + if (vma->vm_file) { + char *s; + p = d_path(&vma->vm_file->f_path, buf, bufsize); + if (IS_ERR(p)) + p = "?"; + s = strrchr(p, '/'); + if (s) + p = s+1; + } else { + p = "anon"; + } + + /* Generate a string description of the vma info. */ + namelen = strlen(p); + remaining = (bufsize - 1) - namelen; + memmove(buf, p, namelen); + snprintf(buf + namelen, remaining, "[%lx+%lx] ", + vma->vm_start, vma->vm_end - vma->vm_start); +} + /* * This method wraps the backtracer's more generic support. * It is only invoked from the architecture-specific code; show_stack() @@ -354,6 +359,7 @@ EXPORT_SYMBOL(KBacktraceIterator_next); void tile_show_stack(struct KBacktraceIterator *kbt, int headers) { int i; + int have_mmap_sem = 0; if (headers) { /* @@ -370,31 +376,16 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers) kbt->verbose = 1; i = 0; for (; !KBacktraceIterator_end(kbt); KBacktraceIterator_next(kbt)) { - char *modname; - const char *name; - unsigned long address = kbt->it.pc; - unsigned long offset, size; char namebuf[KSYM_NAME_LEN+100]; + unsigned long address = kbt->it.pc; - if (address >= PAGE_OFFSET) - name = kallsyms_lookup(address, &size, &offset, - &modname, namebuf); - else - name = NULL; - - if (!name) - namebuf[0] = '\0'; - else { - size_t namelen = strlen(namebuf); - size_t remaining = (sizeof(namebuf) - 1) - namelen; - char *p = namebuf + namelen; - int rc = snprintf(p, remaining, "+%#lx/%#lx ", - offset, size); - if (modname && rc < remaining) - snprintf(p + rc, remaining - rc, - "[%s] ", modname); - namebuf[sizeof(namebuf)-1] = '\0'; - } + /* Try to acquire the mmap_sem as we pass into userspace. */ + if (address < PAGE_OFFSET && !have_mmap_sem && kbt->task->mm) + have_mmap_sem = + down_read_trylock(&kbt->task->mm->mmap_sem); + + describe_addr(kbt, address, have_mmap_sem, + namebuf, sizeof(namebuf)); pr_err(" frame %d: 0x%lx %s(sp 0x%lx)\n", i++, address, namebuf, (unsigned long)(kbt->it.sp)); @@ -409,6 +400,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers) pr_err("Stack dump stopped; next frame identical to this one\n"); if (headers) pr_err("Stack dump complete\n"); + if (have_mmap_sem) + up_read(&kbt->task->mm->mmap_sem); } EXPORT_SYMBOL(tile_show_stack); -- cgit v0.10.2 From e17235382dbb05f70146e141e4b780fd069050dc Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 14:52:00 -0400 Subject: arch/tile: work around a hardware issue with the return-address stack In certain circumstances we need to do a bunch of jump-and-link instructions to fill the hardware return-address stack with nonzero values. Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h index 5f20f92..e28c3df4 100644 --- a/arch/tile/include/asm/traps.h +++ b/arch/tile/include/asm/traps.h @@ -64,7 +64,11 @@ void do_breakpoint(struct pt_regs *, int fault_num); #ifdef __tilegx__ +/* kernel/single_step.c */ void gx_singlestep_handle(struct pt_regs *, int fault_num); + +/* kernel/intvec_64.S */ +void fill_ra_stack(void); #endif -#endif /* _ASM_TILE_SYSCALLS_H */ +#endif /* _ASM_TILE_TRAPS_H */ diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 79c93e1..2c181c8 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S @@ -1156,6 +1156,18 @@ int_unalign: push_extra_callee_saves r0 j do_trap +/* Fill the return address stack with nonzero entries. */ +STD_ENTRY(fill_ra_stack) + { + move r0, lr + jal 1f + } +1: jal 2f +2: jal 3f +3: jal 4f +4: jrp r0 + STD_ENDPROC(fill_ra_stack) + /* Include .intrpt1 array of interrupt vectors */ .section ".intrpt1", "ax" diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 2bb6602..32acfd9 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c @@ -289,7 +289,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, address = regs->pc; break; #ifdef __tilegx__ - case INT_ILL_TRANS: + case INT_ILL_TRANS: { + /* Avoid a hardware erratum with the return address stack. */ + fill_ra_stack(); + signo = SIGSEGV; code = SEGV_MAPERR; if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK) @@ -297,6 +300,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, else address = 0; /* FIXME: GX: single-step for address */ break; + } #endif default: panic("Unexpected do_trap interrupt number %d", fault_num); -- cgit v0.10.2 From a714ffff36a581756ec3b001f47e8e5e96a9fa0e Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:23:54 -0400 Subject: arch/tile: fix up some minor trap handling issues We now respond to MEM_ERROR traps (e.g. an atomic instruction to non-cacheable memory) with a SIGBUS. We also no longer generate a console crash message if a user process die due to a SIGTRAP. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 2c181c8..005535d 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S @@ -1178,7 +1178,7 @@ STD_ENTRY(fill_ra_stack) #define do_hardwall_trap bad_intr #endif - int_hand INT_MEM_ERROR, MEM_ERROR, bad_intr + int_hand INT_MEM_ERROR, MEM_ERROR, do_trap int_hand INT_SINGLE_STEP_3, SINGLE_STEP_3, bad_intr #if CONFIG_KERNEL_PL == 2 int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, gx_singlestep_handle diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 32acfd9..73cff81 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c @@ -200,7 +200,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, { siginfo_t info = { 0 }; int signo, code; - unsigned long address; + unsigned long address = 0; bundle_bits instr; /* Re-enable interrupts. */ @@ -223,6 +223,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, } switch (fault_num) { + case INT_MEM_ERROR: + signo = SIGBUS; + code = BUS_OBJERR; + break; case INT_ILL: if (copy_from_user(&instr, (void __user *)regs->pc, sizeof(instr))) { @@ -312,7 +316,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, info.si_addr = (void __user *)address; if (signo == SIGILL) info.si_trapno = fault_num; - trace_unhandled_signal("trap", regs, address, signo); + if (signo != SIGTRAP) + trace_unhandled_signal("trap", regs, address, signo); force_sig_info(signo, &info, current); } -- cgit v0.10.2 From 51bcdf8879f7920946c90087e6160680812a44bd Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:29:28 -0400 Subject: arch/tile: fix a couple of comments that needed updating Not associated with any code changes, so I'm just lumping these comment changes into a commit by themselves. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 5f85d8b..023e2e1 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -913,6 +913,13 @@ void __cpuinit setup_cpu(int boot) #ifdef CONFIG_BLK_DEV_INITRD +/* + * Note that the kernel can potentially support other compression + * techniques than gz, though we don't do so by default. If we ever + * decide to do so we can either look for other filename extensions, + * or just allow a file with this name to be compressed with an + * arbitrary compressor (somewhat counterintuitively). + */ static int __initdata set_initramfs_file; static char __initdata initramfs_file[128] = "initramfs.cpio.gz"; @@ -928,9 +935,9 @@ static int __init setup_initramfs_file(char *str) early_param("initramfs_file", setup_initramfs_file); /* - * We look for an additional "initramfs.cpio.gz" file in the hvfs. + * We look for an "initramfs.cpio.gz" file in the hvfs. * If there is one, we allocate some memory for it and it will be - * unpacked to the initramfs after any built-in initramfs_data. + * unpacked to the initramfs. */ static void __init load_hv_initrd(void) { diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index cba30e9..cac17c4 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c @@ -130,7 +130,7 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) } /* - * Handle a fault on the vmalloc or module mapping area + * Handle a fault on the vmalloc area. */ static inline int vmalloc_fault(pgd_t *pgd, unsigned long address) { -- cgit v0.10.2 From 6731aa9eae3e94b094a44d2aea02387a39202fbc Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:30:19 -0400 Subject: arch/tile/Makefile: use KCFLAGS when figuring out the libgcc path. Signed-off-by: Chris Metcalf diff --git a/arch/tile/Makefile b/arch/tile/Makefile index 17acce7..5e4d3b9 100644 --- a/arch/tile/Makefile +++ b/arch/tile/Makefile @@ -30,7 +30,8 @@ ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"") KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS) endif -LIBGCC_PATH := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) +LIBGCC_PATH := \ + $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name) # Provide the path to use for "make defconfig". KBUILD_DEFCONFIG := $(ARCH)_defconfig -- cgit v0.10.2 From 48292738d06d7b46d861652ef59bd03be931c2c9 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:34:52 -0400 Subject: arch/tile: don't wait for migrating PTEs in an NMI handler Doing so raises the possibility of self-deadlock if we are waiting for a backtrace for an oprofile or perf interrupt while we are in the middle of migrating our own stack page. Signed-off-by: Chris Metcalf diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index cac17c4..a1da473 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c @@ -203,9 +203,14 @@ static pgd_t *get_current_pgd(void) * interrupt or a critical region, and must do as little as possible. * Similarly, we can't use atomic ops here, since we may be handling a * fault caused by an atomic op access. + * + * If we find a migrating PTE while we're in an NMI context, and we're + * at a PC that has a registered exception handler, we don't wait, + * since this thread may (e.g.) have been interrupted while migrating + * its own stack, which would then cause us to self-deadlock. */ static int handle_migrating_pte(pgd_t *pgd, int fault_num, - unsigned long address, + unsigned long address, unsigned long pc, int is_kernel_mode, int write) { pud_t *pud; @@ -227,6 +232,8 @@ static int handle_migrating_pte(pgd_t *pgd, int fault_num, pte_offset_kernel(pmd, address); pteval = *pte; if (pte_migrating(pteval)) { + if (in_nmi() && search_exception_tables(pc)) + return 0; wait_for_migration(pte); return 1; } @@ -300,7 +307,7 @@ static int handle_page_fault(struct pt_regs *regs, * rather than trying to patch up the existing PTE. */ pgd = get_current_pgd(); - if (handle_migrating_pte(pgd, fault_num, address, + if (handle_migrating_pte(pgd, fault_num, address, regs->pc, is_kernel_mode, write)) return 1; @@ -665,7 +672,7 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num, */ if (fault_num == INT_DTLB_ACCESS) write = 1; - if (handle_migrating_pte(pgd, fault_num, address, 1, write)) + if (handle_migrating_pte(pgd, fault_num, address, pc, 1, write)) return state; /* Return zero so that we continue on with normal fault handling. */ -- cgit v0.10.2 From 12400f1f22ad7651efa1d3d06dd8b6b178d19ea3 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:36:53 -0400 Subject: arch/tile: don't set the homecache of a PTE unless appropriate We make sure not to try to set the home for an MMIO PTE (on tilegx) or a PTE that isn't referencing memory managed by Linux. Signed-off-by: Chris Metcalf diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c index 8730369..6b9a109 100644 --- a/arch/tile/mm/pgtable.c +++ b/arch/tile/mm/pgtable.c @@ -469,10 +469,18 @@ void __set_pte(pte_t *ptep, pte_t pte) void set_pte(pte_t *ptep, pte_t pte) { - struct page *page = pfn_to_page(pte_pfn(pte)); - - /* Update the home of a PTE if necessary */ - pte = pte_set_home(pte, page_home(page)); + if (pte_present(pte) && + (!CHIP_HAS_MMIO() || hv_pte_get_mode(pte) != HV_PTE_MODE_MMIO)) { + /* The PTE actually references physical memory. */ + unsigned long pfn = pte_pfn(pte); + if (pfn_valid(pfn)) { + /* Update the home of the PTE from the struct page. */ + pte = pte_set_home(pte, page_home(pfn_to_page(pfn))); + } else if (hv_pte_get_mode(pte) == 0) { + /* remap_pfn_range(), etc, must supply PTE mode. */ + panic("set_pte(): out-of-range PFN and mode 0\n"); + } + } __set_pte(ptep, pte); } -- cgit v0.10.2 From b230ff2d5c53bb79e1121554cd3c827e5c1b70fd Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:40:50 -0400 Subject: arch/tile: don't enable irqs unconditionally in page fault handler If we took a page fault while we had interrupts disabled, we shouldn't enable them in the page fault handler. Signed-off-by: Chris Metcalf diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index a1da473..22e58f5 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c @@ -342,9 +342,12 @@ static int handle_page_fault(struct pt_regs *regs, /* * If we're trying to touch user-space addresses, we must * be either at PL0, or else with interrupts enabled in the - * kernel, so either way we can re-enable interrupts here. + * kernel, so either way we can re-enable interrupts here + * unless we are doing atomic access to user space with + * interrupts disabled. */ - local_irq_enable(); + if (!(regs->flags & PT_FLAGS_DISABLE_IRQ)) + local_irq_enable(); mm = tsk->mm; -- cgit v0.10.2 From 7a7039ee71811222310b431aee246eb78dd0d401 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:42:27 -0400 Subject: arch/tile: fix bug in loading kernels larger than 16 MB Previously we only handled kernels up to a single huge page in size. Now we create additional PTEs appropriately. Signed-off-by: Chris Metcalf diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c index 830c490..8400d3f 100644 --- a/arch/tile/mm/init.c +++ b/arch/tile/mm/init.c @@ -557,6 +557,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) address = MEM_SV_INTRPT; pmd = get_pmd(pgtables, address); + pfn = 0; /* code starts at PA 0 */ if (ktext_small) { /* Allocate an L2 PTE for the kernel text */ int cpu = 0; @@ -579,10 +580,15 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) } BUG_ON(address != (unsigned long)_stext); - pfn = 0; /* code starts at PA 0 */ - pte = alloc_pte(); - for (pte_ofs = 0; address < (unsigned long)_einittext; - pfn++, pte_ofs++, address += PAGE_SIZE) { + pte = NULL; + for (; address < (unsigned long)_einittext; + pfn++, address += PAGE_SIZE) { + pte_ofs = pte_index(address); + if (pte_ofs == 0) { + if (pte) + assign_pte(pmd++, pte); + pte = alloc_pte(); + } if (!ktext_local) { prot = set_remote_cache_cpu(prot, cpu); cpu = cpumask_next(cpu, &ktext_mask); @@ -591,7 +597,8 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) } pte[pte_ofs] = pfn_pte(pfn, prot); } - assign_pte(pmd, pte); + if (pte) + assign_pte(pmd, pte); } else { pte_t pteval = pfn_pte(0, PAGE_KERNEL_EXEC); pteval = pte_mkhuge(pteval); @@ -614,7 +621,9 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) else pteval = hv_pte_set_mode(pteval, HV_PTE_MODE_CACHE_NO_L3); - *(pte_t *)pmd = pteval; + for (; address < (unsigned long)_einittext; + pfn += PFN_DOWN(HPAGE_SIZE), address += HPAGE_SIZE) + *(pte_t *)(pmd++) = pfn_pte(pfn, pteval); } /* Set swapper_pgprot here so it is flushed to memory right away. */ -- cgit v0.10.2 From 444eef1ba40546690a77b2af4cba7d4561e7bba5 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:43:20 -0400 Subject: arch/tile: fix bug in delay_backoff() We were carefully computing a value to use for the number of loops to spin for, and then ignoring it. Signed-off-by: Chris Metcalf diff --git a/arch/tile/lib/spinlock_common.h b/arch/tile/lib/spinlock_common.h index c101098..6ac3750 100644 --- a/arch/tile/lib/spinlock_common.h +++ b/arch/tile/lib/spinlock_common.h @@ -60,5 +60,5 @@ static void delay_backoff(int iterations) loops += __insn_crc32_32(stack_pointer, get_cycles_low()) & (loops - 1); - relax(1 << exponent); + relax(loops); } -- cgit v0.10.2 From 5f220704127ae70db519fabbda4ece649eadac7f Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:44:10 -0400 Subject: arch/tile: don't leak kernel memory when we unload modules We were failing to track the memory when we allocated it. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index b90ab99..98d4769 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c @@ -67,6 +67,8 @@ void *module_alloc(unsigned long size) area = __get_vm_area(size, VM_ALLOC, MEM_MODULE_START, MEM_MODULE_END); if (!area) goto error; + area->nr_pages = npages; + area->pages = pages; if (map_vm_area(area, prot_rwx, &pages)) { vunmap(area->addr); -- cgit v0.10.2 From 719ea79e330c5e1a17fb7e4cf352a81e4c84cff5 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:50:08 -0400 Subject: arch/tile: fix up locking in pgtable.c slightly We should be holding the init_mm.page_table_lock in shatter_huge_page() since we are modifying the kernel page tables. Then, only if we are walking the other root page tables to update them, do we want to take the pgd_lock. Add a comment about taking the pgd_lock that we always do it with interrupts disabled and therefore are not at risk from the tlbflush IPI deadlock as is seen on x86. Signed-off-by: Chris Metcalf diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c index 6b9a109..2410aa8 100644 --- a/arch/tile/mm/pgtable.c +++ b/arch/tile/mm/pgtable.c @@ -177,14 +177,10 @@ void shatter_huge_page(unsigned long addr) if (!pmd_huge_page(*pmd)) return; - /* - * Grab the pgd_lock, since we may need it to walk the pgd_list, - * and since we need some kind of lock here to avoid races. - */ - spin_lock_irqsave(&pgd_lock, flags); + spin_lock_irqsave(&init_mm.page_table_lock, flags); if (!pmd_huge_page(*pmd)) { /* Lost the race to convert the huge page. */ - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock_irqrestore(&init_mm.page_table_lock, flags); return; } @@ -194,6 +190,7 @@ void shatter_huge_page(unsigned long addr) #ifdef __PAGETABLE_PMD_FOLDED /* Walk every pgd on the system and update the pmd there. */ + spin_lock(&pgd_lock); list_for_each(pos, &pgd_list) { pmd_t *copy_pmd; pgd = list_to_pgd(pos) + pgd_index(addr); @@ -201,6 +198,7 @@ void shatter_huge_page(unsigned long addr) copy_pmd = pmd_offset(pud, addr); __set_pmd(copy_pmd, *pmd); } + spin_unlock(&pgd_lock); #endif /* Tell every cpu to notice the change. */ @@ -208,7 +206,7 @@ void shatter_huge_page(unsigned long addr) cpu_possible_mask, NULL, 0); /* Hold the lock until the TLB flush is finished to avoid races. */ - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock_irqrestore(&init_mm.page_table_lock, flags); } /* @@ -217,9 +215,13 @@ void shatter_huge_page(unsigned long addr) * against pageattr.c; it is the unique case in which a valid change * of kernel pagetables can't be lazily synchronized by vmalloc faults. * vmalloc faults work because attached pagetables are never freed. - * The locking scheme was chosen on the basis of manfred's - * recommendations and having no core impact whatsoever. - * -- wli + * + * The lock is always taken with interrupts disabled, unlike on x86 + * and other platforms, because we need to take the lock in + * shatter_huge_page(), which may be called from an interrupt context. + * We are not at risk from the tlbflush IPI deadlock that was seen on + * x86, since we use the flush_remote() API to have the hypervisor do + * the TLB flushes regardless of irq disabling. */ DEFINE_SPINLOCK(pgd_lock); LIST_HEAD(pgd_list); -- cgit v0.10.2 From bfffe79bc29a9c4c817d5f51590961220e26db1a Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:56:18 -0400 Subject: arch/tile: use proper memparse() for "maxmem" options This is more standard and avoids having to remember what units the options actually take. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 023e2e1..f3598e7 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -103,13 +103,11 @@ unsigned long __initdata pci_reserve_end_pfn = -1U; static int __init setup_maxmem(char *str) { - long maxmem_mb; - if (str == NULL || strict_strtol(str, 0, &maxmem_mb) != 0 || - maxmem_mb == 0) + unsigned long long maxmem; + if (str == NULL || (maxmem = memparse(str, NULL)) == 0) return -EINVAL; - maxmem_pfn = (maxmem_mb >> (HPAGE_SHIFT - 20)) << - (HPAGE_SHIFT - PAGE_SHIFT); + maxmem_pfn = (maxmem >> HPAGE_SHIFT) << (HPAGE_SHIFT - PAGE_SHIFT); pr_info("Forcing RAM used to no more than %dMB\n", maxmem_pfn >> (20 - PAGE_SHIFT)); return 0; @@ -119,14 +117,15 @@ early_param("maxmem", setup_maxmem); static int __init setup_maxnodemem(char *str) { char *endp; - long maxnodemem_mb, node; + unsigned long long maxnodemem; + long node; node = str ? simple_strtoul(str, &endp, 0) : INT_MAX; - if (node >= MAX_NUMNODES || *endp != ':' || - strict_strtol(endp+1, 0, &maxnodemem_mb) != 0) + if (node >= MAX_NUMNODES || *endp != ':') return -EINVAL; - maxnodemem_pfn[node] = (maxnodemem_mb >> (HPAGE_SHIFT - 20)) << + maxnodemem = memparse(endp+1, NULL); + maxnodemem_pfn[node] = (maxnodemem >> HPAGE_SHIFT) << (HPAGE_SHIFT - PAGE_SHIFT); pr_info("Forcing RAM used on node %ld to no more than %dMB\n", node, maxnodemem_pfn[node] >> (20 - PAGE_SHIFT)); -- cgit v0.10.2 From 8c92ba6c327ee5089dec1e92eaa82927bee63d6d Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:57:18 -0400 Subject: arch/tile: add "nop" after "nap" to help GX idle power draw This avoids the hardware istream prefetcher doing unnecessary work. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index 431e9ae..ec91568 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S @@ -85,6 +85,7 @@ STD_ENTRY(cpu_idle_on_new_stack) /* Loop forever on a nap during SMP boot. */ STD_ENTRY(smp_nap) nap + nop /* avoid provoking the icache prefetch with a jump */ j smp_nap /* we are not architecturally guaranteed not to exit nap */ jrp lr /* clue in the backtracer */ STD_ENDPROC(smp_nap) @@ -105,5 +106,6 @@ STD_ENTRY(_cpu_idle) .global _cpu_idle_nap _cpu_idle_nap: nap + nop /* avoid provoking the icache prefetch with a jump */ jrp lr STD_ENDPROC(_cpu_idle) diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c index a44e103..7b6df8c 100644 --- a/arch/tile/kernel/smp.c +++ b/arch/tile/kernel/smp.c @@ -103,7 +103,7 @@ static void smp_stop_cpu_interrupt(void) set_cpu_online(smp_processor_id(), 0); arch_local_irq_disable_all(); for (;;) - asm("nap"); + asm("nap; nop"); } /* This function calls the 'stop' function on all other CPUs in the system. */ -- cgit v0.10.2 From cb210ee3a81afab7c64777635cc18899a2bdd9a5 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 15:59:11 -0400 Subject: arch/tile: implement panic_smp_self_stop() This allows the later-panicking tiles to wait in a lower power state until they get interrupted with an smp_send_stop(). Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c index 7b6df8c..91da0f7 100644 --- a/arch/tile/kernel/smp.c +++ b/arch/tile/kernel/smp.c @@ -113,6 +113,12 @@ void smp_send_stop(void) send_IPI_allbutself(MSG_TAG_STOP_CPU); } +/* On panic, just wait; we may get an smp_send_stop() later on. */ +void panic_smp_self_stop(void) +{ + while (1) + asm("nap; nop"); +} /* * Dispatch code called from hv_message_intr() for HV_MSG_TILE hv messages. -- cgit v0.10.2 From 2858f856021340f3730fa8639dd520a2e4331f7f Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 16:11:09 -0400 Subject: arch/tile: fix single-stepping over swint1 instructions on tilegx If we are single-stepping and make a syscall, we call ptrace_notify() explicitly on the return path back to user space, since we are returning to a pc value set artificially to the next instruction, and otherwise we won't register that we stepped over the syscall instruction (swint1). Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 005535d..fdff17c 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -1039,11 +1040,25 @@ handle_syscall: /* Do syscall trace again, if requested. */ ld r30, r31 - andi r30, r30, _TIF_SYSCALL_TRACE - beqzt r30, 1f + andi r0, r30, _TIF_SYSCALL_TRACE + { + andi r0, r30, _TIF_SINGLESTEP + beqzt r0, 1f + } jal do_syscall_trace FEEDBACK_REENTER(handle_syscall) -1: j .Lresume_userspace /* jump into middle of interrupt_return */ + andi r0, r30, _TIF_SINGLESTEP + +1: beqzt r0, 2f + + /* Single stepping -- notify ptrace. */ + { + movei r0, SIGTRAP + jal ptrace_notify + } + FEEDBACK_REENTER(handle_syscall) + +2: j .Lresume_userspace /* jump into middle of interrupt_return */ .Lcompat_syscall: /* -- cgit v0.10.2 From 918cbd38aef83de3a2516299bcb230caf59462a0 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 16:14:40 -0400 Subject: arch/tile: fix pointer cast in cacheflush.c Pragmatically it couldn't be wrong to cast pointers to long to compare them (since all kernel addresses are in the top half of VA space), but it's more correct to cast to unsigned long. Signed-off-by: Chris Metcalf diff --git a/arch/tile/lib/cacheflush.c b/arch/tile/lib/cacheflush.c index 8928aac..6af2b97 100644 --- a/arch/tile/lib/cacheflush.c +++ b/arch/tile/lib/cacheflush.c @@ -109,7 +109,7 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh) /* Figure out how far back we need to go. */ base = p - (step_size * (load_count - 2)); - if ((long)base < (long)buffer) + if ((unsigned long)base < (unsigned long)buffer) base = buffer; /* -- cgit v0.10.2 From e81510e0c3800dc730e0c544e3949f7bde368c2b Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 29 Mar 2012 16:19:45 -0400 Subject: arch/tile: export the page_home() function. This avois a bug in modules trying to use the function. Signed-off-by: Chris Metcalf diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c index 1cc6ae4..499f737 100644 --- a/arch/tile/mm/homecache.c +++ b/arch/tile/mm/homecache.c @@ -394,6 +394,7 @@ int page_home(struct page *page) return pte_to_home(*virt_to_pte(NULL, kva)); } } +EXPORT_SYMBOL(page_home); void homecache_change_page_home(struct page *page, int order, int home) { -- cgit v0.10.2 From b14f21906774be181627412fed5b6b5fae2b53a2 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 15:29:40 -0400 Subject: arch/tile: stop mentioning the "kvm" subdirectory It causes "make clean" to fail, for example. Once we have KVM support complete, we'll reinstate the subdir reference. Signed-off-by: Chris Metcalf diff --git a/arch/tile/Makefile b/arch/tile/Makefile index 5e4d3b9..9520bc5 100644 --- a/arch/tile/Makefile +++ b/arch/tile/Makefile @@ -54,8 +54,6 @@ libs-y += $(LIBGCC_PATH) # See arch/tile/Kbuild for content of core part of the kernel core-y += arch/tile/ -core-$(CONFIG_KVM) += arch/tile/kvm/ - ifdef TILERA_ROOT INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot endif -- cgit v0.10.2 From ab306cae660e524edbeb8889e4e23d3c97717b9c Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 15:46:29 -0400 Subject: arch/tile: use atomic exchange in arch_write_unlock() This idiom is used elsewhere when we do an unlock by writing a zero, but I missed it here. Using an atomic operation avoids waiting on the write buffer for the unlocking write to be sent to the home cache. Signed-off-by: Chris Metcalf diff --git a/arch/tile/include/asm/spinlock_64.h b/arch/tile/include/asm/spinlock_64.h index 72be590..5f8b6a0 100644 --- a/arch/tile/include/asm/spinlock_64.h +++ b/arch/tile/include/asm/spinlock_64.h @@ -137,7 +137,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) static inline void arch_write_unlock(arch_rwlock_t *rw) { __insn_mf(); - rw->lock = 0; + __insn_exch4(&rw->lock, 0); /* Avoid waiting in the write buffer. */ } static inline int arch_read_trylock(arch_rwlock_t *rw) -- cgit v0.10.2 From 54229ff359250ce7292dbeb59f157a2d3b67e30c Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 15:47:38 -0400 Subject: arch/tile: fix finv_buffer_remote() for tilegx There were some correctness issues with this code that are now fixed with this change. The change is likely less performant than it could be, but it should no longer be vulnerable to any races with memory operations on the memory network while invalidating a range of memory. This code is run infrequently so performance isn't critical, but correctness definitely is. Signed-off-by: Chris Metcalf diff --git a/arch/tile/lib/cacheflush.c b/arch/tile/lib/cacheflush.c index 6af2b97..db4fb89 100644 --- a/arch/tile/lib/cacheflush.c +++ b/arch/tile/lib/cacheflush.c @@ -39,7 +39,21 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh) { char *p, *base; size_t step_size, load_count; + + /* + * On TILEPro the striping granularity is a fixed 8KB; on + * TILE-Gx it is configurable, and we rely on the fact that + * the hypervisor always configures maximum striping, so that + * bits 9 and 10 of the PA are part of the stripe function, so + * every 512 bytes we hit a striping boundary. + * + */ +#ifdef __tilegx__ + const unsigned long STRIPE_WIDTH = 512; +#else const unsigned long STRIPE_WIDTH = 8192; +#endif + #ifdef __tilegx__ /* * On TILE-Gx, we must disable the dstream prefetcher before doing @@ -74,7 +88,7 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh) * memory, that one load would be sufficient, but since we may * be, we also need to back up to the last load issued to * another memory controller, which would be the point where - * we crossed an 8KB boundary (the granularity of striping + * we crossed a "striping" boundary (the granularity of striping * across memory controllers). Keep backing up and doing this * until we are before the beginning of the buffer, or have * hit all the controllers. @@ -88,12 +102,22 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh) * every cache line on a full memory stripe on each * controller" that we simply do that, to simplify the logic. * - * FIXME: See bug 9535 for some issues with this code. + * On TILE-Gx the hash-for-home function is much more complex, + * with the upshot being we can't readily guarantee we have + * hit both entries in the 128-entry AMT that were hit by any + * load in the entire range, so we just re-load them all. + * With larger buffers, we may want to consider using a hypervisor + * trap to issue loads directly to each hash-for-home tile for + * each controller (doing it from Linux would trash the TLB). */ if (hfh) { step_size = L2_CACHE_BYTES; +#ifdef __tilegx__ + load_count = (size + L2_CACHE_BYTES - 1) / L2_CACHE_BYTES; +#else load_count = (STRIPE_WIDTH / L2_CACHE_BYTES) * (1 << CHIP_LOG_NUM_MSHIMS()); +#endif } else { step_size = STRIPE_WIDTH; load_count = (1 << CHIP_LOG_NUM_MSHIMS()); -- cgit v0.10.2 From cdd8e16feba87a3fc2bb1885d36f895a2a3288bf Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 16:24:41 -0400 Subject: arch/tile: return SIGBUS for addresses that are unaligned AND invalid Previously we were returning SIGSEGV in this case. It seems cleaner to return SIGBUS since the hardware figures out alignment traps before TLB violations, so SIGBUS is the "more correct" signal. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index bc1eb58..9efbc13 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c @@ -153,6 +153,25 @@ static tile_bundle_bits rewrite_load_store_unaligned( if (((unsigned long)addr % size) == 0) return bundle; + /* + * Return SIGBUS with the unaligned address, if requested. + * Note that we return SIGBUS even for completely invalid addresses + * as long as they are in fact unaligned; this matches what the + * tilepro hardware would be doing, if it could provide us with the + * actual bad address in an SPR, which it doesn't. + */ + if (unaligned_fixup == 0) { + siginfo_t info = { + .si_signo = SIGBUS, + .si_code = BUS_ADRALN, + .si_addr = addr + }; + trace_unhandled_signal("unaligned trap", regs, + (unsigned long)addr, SIGBUS); + force_sig_info(info.si_signo, &info, current); + return (tilepro_bundle_bits) 0; + } + #ifndef __LITTLE_ENDIAN # error We assume little-endian representation with copy_xx_user size 2 here #endif @@ -192,18 +211,6 @@ static tile_bundle_bits rewrite_load_store_unaligned( return (tile_bundle_bits) 0; } - if (unaligned_fixup == 0) { - siginfo_t info = { - .si_signo = SIGBUS, - .si_code = BUS_ADRALN, - .si_addr = addr - }; - trace_unhandled_signal("unaligned trap", regs, - (unsigned long)addr, SIGBUS); - force_sig_info(info.si_signo, &info, current); - return (tile_bundle_bits) 0; - } - if (unaligned_printk || unaligned_fixup_count == 0) { pr_info("Process %d/%s: PC %#lx: Fixup of" " unaligned %s at %#lx.\n", -- cgit v0.10.2 From b1760c847ff9d04fba7cdbef005a0ad805311c6d Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 16:27:20 -0400 Subject: arch/tile: remove bogus performance optimization We were re-homing the initial task's kernel stack on the boot cpu, but in fact it's better to let it stay globally homed, since that task isn't bound to the boot cpu anyway. This is more of a general cleanup than an actual performance optimization, but it removes code, which is a good thing. :-) Signed-off-by: Chris Metcalf diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c index 8400d3f..6a9d20d 100644 --- a/arch/tile/mm/init.c +++ b/arch/tile/mm/init.c @@ -254,11 +254,6 @@ static pgprot_t __init init_pgprot(ulong address) return construct_pgprot(PAGE_KERNEL_RO, PAGE_HOME_IMMUTABLE); } - /* As a performance optimization, keep the boot init stack here. */ - if (address >= (ulong)&init_thread_union && - address < (ulong)&init_thread_union + THREAD_SIZE) - return construct_pgprot(PAGE_KERNEL, smp_processor_id()); - #ifndef __tilegx__ #if !ATOMIC_LOCKS_FOUND_VIA_TABLE() /* Force the atomic_locks[] array page to be hash-for-home. */ -- cgit v0.10.2 From e1d5c0195075abaa45cd04ca397dbeaa0d18c490 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 16:29:06 -0400 Subject: arch/tile: avoid accidentally unmasking NMI-type interrupt accidentally The return path as we reload registers and core state requires that r30 hold a boolean indicating whether we are returning from an NMI, but in a couple of cases we weren't setting this properly, with the result that we could accidentally unmask the NMI interrupt(s), which could cause confusion. Now we set r30 in every place where we jump into the interrupt return path. Signed-off-by: Chris Metcalf diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index aecc8ed..5d56a1e 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -799,6 +799,10 @@ handle_interrupt: * This routine takes a boolean in r30 indicating if this is an NMI. * If so, we also expect a boolean in r31 indicating whether to * re-enable the oprofile interrupts. + * + * Note that .Lresume_userspace is jumped to directly in several + * places, and we need to make sure r30 is set correctly in those + * callers as well. */ STD_ENTRY(interrupt_return) /* If we're resuming to kernel space, don't check thread flags. */ @@ -1237,7 +1241,10 @@ handle_syscall: bzt r30, 1f jal do_syscall_trace FEEDBACK_REENTER(handle_syscall) -1: j .Lresume_userspace /* jump into middle of interrupt_return */ +1: { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } .Linvalid_syscall: /* Report an invalid syscall back to the user program */ @@ -1246,7 +1253,10 @@ handle_syscall: movei r28, -ENOSYS } sw r29, r28 - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(handle_syscall) /* Return the address for oprofile to suppress in backtraces. */ @@ -1262,7 +1272,10 @@ STD_ENTRY(ret_from_fork) jal sim_notify_fork jal schedule_tail FEEDBACK_REENTER(ret_from_fork) - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(ret_from_fork) /* @@ -1376,7 +1389,10 @@ handle_ill: jal send_sigtrap /* issue a SIGTRAP */ FEEDBACK_REENTER(handle_ill) - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } .Ldispatch_normal_ill: { diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index fdff17c..49d9d66 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S @@ -606,6 +606,10 @@ handle_interrupt: * This routine takes a boolean in r30 indicating if this is an NMI. * If so, we also expect a boolean in r31 indicating whether to * re-enable the oprofile interrupts. + * + * Note that .Lresume_userspace is jumped to directly in several + * places, and we need to make sure r30 is set correctly in those + * callers as well. */ STD_ENTRY(interrupt_return) /* If we're resuming to kernel space, don't check thread flags. */ @@ -1058,7 +1062,10 @@ handle_syscall: } FEEDBACK_REENTER(handle_syscall) -2: j .Lresume_userspace /* jump into middle of interrupt_return */ +2: { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } .Lcompat_syscall: /* @@ -1092,7 +1099,10 @@ handle_syscall: movei r28, -ENOSYS } st r29, r28 - j .Lresume_userspace /* jump into middle of interrupt_return */ + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(handle_syscall) /* Return the address for oprofile to suppress in backtraces. */ @@ -1108,7 +1118,10 @@ STD_ENTRY(ret_from_fork) jal sim_notify_fork jal schedule_tail FEEDBACK_REENTER(ret_from_fork) - j .Lresume_userspace + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } STD_ENDPROC(ret_from_fork) /* Various stub interrupt handlers and syscall handlers */ -- cgit v0.10.2 From e2e110d7596656e2badd21c48713bd01e1b40f44 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 18:58:37 -0400 Subject: edac: say "TILEGx" not "TILEPro" for the tilegx edac driver This is just an aesthetic change but it was silly to say TILEPro when booting up on the tilegx architecture. Signed-off-by: Chris Metcalf diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index 1d5cf06..e99d009 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -145,7 +145,11 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev) mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->mod_name = DRV_NAME; +#ifdef __tilegx__ + mci->ctl_name = "TILEGx_Memory_Controller"; +#else mci->ctl_name = "TILEPro_Memory_Controller"; +#endif mci->dev_name = dev_name(&pdev->dev); mci->edac_check = tile_edac_check; -- cgit v0.10.2 From 16418bb1da8a685e639c6c4f2d3096f762e8b0fb Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 19:03:04 -0400 Subject: tile-srom.c driver: minor code cleanup Signed-off-by: Chris Metcalf diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c index 4dc0194..3b22a60 100644 --- a/drivers/char/tile-srom.c +++ b/drivers/char/tile-srom.c @@ -194,17 +194,17 @@ static ssize_t srom_read(struct file *filp, char __user *buf, hv_retval = _srom_read(srom->hv_devhdl, kernbuf, *f_pos, bytes_this_pass); - if (hv_retval > 0) { - if (copy_to_user(buf, kernbuf, hv_retval) != 0) { - retval = -EFAULT; - break; - } - } else if (hv_retval <= 0) { + if (hv_retval <= 0) { if (retval == 0) retval = hv_retval; break; } + if (copy_to_user(buf, kernbuf, hv_retval) != 0) { + retval = -EFAULT; + break; + } + retval += hv_retval; *f_pos += hv_retval; buf += hv_retval; -- cgit v0.10.2 From 92795672898d5ee1faa557c498c078123d20e827 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 30 Mar 2012 19:23:35 -0400 Subject: tilepro ethernet driver: fix a few minor issues This commit fixes a number of issues seen with the driver: - Improve handling of return credits to the hardware shim - Use skb_frag_size() appropriately - Fix driver so it works properly with netpoll for console over UDP Signed-off-by: Chris Metcalf diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index 261356c..75e5905 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@ -342,6 +342,21 @@ inline int __netio_fastio1(u32 fastio_index, u32 arg0) } +static void tile_net_return_credit(struct tile_net_cpu *info) +{ + struct tile_netio_queue *queue = &info->queue; + netio_queue_user_impl_t *qup = &queue->__user_part; + + /* Return four credits after every fourth packet. */ + if (--qup->__receive_credit_remaining == 0) { + u32 interval = qup->__receive_credit_interval; + qup->__receive_credit_remaining = interval; + __netio_fastio_return_credits(qup->__fastio_index, interval); + } +} + + + /* * Provide a linux buffer to LIPP. */ @@ -864,19 +879,11 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index) stats->rx_packets++; stats->rx_bytes += len; - - if (small) - info->num_needed_small_buffers++; - else - info->num_needed_large_buffers++; } - /* Return four credits after every fourth packet. */ - if (--qup->__receive_credit_remaining == 0) { - u32 interval = qup->__receive_credit_interval; - qup->__receive_credit_remaining = interval; - __netio_fastio_return_credits(qup->__fastio_index, interval); - } + /* ISSUE: It would be nice to defer this until the packet has */ + /* actually been processed. */ + tile_net_return_credit(info); /* Consume this packet. */ qup->__packet_receive_read = index2; @@ -1543,7 +1550,7 @@ static int tile_net_drain_lipp_buffers(struct tile_net_priv *priv) /* Drain all the LIPP buffers. */ while (true) { - int buffer; + unsigned int buffer; /* NOTE: This should never fail. */ if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&buffer, @@ -1707,7 +1714,7 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags, if (!hash_default) { void *va = pfn_to_kaddr(pfn) + f->page_offset; BUG_ON(PageHighMem(skb_frag_page(f))); - finv_buffer_remote(va, f->size, 0); + finv_buffer_remote(va, skb_frag_size(f), 0); } cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset; @@ -1735,8 +1742,8 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags, * Sometimes, if "sendfile()" requires copying, we will be called with * "data" containing the header and payload, with "frags" being empty. * - * In theory, "sh->nr_frags" could be 3, but in practice, it seems - * that this will never actually happen. + * Sometimes, for example when using NFS over TCP, a single segment can + * span 3 fragments, which must be handled carefully in LEPP. * * See "emulate_large_send_offload()" for some reference code, which * does not handle checksumming. @@ -1844,10 +1851,8 @@ static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&priv->eq_lock, irqflags); - /* - * Handle completions if needed to make room. - * HACK: Spin until there is sufficient room. - */ + /* Handle completions if needed to make room. */ + /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */ if (lepp_num_free_comp_slots(eq) == 0) { nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0); if (nolds == 0) { @@ -1861,6 +1866,7 @@ busy: cmd_tail = eq->cmd_tail; /* Prepare to advance, detecting full queue. */ + /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */ cmd_next = cmd_tail + cmd_size; if (cmd_tail < cmd_head && cmd_next >= cmd_head) goto busy; @@ -2023,10 +2029,8 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&priv->eq_lock, irqflags); - /* - * Handle completions if needed to make room. - * HACK: Spin until there is sufficient room. - */ + /* Handle completions if needed to make room. */ + /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */ if (lepp_num_free_comp_slots(eq) == 0) { nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0); if (nolds == 0) { @@ -2040,6 +2044,7 @@ busy: cmd_tail = eq->cmd_tail; /* Copy the commands, or fail. */ + /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */ for (i = 0; i < num_frags; i++) { /* Prepare to advance, detecting full queue. */ @@ -2261,6 +2266,23 @@ static int tile_net_get_mac(struct net_device *dev) return 0; } + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +static void tile_net_netpoll(struct net_device *dev) +{ + struct tile_net_priv *priv = netdev_priv(dev); + disable_percpu_irq(priv->intr_id); + tile_net_handle_ingress_interrupt(priv->intr_id, dev); + enable_percpu_irq(priv->intr_id, 0); +} +#endif + + static const struct net_device_ops tile_net_ops = { .ndo_open = tile_net_open, .ndo_stop = tile_net_stop, @@ -2269,7 +2291,10 @@ static const struct net_device_ops tile_net_ops = { .ndo_get_stats = tile_net_get_stats, .ndo_change_mtu = tile_net_change_mtu, .ndo_tx_timeout = tile_net_tx_timeout, - .ndo_set_mac_address = tile_net_set_mac_address + .ndo_set_mac_address = tile_net_set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tile_net_netpoll, +#endif }; @@ -2409,7 +2434,7 @@ static void tile_net_cleanup(void) */ static int tile_net_init_module(void) { - pr_info("Tilera IPP Net Driver\n"); + pr_info("Tilera Network Driver\n"); tile_net_devs[0] = tile_net_dev_init("xgbe0"); tile_net_devs[1] = tile_net_dev_init("xgbe1"); -- cgit v0.10.2 From 91445c72cac7cb48f383fc6e44221e244cc32f6e Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Sat, 31 Mar 2012 09:46:03 -0400 Subject: MAINTAINERS: update EDAC information The bluesmoke mailing list no longer works, so use linux-edac@vger.kernel.org. And, use a less restrictive pattern so all drivers/edac changes go to linux-edac as well. Borislav suggested I just push this through the tile tree since there is currently no core edac maintainer (emails to Doug Thompson bounce). Acked-by: Borislav Petkov Signed-off-by: Chris Metcalf diff --git a/MAINTAINERS b/MAINTAINERS index eecf344..ef04eaa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2451,17 +2451,17 @@ F: fs/ecryptfs/ EDAC-CORE M: Doug Thompson -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Supported F: Documentation/edac.txt -F: drivers/edac/edac_* +F: drivers/edac/ F: include/linux/edac.h EDAC-AMD64 M: Doug Thompson M: Borislav Petkov -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Supported F: drivers/edac/amd64_edac* @@ -2469,35 +2469,35 @@ F: drivers/edac/amd64_edac* EDAC-E752X M: Mark Gross M: Doug Thompson -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/e752x_edac.c EDAC-E7XXX M: Doug Thompson -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/e7xxx_edac.c EDAC-I82443BXGX M: Tim Small -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i82443bxgx_edac.c EDAC-I3000 M: Jason Uhlenkott -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i3000_edac.c EDAC-I5000 M: Doug Thompson -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i5000_edac.c @@ -2526,21 +2526,21 @@ F: drivers/edac/i7core_edac.c EDAC-I82975X M: Ranganathan Desikan M: "Arvind R." -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i82975x_edac.c EDAC-PASEMI M: Egor Martovetsky -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/pasemi_edac.c EDAC-R82600 M: Tim Small -L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) +L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/r82600_edac.c -- cgit v0.10.2 From 00a62d4bc9b9a0388abee5c5ea946b9631b149d5 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Mon, 2 Apr 2012 13:17:37 -0400 Subject: drivers/net/ethernet/tile: fix netdev_alloc_skb() bombing Commit dae2e9f430c46c29e3f771110094bd3da3625aa4 changed dev_alloc_skb() to netdev_alloc_skb(), adding a dev pointer, but erroneously used "->" instead of "." for a struct member when accessing the dev pointer. This change fixes the build breakage. Signed-off-by: Chris Metcalf diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index 75e5905..3d501ec 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@ -448,7 +448,7 @@ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info, struct sk_buff **skb_ptr; /* Request 96 extra bytes for alignment purposes. */ - skb = netdev_alloc_skb(info->napi->dev, len + padding); + skb = netdev_alloc_skb(info->napi.dev, len + padding); if (skb == NULL) return false; -- cgit v0.10.2 From b443caf12f9ee14e9843e53d4d929319e637275a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:38 -0400 Subject: ARM: mach-msm: fix compile fail from system.h fallout To fix: In file included from arm/boot/compressed/misc.c:28:0: arm/mach-msm/include/mach/uncompress.h: In function 'putc': arch/arm/mach-msm/include/mach/uncompress.h:48:3: error: implicit declaration of function 'smp_mb' [-Werror=implicit-function-declaration] The putc does a cpu_relax which for this platform is smp_mb. Bisect indicates the 1st failing commit as: 0195c00244dc ("Merge tag 'split-asm_system_h...") Signed-off-by: Paul Gortmaker Acked-by: David Howells Acked-by: David Brown Signed-off-by: Linus Torvalds diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h index 169a840..c14011f 100644 --- a/arch/arm/mach-msm/include/mach/uncompress.h +++ b/arch/arm/mach-msm/include/mach/uncompress.h @@ -16,6 +16,7 @@ #ifndef __ASM_ARCH_MSM_UNCOMPRESS_H #define __ASM_ARCH_MSM_UNCOMPRESS_H +#include #include #include -- cgit v0.10.2 From 3d92e05118262379f76a220772b666dfddb77a9d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:40 -0400 Subject: avr32: fix build failures from mis-naming of atmel_nand.h Commit bf4289cba02b ("ATMEL: fix nand ecc support") indicated that it wanted to "Move platform data to a common header include/linux/platform_data/atmel_nand.h" and the new header even had re-include protectors with: #ifndef __ATMEL_NAND_H__ However, the file that was added was simply called atmel.h and this caused avr32 defconfig to fail with: In file included from arch/avr32/boards/atstk1000/setup.c:22: arch/avr32/mach-at32ap/include/mach/board.h:10:44: error: linux/platform_data/atmel_nand.h: No such file or directory In file included from arch/avr32/boards/atstk1000/setup.c:22: arch/avr32/mach-at32ap/include/mach/board.h:121: warning: 'struct atmel_nand_data' declared inside parameter list arch/avr32/mach-at32ap/include/mach/board.h:121: warning: its scope is only this definition or declaration, which is probably not what you want make[2]: *** [arch/avr32/boards/atstk1000/setup.o] Error 1 It seems the scope of the file contents will expand beyond just nand, so ignore the original intention, and fix up the users who reference the bad name with the _nand suffix. CC: Jean-Christophe PLAGNIOL-VILLARD CC: David Woodhouse Acked-by: Hans-Christian Egtvedt Signed-off-by: Paul Gortmaker Signed-off-by: Linus Torvalds diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index 7173386..70742ec 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define GPIO_PIN_NONE (-1) diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index d056263..b0f2c56 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h @@ -4,8 +4,8 @@ * GPL v2 Only */ -#ifndef __ATMEL_NAND_H__ -#define __ATMEL_NAND_H__ +#ifndef __ATMEL_H__ +#define __ATMEL_H__ #include @@ -24,4 +24,4 @@ struct atmel_nand_data { unsigned int num_parts; }; -#endif /* __ATMEL_NAND_H__ */ +#endif /* __ATMEL_H__ */ -- cgit v0.10.2 From 1512cdc3572dac34a1809764f9a646cde7e82407 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:41 -0400 Subject: blackfin: fix cmpxchg build fails from system.h fallout Commit 3bed8d67469c ("Disintegrate asm/system.h for Blackfin [ver #2]") introduced arch/blackfin/include/asm/cmpxchg.h but has it also including the asm-generic one which causes this: CC arch/blackfin/kernel/asm-offsets.s In file included from arch/blackfin/include/asm/cmpxchg.h:125:0, from arch/blackfin/include/asm/atomic.h:10, from include/linux/atomic.h:4, from include/linux/spinlock.h:384, from include/linux/seqlock.h:29, from include/linux/time.h:8, from include/linux/timex.h:56, from include/linux/sched.h:57, from arch/blackfin/kernel/asm-offsets.c:10: include/asm-generic/cmpxchg.h:24:15: error: redefinition of '__xchg' arch/blackfin/include/asm/cmpxchg.h:82:29: note: previous definition of '__xchg' was here make[2]: *** [arch/blackfin/kernel/asm-offsets.s] Error 1 It really only needs two simple defines from asm-generic, so just use those instead. Cc: Bob Liu Cc: Mike Frysinger Signed-off-by: Paul Gortmaker Acked-by: David Howells Signed-off-by: Linus Torvalds diff --git a/arch/blackfin/include/asm/cmpxchg.h b/arch/blackfin/include/asm/cmpxchg.h index ba2484f..c05868c 100644 --- a/arch/blackfin/include/asm/cmpxchg.h +++ b/arch/blackfin/include/asm/cmpxchg.h @@ -122,7 +122,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, (unsigned long)(n), sizeof(*(ptr)))) #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) -#include +#define cmpxchg(ptr, o, n) cmpxchg_local((ptr), (o), (n)) +#define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) #endif /* !CONFIG_SMP */ -- cgit v0.10.2 From 9e5228ce0b9619bde7dcd6c51fb26e2401cfe81a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:42 -0400 Subject: parisc: fix missing cmpxchg file error from system.h split Commit b4816afa3986 ("Move the asm-generic/system.h xchg() implementation to asm-generic/cmpxchg.h") introduced the concept of asm/cmpxchg.h but the parisc arch never got one. Fork the cmpxchg content out of the asm/atomic.h file to create one. Some minor whitespace fixups were done on the block of code that created the new file. Cc: "James E.J. Bottomley" Cc: Helge Deller Signed-off-by: Paul Gortmaker Acked-by: David Howells Signed-off-by: Linus Torvalds diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 3ae5607..6c6defc 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -6,6 +6,7 @@ #define _ASM_PARISC_ATOMIC_H_ #include +#include /* * Atomic operations that C can't guarantee us. Useful for @@ -48,112 +49,6 @@ extern arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned; # define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0) #endif -/* This should get optimized out since it's never called. -** Or get a link error if xchg is used "wrong". -*/ -extern void __xchg_called_with_bad_pointer(void); - - -/* __xchg32/64 defined in arch/parisc/lib/bitops.c */ -extern unsigned long __xchg8(char, char *); -extern unsigned long __xchg32(int, int *); -#ifdef CONFIG_64BIT -extern unsigned long __xchg64(unsigned long, unsigned long *); -#endif - -/* optimizer better get rid of switch since size is a constant */ -static __inline__ unsigned long -__xchg(unsigned long x, __volatile__ void * ptr, int size) -{ - switch(size) { -#ifdef CONFIG_64BIT - case 8: return __xchg64(x,(unsigned long *) ptr); -#endif - case 4: return __xchg32((int) x, (int *) ptr); - case 1: return __xchg8((char) x, (char *) ptr); - } - __xchg_called_with_bad_pointer(); - return x; -} - - -/* -** REVISIT - Abandoned use of LDCW in xchg() for now: -** o need to test sizeof(*ptr) to avoid clearing adjacent bytes -** o and while we are at it, could CONFIG_64BIT code use LDCD too? -** -** if (__builtin_constant_p(x) && (x == NULL)) -** if (((unsigned long)p & 0xf) == 0) -** return __ldcw(p); -*/ -#define xchg(ptr,x) \ - ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) - - -#define __HAVE_ARCH_CMPXCHG 1 - -/* bug catcher for when unsupported size is used - won't link */ -extern void __cmpxchg_called_with_bad_pointer(void); - -/* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */ -extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old, unsigned int new_); -extern unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new_); - -/* don't worry...optimizer will get rid of most of this */ -static __inline__ unsigned long -__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) -{ - switch(size) { -#ifdef CONFIG_64BIT - case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_); -#endif - case 4: return __cmpxchg_u32((unsigned int *)ptr, (unsigned int) old, (unsigned int) new_); - } - __cmpxchg_called_with_bad_pointer(); - return old; -} - -#define cmpxchg(ptr,o,n) \ - ({ \ - __typeof__(*(ptr)) _o_ = (o); \ - __typeof__(*(ptr)) _n_ = (n); \ - (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ - (unsigned long)_n_, sizeof(*(ptr))); \ - }) - -#include - -static inline unsigned long __cmpxchg_local(volatile void *ptr, - unsigned long old, - unsigned long new_, int size) -{ - switch (size) { -#ifdef CONFIG_64BIT - case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_); -#endif - case 4: return __cmpxchg_u32(ptr, old, new_); - default: - return __cmpxchg_local_generic(ptr, old, new_, size); - } -} - -/* - * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make - * them available. - */ -#define cmpxchg_local(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr)))) -#ifdef CONFIG_64BIT -#define cmpxchg64_local(ptr, o, n) \ - ({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg_local((ptr), (o), (n)); \ - }) -#else -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) -#endif - /* * Note that we need not lock read accesses - aligned word writes/reads * are atomic, so a reader never sees inconsistent values. diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h new file mode 100644 index 0000000..dbd1335 --- /dev/null +++ b/arch/parisc/include/asm/cmpxchg.h @@ -0,0 +1,116 @@ +/* + * forked from parisc asm/atomic.h which was: + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2006 Kyle McMartin + */ + +#ifndef _ASM_PARISC_CMPXCHG_H_ +#define _ASM_PARISC_CMPXCHG_H_ + +/* This should get optimized out since it's never called. +** Or get a link error if xchg is used "wrong". +*/ +extern void __xchg_called_with_bad_pointer(void); + +/* __xchg32/64 defined in arch/parisc/lib/bitops.c */ +extern unsigned long __xchg8(char, char *); +extern unsigned long __xchg32(int, int *); +#ifdef CONFIG_64BIT +extern unsigned long __xchg64(unsigned long, unsigned long *); +#endif + +/* optimizer better get rid of switch since size is a constant */ +static inline unsigned long +__xchg(unsigned long x, __volatile__ void *ptr, int size) +{ + switch (size) { +#ifdef CONFIG_64BIT + case 8: return __xchg64(x, (unsigned long *) ptr); +#endif + case 4: return __xchg32((int) x, (int *) ptr); + case 1: return __xchg8((char) x, (char *) ptr); + } + __xchg_called_with_bad_pointer(); + return x; +} + +/* +** REVISIT - Abandoned use of LDCW in xchg() for now: +** o need to test sizeof(*ptr) to avoid clearing adjacent bytes +** o and while we are at it, could CONFIG_64BIT code use LDCD too? +** +** if (__builtin_constant_p(x) && (x == NULL)) +** if (((unsigned long)p & 0xf) == 0) +** return __ldcw(p); +*/ +#define xchg(ptr, x) \ + ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) + +#define __HAVE_ARCH_CMPXCHG 1 + +/* bug catcher for when unsupported size is used - won't link */ +extern void __cmpxchg_called_with_bad_pointer(void); + +/* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */ +extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old, + unsigned int new_); +extern unsigned long __cmpxchg_u64(volatile unsigned long *ptr, + unsigned long old, unsigned long new_); + +/* don't worry...optimizer will get rid of most of this */ +static inline unsigned long +__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) +{ + switch (size) { +#ifdef CONFIG_64BIT + case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_); +#endif + case 4: return __cmpxchg_u32((unsigned int *)ptr, + (unsigned int)old, (unsigned int)new_); + } + __cmpxchg_called_with_bad_pointer(); + return old; +} + +#define cmpxchg(ptr, o, n) \ +({ \ + __typeof__(*(ptr)) _o_ = (o); \ + __typeof__(*(ptr)) _n_ = (n); \ + (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ + (unsigned long)_n_, sizeof(*(ptr))); \ +}) + +#include + +static inline unsigned long __cmpxchg_local(volatile void *ptr, + unsigned long old, + unsigned long new_, int size) +{ + switch (size) { +#ifdef CONFIG_64BIT + case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_); +#endif + case 4: return __cmpxchg_u32(ptr, old, new_); + default: + return __cmpxchg_local_generic(ptr, old, new_, size); + } +} + +/* + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make + * them available. + */ +#define cmpxchg_local(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) +#ifdef CONFIG_64BIT +#define cmpxchg64_local(ptr, o, n) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg_local((ptr), (o), (n)); \ +}) +#else +#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#endif + +#endif /* _ASM_PARISC_CMPXCHG_H_ */ -- cgit v0.10.2 From 9a78da114c18c130769c1ba25cabbc34da7ad70c Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:44 -0400 Subject: frv: fix warnings in mb93090-mb00/pci-dma.c about implicit EXPORT_SYMBOL To fix: arch/frv/mb93090-mb00/pci-dma.c:31:1: warning: data definition has no type or storage class [enabled by default] arch/frv/mb93090-mb00/pci-dma.c:31:1: warning: type defaults to 'int' in declaration of 'EXPORT_SYMBOL' [-Wimplicit-int] arch/frv/mb93090-mb00/pci-dma.c:31:1: warning: parameter names (without types) in function declaration [enabled by default] arch/frv/mb93090-mb00/pci-dma.c:38:1: warning: data definition has no type or storage class [enabled by default] Signed-off-by: Paul Gortmaker Acked-by: David Howells Signed-off-by: Linus Torvalds diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c index 41098a3..4f8d8bc 100644 --- a/arch/frv/mb93090-mb00/pci-dma.c +++ b/arch/frv/mb93090-mb00/pci-dma.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From f68c56b7d2351036d1ec58c7a0ac4f258cbc1fa2 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:45 -0400 Subject: firewire: restore the device.h include in linux/firewire.h Commit 313162d0b838 ("device.h: audit and cleanup users in main include dir") exchanged an include for a struct *device but in actuality I misread this file when creating 313162d and it should have remained an include. There were no build regressions since all consumers were already getting device.h anyway, but make it right regardless. Reported-by: Stefan Richter Signed-off-by: Paul Gortmaker Signed-off-by: Linus Torvalds diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 4db7b68..cdc9b71 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -2,6 +2,7 @@ #define _LINUX_FIREWIRE_H #include +#include #include #include #include @@ -64,8 +65,6 @@ #define CSR_MODEL 0x17 #define CSR_DIRECTORY_ID 0x20 -struct device; - struct fw_csr_iterator { const u32 *p; const u32 *end; -- cgit v0.10.2 From 80da6a4feeb9e4d6554f771f14f5b994e6c6c7e8 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 1 Apr 2012 16:38:47 -0400 Subject: asm-generic: add linux/types.h to cmpxchg.h Builds of the openrisc or1ksim_defconfig show the following: In file included from arch/openrisc/include/generated/asm/cmpxchg.h:1:0, from include/asm-generic/atomic.h:18, from arch/openrisc/include/generated/asm/atomic.h:1, from include/linux/atomic.h:4, from include/linux/dcache.h:4, from fs/notify/fsnotify.c:19: include/asm-generic/cmpxchg.h: In function '__xchg': include/asm-generic/cmpxchg.h:34:20: error: expected ')' before 'u8' include/asm-generic/cmpxchg.h:34:20: warning: type defaults to 'int' in type name and many more lines of similar errors. It seems specific to the or32 because most other platforms have an arch specific component that would have already included types.h ahead of time, but the o32 does not. Cc: Arnd Bergmann Cc: Jonas Bonn Signed-off-by: Paul Gortmaker Acked-by: David Howells diff --git a/include/asm-generic/cmpxchg.h b/include/asm-generic/cmpxchg.h index 8a36183..1488302 100644 --- a/include/asm-generic/cmpxchg.h +++ b/include/asm-generic/cmpxchg.h @@ -10,6 +10,7 @@ #error "Cannot use generic cmpxchg on SMP" #endif +#include #include #ifndef xchg -- cgit v0.10.2 From 085f1afc56619bda424941412fdeaff1e32c21dc Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Apr 2012 09:01:40 +0000 Subject: tg3: Fix 5717 serdes powerdown problem If port 0 of a 5717 serdes device powers down, it hides the phy from port 1. This patch works around the problem by keeping port 0's phy powered up. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 7b71387..d2ff8ee 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -2779,7 +2779,9 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && - (tp->phy_flags & TG3_PHYFLG_MII_SERDES))) + (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + !tp->pci_fn)) return; if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX || -- cgit v0.10.2 From 2240eb4ae3dc4acff20d1a8947c441c451513e37 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Fri, 30 Mar 2012 07:28:59 +0000 Subject: sky2: dont overwrite settings for PHY Quick link This patch corrects a bug in function sky2_open() of the Marvell Yukon 2 driver in which the settings for PHY quick link are overwritten. Signed-off-by: Lino Sanfilippo Acked-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 423a1a2..b806d9b 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1767,13 +1767,14 @@ static int sky2_open(struct net_device *dev) sky2_hw_up(sky2); + /* Enable interrupts from phy/mac for port */ + imask = sky2_read32(hw, B0_IMSK); + if (hw->chip_id == CHIP_ID_YUKON_OPT || hw->chip_id == CHIP_ID_YUKON_PRM || hw->chip_id == CHIP_ID_YUKON_OP_2) imask |= Y2_IS_PHY_QLNK; /* enable PHY Quick Link */ - /* Enable interrupts from phy/mac for port */ - imask = sky2_read32(hw, B0_IMSK); imask |= portirq_msk[port]; sky2_write32(hw, B0_IMSK, imask); sky2_read32(hw, B0_IMSK); -- cgit v0.10.2 From f283d22713b0bdc147097c92c9b45855339cf1c8 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 1 Apr 2012 20:19:30 +1000 Subject: APM: fix deadlock in APM_IOC_SUSPEND ioctl I found the Xorg server on my ARM device stuck in the 'msleep()' loop in apm_ioctl. I suspect it had attempted suspend immediately after resuming and lost a race. During that msleep(10);, a new suspend cycle must have started and changed ->suspend_state to SUSPEND_PENDING, so it was never seen to be SUSPEND_DONE and the loop could never exited. It would have moved on to SUSPEND_ACKTO but never been able to reach SUSPEND_DONE. So change the loop to only run while SUSPEND_ACKED rather than until SUSPEND_DONE. This is much safer. Signed-off-by: NeilBrown Signed-off-by: Jiri Kosina diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index f4837a8..6005c5c 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c @@ -302,7 +302,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg) * anything critical, chill a bit on each iteration. */ while (wait_event_freezable(apm_suspend_waitqueue, - as->suspend_state == SUSPEND_DONE)) + as->suspend_state != SUSPEND_ACKED)) msleep(10); break; case SUSPEND_ACKTO: -- cgit v0.10.2 From ee5324ea33d373558da43a22f3c1074a5fd5496e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 2 Apr 2012 19:48:25 -0400 Subject: ARM: versatile: fix build failure in pci.c commit 9f786d033d025ab7d2c4d1b959aa81d935eb9e19 "arm/PCI: get rid of device resource fixups" causes this failure on the versatile: arch/arm/mach-versatile/pci.c: In function 'pci_versatile_setup_resources': arch/arm/mach-versatile/pci.c:221: error: 'sys' undeclared (first use in this function) because the versatile wasn't passing in the full struct pci_sys_data but only the resource sub-field. Change it to pass in the full struct so that sys will be in scope. Reported-by: Bruce Ashfield Signed-off-by: Paul Gortmaker Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c index a6e23f4..d2268be8 100644 --- a/arch/arm/mach-versatile/pci.c +++ b/arch/arm/mach-versatile/pci.c @@ -190,7 +190,7 @@ static struct resource pre_mem = { .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, }; -static int __init pci_versatile_setup_resources(struct list_head *resources) +static int __init pci_versatile_setup_resources(struct pci_sys_data *sys) { int ret = 0; @@ -218,9 +218,9 @@ static int __init pci_versatile_setup_resources(struct list_head *resources) * the mem resource for this bus * the prefetch mem resource for this bus */ - pci_add_resource_offset(resources, &io_mem, sys->io_offset); - pci_add_resource_offset(resources, &non_mem, sys->mem_offset); - pci_add_resource_offset(resources, &pre_mem, sys->mem_offset); + pci_add_resource_offset(&sys->resources, &io_mem, sys->io_offset); + pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset); + pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset); goto out; @@ -249,7 +249,7 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys) if (nr == 0) { sys->mem_offset = 0; - ret = pci_versatile_setup_resources(&sys->resources); + ret = pci_versatile_setup_resources(sys); if (ret < 0) { printk("pci_versatile_setup: resources... oops?\n"); goto out; -- cgit v0.10.2 From beca98c93dc8d838c3656bc62fd49b45622ef788 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 2 Apr 2012 18:17:17 -0400 Subject: ARM: fix lcd power build failure in collie_defconfig Commit 086ada54abaa4316e8603f02410fe8ebc9ba2de1 "FB: sa1100: remove global sa1100fb_.*_power function pointers" got rid of all instances but one in locomolcd.c -- which was conditional on CONFIG_SA1100_COLLIE. The associated .power field which replaces the global is populated in mach-sa1100/collie.c so move the assignment there, but make it conditional on the locomolcd support, so use CONFIG_BACKLIGHT_LOCOMO in that file. Cc: arm@kernel.org Acked-by: Russell King Signed-off-by: Paul Gortmaker Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 48885b7..c7f418b 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -313,6 +313,10 @@ static struct sa1100fb_mach_info collie_lcd_info = { .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), + +#ifdef CONFIG_BACKLIGHT_LOCOMO + .lcd_power = locomolcd_power +#endif }; static void __init collie_init(void) diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h index 52acda7..f33679d 100644 --- a/arch/arm/mach-sa1100/include/mach/collie.h +++ b/arch/arm/mach-sa1100/include/mach/collie.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-sa1100/include/mach/collie.h * - * This file contains the hardware specific definitions for Assabet + * This file contains the hardware specific definitions for Collie * Only include this file from SA1100-specific files. * * ChangeLog: @@ -13,6 +13,7 @@ #ifndef __ASM_ARCH_COLLIE_H #define __ASM_ARCH_COLLIE_H +extern void locomolcd_power(int on); #define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1) #define COLLIE_GPIO_CHARGE_ON (COLLIE_SCOOP_GPIO_BASE + 0) diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index be20b5c..3a6d541 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -229,14 +229,7 @@ static struct locomo_driver poodle_lcd_driver = { static int __init locomolcd_init(void) { - int ret = locomo_driver_register(&poodle_lcd_driver); - if (ret) - return ret; - -#ifdef CONFIG_SA1100_COLLIE - sa1100fb_lcd_power = locomolcd_power; -#endif - return 0; + return locomo_driver_register(&poodle_lcd_driver); } static void __exit locomolcd_exit(void) -- cgit v0.10.2 From 18b9837ea0dc3cf844c6c4196871ce91d047bddb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 1 Apr 2012 23:48:38 +1000 Subject: md/raid5: fix handling of bad blocks during recovery. 1/ We can only treat a known-bad-block like a read-error if we have the data that belongs in that block. So fix that test. 2/ If we cannot recovery a stripe due to insufficient data, don't tell "md_done_sync" that the sync failed unless we really did fail something. If we successfully record bad blocks, that is success. Reported-by: "majianpeng" Signed-off-by: NeilBrown diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 23ac880..9799be8 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2471,39 +2471,41 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh, int abort = 0; int i; - md_done_sync(conf->mddev, STRIPE_SECTORS, 0); clear_bit(STRIPE_SYNCING, &sh->state); s->syncing = 0; s->replacing = 0; /* There is nothing more to do for sync/check/repair. + * Don't even need to abort as that is handled elsewhere + * if needed, and not always wanted e.g. if there is a known + * bad block here. * For recover/replace we need to record a bad block on all * non-sync devices, or abort the recovery */ - if (!test_bit(MD_RECOVERY_RECOVER, &conf->mddev->recovery)) - return; - /* During recovery devices cannot be removed, so locking and - * refcounting of rdevs is not needed - */ - for (i = 0; i < conf->raid_disks; i++) { - struct md_rdev *rdev = conf->disks[i].rdev; - if (rdev - && !test_bit(Faulty, &rdev->flags) - && !test_bit(In_sync, &rdev->flags) - && !rdev_set_badblocks(rdev, sh->sector, - STRIPE_SECTORS, 0)) - abort = 1; - rdev = conf->disks[i].replacement; - if (rdev - && !test_bit(Faulty, &rdev->flags) - && !test_bit(In_sync, &rdev->flags) - && !rdev_set_badblocks(rdev, sh->sector, - STRIPE_SECTORS, 0)) - abort = 1; - } - if (abort) { - conf->recovery_disabled = conf->mddev->recovery_disabled; - set_bit(MD_RECOVERY_INTR, &conf->mddev->recovery); + if (test_bit(MD_RECOVERY_RECOVER, &conf->mddev->recovery)) { + /* During recovery devices cannot be removed, so + * locking and refcounting of rdevs is not needed + */ + for (i = 0; i < conf->raid_disks; i++) { + struct md_rdev *rdev = conf->disks[i].rdev; + if (rdev + && !test_bit(Faulty, &rdev->flags) + && !test_bit(In_sync, &rdev->flags) + && !rdev_set_badblocks(rdev, sh->sector, + STRIPE_SECTORS, 0)) + abort = 1; + rdev = conf->disks[i].replacement; + if (rdev + && !test_bit(Faulty, &rdev->flags) + && !test_bit(In_sync, &rdev->flags) + && !rdev_set_badblocks(rdev, sh->sector, + STRIPE_SECTORS, 0)) + abort = 1; + } + if (abort) + conf->recovery_disabled = + conf->mddev->recovery_disabled; } + md_done_sync(conf->mddev, STRIPE_SECTORS, !abort); } static int want_replace(struct stripe_head *sh, int disk_idx) @@ -3203,7 +3205,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) /* Not in-sync */; else if (is_bad) { /* also not in-sync */ - if (!test_bit(WriteErrorSeen, &rdev->flags)) { + if (!test_bit(WriteErrorSeen, &rdev->flags) && + test_bit(R5_UPTODATE, &dev->flags)) { /* treat as in-sync, but with a read error * which we can now try to correct */ -- cgit v0.10.2 From 24b961f811a3e790a9b93604d2594bfb6cce4fa4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Sun, 1 Apr 2012 23:48:38 +1000 Subject: md: Avoid OOPS when reshaping raid1 to raid0 raid1 arrays do not have the notion of chunk size. Calculate the largest chunk sector size we can use to avoid a divide by zero OOPS when aligning the size of the new array to the chunk size. Signed-off-by: Jes Sorensen Signed-off-by: NeilBrown diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index c980945..de63a1f 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -632,6 +632,7 @@ static void *raid0_takeover_raid10(struct mddev *mddev) static void *raid0_takeover_raid1(struct mddev *mddev) { struct r0conf *priv_conf; + int chunksect; /* Check layout: * - (N - 1) mirror drives must be already faulty @@ -642,10 +643,25 @@ static void *raid0_takeover_raid1(struct mddev *mddev) return ERR_PTR(-EINVAL); } + /* + * a raid1 doesn't have the notion of chunk size, so + * figure out the largest suitable size we can use. + */ + chunksect = 64 * 2; /* 64K by default */ + + /* The array must be an exact multiple of chunksize */ + while (chunksect && (mddev->array_sectors & (chunksect - 1))) + chunksect >>= 1; + + if ((chunksect << 9) < PAGE_SIZE) + /* array size does not allow a suitable chunk size */ + return ERR_PTR(-EINVAL); + /* Set new parameters */ mddev->new_level = 0; mddev->new_layout = 0; - mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */ + mddev->new_chunk_sectors = chunksect; + mddev->chunk_sectors = chunksect; mddev->delta_disks = 1 - mddev->raid_disks; mddev->raid_disks = 1; /* make sure it will be not marked as dirty */ -- cgit v0.10.2 From a42f9d83b5c05dc6e678a1f0cd9767502c2c58de Mon Sep 17 00:00:00 2001 From: majianpeng Date: Mon, 2 Apr 2012 01:04:19 +1000 Subject: md/raid1:Remove unnecessary rcu_dereference(conf->mirrors[i].rdev). Because rde->nr_pending > 0,so can not remove this disk. And in any case, we aren't holding rcu_read_lock() Signed-off-by: majianpeng Signed-off-by: NeilBrown diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 2424408..8c420f1 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2386,8 +2386,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp int ok = 1; for (i = 0 ; i < conf->raid_disks * 2 ; i++) if (r1_bio->bios[i]->bi_end_io == end_sync_write) { - struct md_rdev *rdev = - rcu_dereference(conf->mirrors[i].rdev); + struct md_rdev *rdev = conf->mirrors[i].rdev; ok = rdev_set_badblocks(rdev, sector_nr, min_bad, 0 ) && ok; -- cgit v0.10.2 From c6d2e084c7411f61f2b446d94989e5aaf9879b0f Mon Sep 17 00:00:00 2001 From: majianpeng Date: Mon, 2 Apr 2012 01:16:59 +1000 Subject: md/raid5: Fix a bug about judging if the operation is syncing or replacing When create a raid5 using assume-clean and echo check or repair to sync_action.Then component disks did not operated IO but the raid check/resync faster than normal. Because the judgement in function analyse_stripe(): if (do_recovery || sh->sector >= conf->mddev->recovery_cp) s->syncing = 1; else s->replacing = 1; When check or repair,the recovery_cp == MaxSectore,so syncing equal zero not one. This bug was introduced by commit 9a3e1101b827 md/raid5: detect and handle replacements during recovery. so this patch is suitable for 3.3-stable. Cc: stable@vger.kernel.org Signed-off-by: majianpeng Signed-off-by: NeilBrown diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 9799be8..f351422 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3279,12 +3279,14 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) /* If there is a failed device being replaced, * we must be recovering. * else if we are after recovery_cp, we must be syncing + * else if MD_RECOVERY_REQUESTED is set, we also are syncing. * else we can only be replacing * sync and recovery both need to read all devices, and so * use the same flag. */ if (do_recovery || - sh->sector >= conf->mddev->recovery_cp) + sh->sector >= conf->mddev->recovery_cp || + test_bit(MD_RECOVERY_REQUESTED, &(conf->mddev->recovery))) s->syncing = 1; else s->replacing = 1; -- cgit v0.10.2 From 5020ad7d143ccfcf8149974096220d59e5572120 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 2 Apr 2012 01:39:05 +1000 Subject: md/raid1,raid10: don't compare excess byte during consistency check. When comparing two pages read from different legs of a mirror, only compare the bytes that were read, not the whole page. In most cases we read a whole page, but in some cases with bad blocks or odd sizes devices we might read fewer than that. This bug has been present "forever" but at worst it might cause a report of two many mismatches and generate a little bit extra resync IO, so there is no need to back-port to -stable kernels. Reported-by: majianpeng Signed-off-by: NeilBrown diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 8c420f1..d35e4c9 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1738,7 +1738,7 @@ static int process_checks(struct r1bio *r1_bio) s = sbio->bi_io_vec[j].bv_page; if (memcmp(page_address(p), page_address(s), - PAGE_SIZE)) + sbio->bi_io_vec[j].bv_len)) break; } } else diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 3540316..fff7821 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1821,7 +1821,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) for (j = 0; j < vcnt; j++) if (memcmp(page_address(fbio->bi_io_vec[j].bv_page), page_address(tbio->bi_io_vec[j].bv_page), - PAGE_SIZE)) + fbio->bi_io_vec[j].bv_len)) break; if (j == vcnt) continue; -- cgit v0.10.2 From 7b8e6da46b921d30ac1553cac56d8fb74f0b431d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 27 Mar 2012 16:50:42 +0200 Subject: perf/x86/p4: Add format attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steven reported his P4 not booting properly, the missing format attributes cause a NULL ptr deref. Cure this by adding the missing format specification. I took the format description out of the comment near p4_config_pack*() and hope that comment is still relatively accurate. Reported-by: Steven Rostedt Reported-by: Bruno Prémont Tested-by: Steven Rostedt Signed-off-by: Peter Zijlstra Cc: Jiri Olsa Cc: Cyrill Gorcunov Cc: Lin Ming Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1332859842.16159.227.camel@twins Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index ef484d9..a2dfacf 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -1271,6 +1271,17 @@ done: return num ? -EINVAL : 0; } +PMU_FORMAT_ATTR(cccr, "config:0-31" ); +PMU_FORMAT_ATTR(escr, "config:32-62"); +PMU_FORMAT_ATTR(ht, "config:63" ); + +static struct attribute *intel_p4_formats_attr[] = { + &format_attr_cccr.attr, + &format_attr_escr.attr, + &format_attr_ht.attr, + NULL, +}; + static __initconst const struct x86_pmu p4_pmu = { .name = "Netburst P4/Xeon", .handle_irq = p4_pmu_handle_irq, @@ -1305,6 +1316,8 @@ static __initconst const struct x86_pmu p4_pmu = { * the former idea is taken from OProfile code */ .perfctr_second_write = 1, + + .format_attrs = intel_p4_formats_attr, }; __init int p4_pmu_init(void) -- cgit v0.10.2 From b8e6f8ae511d88732247aa2af26bfd1bef21b2f4 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 13 Mar 2012 19:59:39 +0100 Subject: KVM: PPC: Book3S: Compile fix for ppc32 in HIOR access code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were failing to compile on book3s_32 with the following errors: arch/powerpc/kvm/book3s_pr.c:883:45: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] arch/powerpc/kvm/book3s_pr.c:898:79: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] Fix this by explicity casting the u64 to long before we use it as a pointer. Also, on PPC32 we can not use get_user/put_user for 64bit wide variables, as there is no single instruction that could load or store variables that big. So instead, we have to use copy_from/to_user which works everywhere. Reported-by: Jörg Sommer Signed-off-by: Alexander Graf Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 642d885..a657c44 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -881,7 +881,8 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) switch (reg->id) { case KVM_REG_PPC_HIOR: - r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr); + r = copy_to_user((u64 __user *)(long)reg->addr, + &to_book3s(vcpu)->hior, sizeof(u64)); break; default: break; @@ -896,7 +897,8 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) switch (reg->id) { case KVM_REG_PPC_HIOR: - r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr); + r = copy_from_user(&to_book3s(vcpu)->hior, + (u64 __user *)(long)reg->addr, sizeof(u64)); if (!r) to_book3s(vcpu)->hior_explicit = true; break; -- cgit v0.10.2 From b4e51229d8a1e499fe65153766437152cca42053 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 3 Feb 2012 00:45:02 +0000 Subject: KVM: PPC: Book3S HV: Fix kvm_alloc_linear in case where no linears exist In kvm_alloc_linear we were using and deferencing ri after the list_for_each_entry had come to the end of the list. In that situation, ri is not really defined and probably points to the list head. This will happen every time if the free_linears list is empty, for instance. This led to a NULL pointer dereference crash in memset on POWER7 while trying to allocate an HPT in the case where no HPTs were preallocated. This fixes it by using a separate variable for the return value from the loop iterator. Signed-off-by: Paul Mackerras Signed-off-by: Alexander Graf Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index bed1279..e1b60f5 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -173,9 +173,9 @@ static void __init kvm_linear_init_one(ulong size, int count, int type) static struct kvmppc_linear_info *kvm_alloc_linear(int type) { - struct kvmppc_linear_info *ri; + struct kvmppc_linear_info *ri, *ret; - ri = NULL; + ret = NULL; spin_lock(&linear_lock); list_for_each_entry(ri, &free_linears, list) { if (ri->type != type) @@ -183,11 +183,12 @@ static struct kvmppc_linear_info *kvm_alloc_linear(int type) list_del(&ri->list); atomic_inc(&ri->use_count); + memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT); + ret = ri; break; } spin_unlock(&linear_lock); - memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT); - return ri; + return ret; } static void kvm_release_linear(struct kvmppc_linear_info *ri) -- cgit v0.10.2 From a5ddea0e78e76aa8d6354b9b0e51e652e21b8137 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 3 Feb 2012 00:53:21 +0000 Subject: KVM: PPC: Book3S HV: Save and restore CR in __kvmppc_vcore_entry The ABI specifies that CR fields CR2--CR4 are nonvolatile across function calls. Currently __kvmppc_vcore_entry doesn't save and restore the CR, leading to CR2--CR4 getting corrupted with guest values, possibly leading to incorrect behaviour in its caller. This adds instructions to save and restore CR at the points where we save and restore the nonvolatile GPRs. Signed-off-by: Paul Mackerras Signed-off-by: Alexander Graf Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S index 3f7b674..d3fb4df 100644 --- a/arch/powerpc/kvm/book3s_hv_interrupts.S +++ b/arch/powerpc/kvm/book3s_hv_interrupts.S @@ -46,8 +46,10 @@ _GLOBAL(__kvmppc_vcore_entry) /* Save host state to the stack */ stdu r1, -SWITCH_FRAME_SIZE(r1) - /* Save non-volatile registers (r14 - r31) */ + /* Save non-volatile registers (r14 - r31) and CR */ SAVE_NVGPRS(r1) + mfcr r3 + std r3, _CCR(r1) /* Save host DSCR */ BEGIN_FTR_SECTION @@ -157,8 +159,10 @@ kvmppc_handler_highmem: * R13 = PACA */ - /* Restore non-volatile host registers (r14 - r31) */ + /* Restore non-volatile host registers (r14 - r31) and CR */ REST_NVGPRS(r1) + ld r4, _CCR(r1) + mtcr r4 addi r1, r1, SWITCH_FRAME_SIZE ld r0, PPC_LR_STKOFF(r1) -- cgit v0.10.2 From e1f8acf8380abfd52aefbfa524e74af5ce0c8492 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 5 Mar 2012 16:00:28 +0100 Subject: KVM: PPC: Save/Restore CR over vcpu_run On PPC, CR2-CR4 are nonvolatile, thus have to be saved across function calls. We didn't respect that for any architecture until Paul spotted it in his patch for Book3S-HV. This patch saves/restores CR for all KVM capable PPC hosts. Signed-off-by: Alexander Graf Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S index 0a8515a..3e35383 100644 --- a/arch/powerpc/kvm/book3s_interrupts.S +++ b/arch/powerpc/kvm/book3s_interrupts.S @@ -84,6 +84,10 @@ kvm_start_entry: /* Save non-volatile registers (r14 - r31) */ SAVE_NVGPRS(r1) + /* Save CR */ + mfcr r14 + stw r14, _CCR(r1) + /* Save LR */ PPC_STL r0, _LINK(r1) @@ -165,6 +169,9 @@ kvm_exit_loop: PPC_LL r4, _LINK(r1) mtlr r4 + lwz r14, _CCR(r1) + mtcr r14 + /* Restore non-volatile host registers (r14 - r31) */ REST_NVGPRS(r1) diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 10d8ef6..c8c4b87 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -34,7 +34,8 @@ /* r2 is special: it holds 'current', and it made nonvolatile in the * kernel with the -ffixed-r2 gcc option. */ #define HOST_R2 12 -#define HOST_NV_GPRS 16 +#define HOST_CR 16 +#define HOST_NV_GPRS 20 #define HOST_NV_GPR(n) (HOST_NV_GPRS + ((n - 14) * 4)) #define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + 4) #define HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */ @@ -296,8 +297,10 @@ heavyweight_exit: /* Return to kvm_vcpu_run(). */ lwz r4, HOST_STACK_LR(r1) + lwz r5, HOST_CR(r1) addi r1, r1, HOST_STACK_SIZE mtlr r4 + mtcr r5 /* r3 still contains the return code from kvmppc_handle_exit(). */ blr @@ -314,6 +317,8 @@ _GLOBAL(__kvmppc_vcpu_run) stw r3, HOST_RUN(r1) mflr r3 stw r3, HOST_STACK_LR(r1) + mfcr r5 + stw r5, HOST_CR(r1) /* Save host non-volatile register state to stack. */ stw r14, HOST_NV_GPR(r14)(r1) -- cgit v0.10.2 From 592f5d87b3feee9d60411f19d583038c0c7670ad Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 13 Mar 2012 23:31:02 +0100 Subject: KVM: PPC: Book3S: PR: Fix preemption We were leaking preemption counters. Fix the code to always toggle between preempt and non-preempt properly. Signed-off-by: Alexander Graf Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index a657c44..7759053 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -777,6 +777,7 @@ program_interrupt: } } + preempt_disable(); if (!(r & RESUME_HOST)) { /* To avoid clobbering exit_reason, only check for signals if * we aren't already exiting to userspace for some other @@ -798,8 +799,6 @@ program_interrupt: run->exit_reason = KVM_EXIT_INTR; r = -EINTR; } else { - preempt_disable(); - /* In case an interrupt came in that was triggered * from userspace (like DEC), we need to check what * to inject now! */ -- cgit v0.10.2 From 44b52bccf855b0706de624c29fc3d82ca954bb4e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 3 Apr 2012 10:08:48 +0200 Subject: netfilter: xt_CT: remove a compile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_NF_CONNTRACK_TIMEOUT=n we have following warning : CC [M] net/netfilter/xt_CT.o net/netfilter/xt_CT.c: In function ‘xt_ct_tg_check_v1’: net/netfilter/xt_CT.c:284: warning: label ‘err4’ defined but not used Reported-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 0c8e438..138b75e 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -281,8 +281,10 @@ out: info->ct = ct; return 0; +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT err4: rcu_read_unlock(); +#endif err3: nf_conntrack_free(ct); err2: -- cgit v0.10.2 From e02f14cd48a5da0ebaecf88c93dbd54a81e0dead Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Apr 2012 23:33:03 +0200 Subject: drm/i915: don't leak struct_mutex lock on ppgtt init failures Reported-by: Konstantin Belousov Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 8a62285..785f67f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1222,8 +1222,10 @@ static int i915_load_gem_init(struct drm_device *dev) i915_gem_do_init(dev, 0, mappable_size, gtt_size); ret = i915_gem_init_aliasing_ppgtt(dev); - if (ret) + if (ret) { + mutex_unlock(&dev->struct_mutex); return ret; + } } else { /* Let GEM Manage all of the aperture. * -- cgit v0.10.2 From 927a2f119e8235238a2fc64871051b16c9bdae75 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Fri, 23 Mar 2012 08:52:58 -0400 Subject: drm/i915: Add lock on drm_helper_resume_force_mode i915_drm_thaw was not locking the mode_config lock when calling drm_helper_resume_force_mode. When there were multiple wake sources, this caused FDI training failure on SNB which in turn corrupted the display. Signed-off-by: Sean Paul Reviewed-by: Chris Wilson Cc: stable@kernel.org Signed-Off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 19d55bc..dfa55e7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -538,7 +538,9 @@ static int i915_drm_thaw(struct drm_device *dev) drm_irq_install(dev); /* Resume the modeset for every activated CRTC */ + mutex_lock(&dev->mode_config.mutex); drm_helper_resume_force_mode(dev); + mutex_unlock(&dev->mode_config.mutex); if (IS_IRONLAKE_M(dev)) ironlake_enable_rc6(dev); -- cgit v0.10.2 From 97effadb65ed08809e1720c8d3ee80b73a93665c Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Wed, 7 Mar 2012 18:36:35 +0100 Subject: drm/i915: no-lvds quirk on MSI DC500 This hardware doesn't have an LVDS, it's a desktop box. Fix incorrect LVDS detection. Cc: stable@kernel.org Signed-off-by: Anisse Astier Acked-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index c5c0973..95db2e9 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -755,6 +755,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "hp st5747"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "MSI Wind Box DC500", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), + DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), + }, + }, { } /* terminating entry */ }; -- cgit v0.10.2 From b4db1e35ac59c144965f517bc575a0d75b60b03f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 20 Mar 2012 10:59:09 -0700 Subject: drm/i915: treat src w & h as fixed point in sprite handling code This was missed when we converted the source values to 16.16 fixed point. Cc: stable@vger.kernel.org Signed-off-by: Jesse Barnes Tested-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 7aa0450..a464771 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -411,6 +411,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, old_obj = intel_plane->obj; + src_w = src_w >> 16; + src_h = src_h >> 16; + /* Pipe must be running... */ if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE)) return -EINVAL; -- cgit v0.10.2 From 62fb376e214d3c1bfdf6fbb77dac162f6da04d7e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 26 Mar 2012 21:15:53 +0100 Subject: drm: Validate requested virtual size against allocated fb size mplayer -vo fbdev tries to create a screen that is twice as tall as the allocated framebuffer for "doublebuffering". By default, and all in-tree users, only sufficient memory is allocated and mapped to satisfy the smallest framebuffer and the virtual size is no larger than the actual. For these users, we should therefore reject any userspace request to create a screen that requires a buffer larger than the framebuffer originally allocated. References: https://bugs.freedesktop.org/show_bug.cgi?id=38138 Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter Cc: stable@kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 7740dd2..a0d6e89 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -559,9 +559,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, return -EINVAL; /* Need to resize the fb object !!! */ - if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) { + if (var->bits_per_pixel > fb->bits_per_pixel || + var->xres > fb->width || var->yres > fb->height || + var->xres_virtual > fb->width || var->yres_virtual > fb->height) { DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " - "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, + "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", + var->xres, var->yres, var->bits_per_pixel, + var->xres_virtual, var->yres_virtual, fb->width, fb->height, fb->bits_per_pixel); return -EINVAL; } -- cgit v0.10.2 From e466de05194b666114713b753e2f4be1d4200140 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 3 Apr 2012 13:08:53 +0100 Subject: regmap: Export regcache_sync_region() regcache_sync_region() isn't going to be useful to most drivers if we don't export it since otherwise they can't use it when built modular. Signed-off-by: Mark Brown diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 87f54db..74b6909 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -346,6 +346,7 @@ out: return ret; } +EXPORT_SYMBOL_GPL(regcache_sync_region); /** * regcache_cache_only: Put a register map into cache only mode -- cgit v0.10.2 From 3b3b0e4fc15efa507b902d90cea39e496a523c3b Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Apr 2012 09:37:02 -0700 Subject: LSM: shrink sizeof LSM specific portion of common_audit_data Linus found that the gigantic size of the common audit data caused a big perf hit on something as simple as running stat() in a loop. This patch requires LSMs to declare the LSM specific portion separately rather than doing it in a union. Thus each LSM can be responsible for shrinking their portion and don't have to pay a penalty just because other LSMs have a bigger space requirement. Signed-off-by: Eric Paris Signed-off-by: Linus Torvalds diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index eab507f..6f4fb37 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h @@ -72,61 +72,15 @@ struct common_audit_data { /* this union contains LSM specific data */ union { #ifdef CONFIG_SECURITY_SMACK - /* SMACK data */ - struct smack_audit_data { - const char *function; - char *subject; - char *object; - char *request; - int result; - } smack_audit_data; + struct smack_audit_data *smack_audit_data; #endif #ifdef CONFIG_SECURITY_SELINUX - /* SELinux data */ - struct { - u32 ssid; - u32 tsid; - u16 tclass; - u32 requested; - u32 audited; - u32 denied; - /* - * auditdeny is a bit tricky and unintuitive. See the - * comments in avc.c for it's meaning and usage. - */ - u32 auditdeny; - struct av_decision *avd; - int result; - } selinux_audit_data; + struct selinux_audit_data *selinux_audit_data; #endif #ifdef CONFIG_SECURITY_APPARMOR - struct { - int error; - int op; - int type; - void *profile; - const char *name; - const char *info; - union { - void *target; - struct { - long pos; - void *target; - } iface; - struct { - int rlim; - unsigned long max; - } rlim; - struct { - const char *target; - u32 request; - u32 denied; - uid_t ouid; - } fs; - }; - } apparmor_audit_data; + struct apparmor_audit_data *apparmor_audit_data; #endif - }; + }; /* per LSM data pointer union */ /* these callback will be implemented by a specific LSM */ void (*lsm_pre_audit)(struct audit_buffer *, void *); void (*lsm_post_audit)(struct audit_buffer *, void *); diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 5ff6777..23f7eb6 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -115,23 +115,23 @@ static void audit_pre(struct audit_buffer *ab, void *ca) if (aa_g_audit_header) { audit_log_format(ab, "apparmor="); - audit_log_string(ab, aa_audit_type[sa->aad.type]); + audit_log_string(ab, aa_audit_type[sa->aad->type]); } - if (sa->aad.op) { + if (sa->aad->op) { audit_log_format(ab, " operation="); - audit_log_string(ab, op_table[sa->aad.op]); + audit_log_string(ab, op_table[sa->aad->op]); } - if (sa->aad.info) { + if (sa->aad->info) { audit_log_format(ab, " info="); - audit_log_string(ab, sa->aad.info); - if (sa->aad.error) - audit_log_format(ab, " error=%d", sa->aad.error); + audit_log_string(ab, sa->aad->info); + if (sa->aad->error) + audit_log_format(ab, " error=%d", sa->aad->error); } - if (sa->aad.profile) { - struct aa_profile *profile = sa->aad.profile; + if (sa->aad->profile) { + struct aa_profile *profile = sa->aad->profile; pid_t pid; rcu_read_lock(); pid = rcu_dereference(tsk->real_parent)->pid; @@ -145,9 +145,9 @@ static void audit_pre(struct audit_buffer *ab, void *ca) audit_log_untrustedstring(ab, profile->base.hname); } - if (sa->aad.name) { + if (sa->aad->name) { audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, sa->aad.name); + audit_log_untrustedstring(ab, sa->aad->name); } } @@ -159,7 +159,7 @@ static void audit_pre(struct audit_buffer *ab, void *ca) void aa_audit_msg(int type, struct common_audit_data *sa, void (*cb) (struct audit_buffer *, void *)) { - sa->aad.type = type; + sa->aad->type = type; sa->lsm_pre_audit = audit_pre; sa->lsm_post_audit = cb; common_lsm_audit(sa); @@ -184,7 +184,7 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, BUG_ON(!profile); if (type == AUDIT_APPARMOR_AUTO) { - if (likely(!sa->aad.error)) { + if (likely(!sa->aad->error)) { if (AUDIT_MODE(profile) != AUDIT_ALL) return 0; type = AUDIT_APPARMOR_AUDIT; @@ -196,21 +196,21 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, if (AUDIT_MODE(profile) == AUDIT_QUIET || (type == AUDIT_APPARMOR_DENIED && AUDIT_MODE(profile) == AUDIT_QUIET)) - return sa->aad.error; + return sa->aad->error; if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; if (!unconfined(profile)) - sa->aad.profile = profile; + sa->aad->profile = profile; aa_audit_msg(type, sa, cb); - if (sa->aad.type == AUDIT_APPARMOR_KILL) + if (sa->aad->type == AUDIT_APPARMOR_KILL) (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current); - if (sa->aad.type == AUDIT_APPARMOR_ALLOWED) - return complain_error(sa->aad.error); + if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) + return complain_error(sa->aad->error); - return sa->aad.error; + return sa->aad->error; } diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c index 9982c48..088dba3 100644 --- a/security/apparmor/capability.c +++ b/security/apparmor/capability.c @@ -64,11 +64,13 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task, struct audit_cache *ent; int type = AUDIT_APPARMOR_AUTO; struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, CAP); + sa.aad = &aad; sa.tsk = task; sa.u.cap = cap; - sa.aad.op = OP_CAPABLE; - sa.aad.error = error; + sa.aad->op = OP_CAPABLE; + sa.aad->error = error; if (likely(!error)) { /* test if auditing is being forced */ diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 5d176f2..2f8fcba 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -67,22 +67,22 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) struct common_audit_data *sa = va; uid_t fsuid = current_fsuid(); - if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) { + if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " requested_mask="); - audit_file_mask(ab, sa->aad.fs.request); + audit_file_mask(ab, sa->aad->fs.request); } - if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) { + if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " denied_mask="); - audit_file_mask(ab, sa->aad.fs.denied); + audit_file_mask(ab, sa->aad->fs.denied); } - if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) { + if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " fsuid=%d", fsuid); - audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid); + audit_log_format(ab, " ouid=%d", sa->aad->fs.ouid); } - if (sa->aad.fs.target) { + if (sa->aad->fs.target) { audit_log_format(ab, " target="); - audit_log_untrustedstring(ab, sa->aad.fs.target); + audit_log_untrustedstring(ab, sa->aad->fs.target); } } @@ -107,45 +107,47 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, { int type = AUDIT_APPARMOR_AUTO; struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad.op = op, - sa.aad.fs.request = request; - sa.aad.name = name; - sa.aad.fs.target = target; - sa.aad.fs.ouid = ouid; - sa.aad.info = info; - sa.aad.error = error; - - if (likely(!sa.aad.error)) { + sa.aad = &aad; + aad.op = op, + aad.fs.request = request; + aad.name = name; + aad.fs.target = target; + aad.fs.ouid = ouid; + aad.info = info; + aad.error = error; + + if (likely(!sa.aad->error)) { u32 mask = perms->audit; if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) mask = 0xffff; /* mask off perms that are not being force audited */ - sa.aad.fs.request &= mask; + sa.aad->fs.request &= mask; - if (likely(!sa.aad.fs.request)) + if (likely(!sa.aad->fs.request)) return 0; type = AUDIT_APPARMOR_AUDIT; } else { /* only report permissions that were denied */ - sa.aad.fs.request = sa.aad.fs.request & ~perms->allow; + sa.aad->fs.request = sa.aad->fs.request & ~perms->allow; - if (sa.aad.fs.request & perms->kill) + if (sa.aad->fs.request & perms->kill) type = AUDIT_APPARMOR_KILL; /* quiet known rejects, assumes quiet and kill do not overlap */ - if ((sa.aad.fs.request & perms->quiet) && + if ((sa.aad->fs.request & perms->quiet) && AUDIT_MODE(profile) != AUDIT_NOQUIET && AUDIT_MODE(profile) != AUDIT_ALL) - sa.aad.fs.request &= ~perms->quiet; + sa.aad->fs.request &= ~perms->quiet; - if (!sa.aad.fs.request) - return COMPLAIN_MODE(profile) ? 0 : sa.aad.error; + if (!sa.aad->fs.request) + return COMPLAIN_MODE(profile) ? 0 : sa.aad->error; } - sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow; + sa.aad->fs.denied = sa.aad->fs.request & ~perms->allow; return aa_audit(type, profile, gfp, &sa, file_audit_cb); } diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index 4ba78c2..3868b1e 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -103,7 +103,33 @@ enum aa_ops { }; -/* define a short hand for apparmor_audit_data portion of common_audit_data */ +struct apparmor_audit_data { + int error; + int op; + int type; + void *profile; + const char *name; + const char *info; + union { + void *target; + struct { + long pos; + void *target; + } iface; + struct { + int rlim; + unsigned long max; + } rlim; + struct { + const char *target; + u32 request; + u32 denied; + uid_t ouid; + } fs; + }; +}; + +/* define a short hand for apparmor_audit_data structure */ #define aad apparmor_audit_data void aa_audit_msg(int type, struct common_audit_data *sa, diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index 7ee05c6..c3da93a 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -26,7 +26,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; audit_log_format(ab, " target="); - audit_log_untrustedstring(ab, sa->aad.target); + audit_log_untrustedstring(ab, sa->aad->target); } /** @@ -41,10 +41,12 @@ static int aa_audit_ptrace(struct aa_profile *profile, struct aa_profile *target, int error) { struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad.op = OP_PTRACE; - sa.aad.target = target; - sa.aad.error = error; + sa.aad = &aad; + aad.op = OP_PTRACE; + aad.target = target; + aad.error = error; return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa, audit_cb); diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 9516948..e75829b 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -65,8 +65,10 @@ void aa_info_message(const char *str) { if (audit_enabled) { struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad.info = str; + sa.aad = &aad; + aad.info = str; aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); } printk(KERN_INFO "AppArmor: %s\n", str); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 97ce8fa..ad05d39 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -588,10 +588,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, error = aa_setprocattr_permipc(args); } else { struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad.op = OP_SETPROCATTR; - sa.aad.info = name; - sa.aad.error = -EINVAL; + sa.aad = &aad; + aad.op = OP_SETPROCATTR; + aad.info = name; + aad.error = -EINVAL; return aa_audit(AUDIT_APPARMOR_DENIED, __aa_current_profile(), GFP_KERNEL, &sa, NULL); diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 9064143..f1f7506 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -964,11 +964,13 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, int error) { struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad.op = op; - sa.aad.name = name; - sa.aad.info = info; - sa.aad.error = error; + sa.aad = &aad; + aad.op = op; + aad.name = name; + aad.info = info; + aad.error = error; return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp, &sa, NULL); diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 25fd51e..deab7c7 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -70,13 +70,13 @@ struct aa_ext { static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; - if (sa->aad.iface.target) { - struct aa_profile *name = sa->aad.iface.target; + if (sa->aad->iface.target) { + struct aa_profile *name = sa->aad->iface.target; audit_log_format(ab, " name="); audit_log_untrustedstring(ab, name->base.hname); } - if (sa->aad.iface.pos) - audit_log_format(ab, " offset=%ld", sa->aad.iface.pos); + if (sa->aad->iface.pos) + audit_log_format(ab, " offset=%ld", sa->aad->iface.pos); } /** @@ -94,13 +94,15 @@ static int audit_iface(struct aa_profile *new, const char *name, { struct aa_profile *profile = __aa_current_profile(); struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, NONE); + sa.aad = &aad; if (e) - sa.aad.iface.pos = e->pos - e->start; - sa.aad.iface.target = new; - sa.aad.name = name; - sa.aad.info = info; - sa.aad.error = error; + aad.iface.pos = e->pos - e->start; + aad.iface.target = new; + aad.name = name; + aad.info = info; + aad.error = error; return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa, audit_cb); diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index 72c25a4f..2fe8613 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c @@ -34,7 +34,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) struct common_audit_data *sa = va; audit_log_format(ab, " rlimit=%s value=%lu", - rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max); + rlim_names[sa->aad->rlim.rlim], sa->aad->rlim.max); } /** @@ -50,12 +50,14 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource, unsigned long value, int error) { struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad.op = OP_SETRLIMIT, - sa.aad.rlim.rlim = resource; - sa.aad.rlim.max = value; - sa.aad.error = error; + sa.aad = &aad; + aad.op = OP_SETRLIMIT, + aad.rlim.rlim = resource; + aad.rlim.max = value; + aad.error = error; return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa, audit_cb); } diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 1a70fa2..00f3860 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) { struct common_audit_data *ad = a; audit_log_format(ab, "avc: %s ", - ad->selinux_audit_data.denied ? "denied" : "granted"); - avc_dump_av(ab, ad->selinux_audit_data.tclass, - ad->selinux_audit_data.audited); + ad->selinux_audit_data->denied ? "denied" : "granted"); + avc_dump_av(ab, ad->selinux_audit_data->tclass, + ad->selinux_audit_data->audited); audit_log_format(ab, " for "); } @@ -452,9 +452,9 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) { struct common_audit_data *ad = a; audit_log_format(ab, " "); - avc_dump_query(ab, ad->selinux_audit_data.ssid, - ad->selinux_audit_data.tsid, - ad->selinux_audit_data.tclass); + avc_dump_query(ab, ad->selinux_audit_data->ssid, + ad->selinux_audit_data->tsid, + ad->selinux_audit_data->tclass); } /* This is the slow part of avc audit with big stack footprint */ @@ -464,10 +464,12 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, unsigned flags) { struct common_audit_data stack_data; + struct selinux_audit_data sad = {0,}; if (!a) { a = &stack_data; COMMON_AUDIT_DATA_INIT(a, NONE); + a->selinux_audit_data = &sad; } /* @@ -481,12 +483,12 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, (flags & MAY_NOT_BLOCK)) return -ECHILD; - a->selinux_audit_data.tclass = tclass; - a->selinux_audit_data.requested = requested; - a->selinux_audit_data.ssid = ssid; - a->selinux_audit_data.tsid = tsid; - a->selinux_audit_data.audited = audited; - a->selinux_audit_data.denied = denied; + a->selinux_audit_data->tclass = tclass; + a->selinux_audit_data->requested = requested; + a->selinux_audit_data->ssid = ssid; + a->selinux_audit_data->tsid = tsid; + a->selinux_audit_data->audited = audited; + a->selinux_audit_data->denied = denied; a->lsm_pre_audit = avc_audit_pre_callback; a->lsm_post_audit = avc_audit_post_callback; common_lsm_audit(a); @@ -523,7 +525,7 @@ inline int avc_audit(u32 ssid, u32 tsid, if (unlikely(denied)) { audited = denied & avd->auditdeny; /* - * a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in + * a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in * this field means that ANY denials should NOT be audited if * the policy contains an explicit dontaudit rule for that * permission. Take notice that this is unrelated to the @@ -532,15 +534,15 @@ inline int avc_audit(u32 ssid, u32 tsid, * * denied == READ * avd.auditdeny & ACCESS == 0 (not set means explicit rule) - * selinux_audit_data.auditdeny & ACCESS == 1 + * selinux_audit_data->auditdeny & ACCESS == 1 * * We will NOT audit the denial even though the denied * permission was READ and the auditdeny checks were for * ACCESS */ if (a && - a->selinux_audit_data.auditdeny && - !(a->selinux_audit_data.auditdeny & avd->auditdeny)) + a->selinux_audit_data->auditdeny && + !(a->selinux_audit_data->auditdeny & avd->auditdeny)) audited = 0; } else if (result) audited = denied = requested; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 28482f9..3861ce4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1420,6 +1420,7 @@ static int cred_has_capability(const struct cred *cred, int cap, int audit) { struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; struct av_decision avd; u16 sclass; u32 sid = cred_sid(cred); @@ -1427,6 +1428,7 @@ static int cred_has_capability(const struct cred *cred, int rc; COMMON_AUDIT_DATA_INIT(&ad, CAP); + ad.selinux_audit_data = &sad; ad.tsk = current; ad.u.cap = cap; @@ -1492,9 +1494,11 @@ static int inode_has_perm_noadp(const struct cred *cred, unsigned flags) { struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; COMMON_AUDIT_DATA_INIT(&ad, INODE); ad.u.inode = inode; + ad.selinux_audit_data = &sad; return inode_has_perm(cred, inode, perms, &ad, flags); } @@ -1507,9 +1511,11 @@ static inline int dentry_has_perm(const struct cred *cred, { struct inode *inode = dentry->d_inode; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.u.dentry = dentry; + ad.selinux_audit_data = &sad; return inode_has_perm(cred, inode, av, &ad, 0); } @@ -1522,9 +1528,11 @@ static inline int path_has_perm(const struct cred *cred, { struct inode *inode = path->dentry->d_inode; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; COMMON_AUDIT_DATA_INIT(&ad, PATH); ad.u.path = *path; + ad.selinux_audit_data = &sad; return inode_has_perm(cred, inode, av, &ad, 0); } @@ -1543,11 +1551,13 @@ static int file_has_perm(const struct cred *cred, struct file_security_struct *fsec = file->f_security; struct inode *inode = file->f_path.dentry->d_inode; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = cred_sid(cred); int rc; COMMON_AUDIT_DATA_INIT(&ad, PATH); ad.u.path = file->f_path; + ad.selinux_audit_data = &sad; if (sid != fsec->sid) { rc = avc_has_perm(sid, fsec->sid, @@ -1577,6 +1587,7 @@ static int may_create(struct inode *dir, struct superblock_security_struct *sbsec; u32 sid, newsid; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; int rc; dsec = dir->i_security; @@ -1587,6 +1598,7 @@ static int may_create(struct inode *dir, COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.u.dentry = dentry; + ad.selinux_audit_data = &sad; rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, DIR__ADD_NAME | DIR__SEARCH, @@ -1631,6 +1643,7 @@ static int may_link(struct inode *dir, { struct inode_security_struct *dsec, *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); u32 av; int rc; @@ -1640,6 +1653,7 @@ static int may_link(struct inode *dir, COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.u.dentry = dentry; + ad.selinux_audit_data = &sad; av = DIR__SEARCH; av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); @@ -1674,6 +1688,7 @@ static inline int may_rename(struct inode *old_dir, { struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); u32 av; int old_is_dir, new_is_dir; @@ -1685,6 +1700,7 @@ static inline int may_rename(struct inode *old_dir, new_dsec = new_dir->i_security; COMMON_AUDIT_DATA_INIT(&ad, DENTRY); + ad.selinux_audit_data = &sad; ad.u.dentry = old_dentry; rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, @@ -1970,6 +1986,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) struct task_security_struct *new_tsec; struct inode_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; struct inode *inode = bprm->file->f_path.dentry->d_inode; int rc; @@ -2009,6 +2026,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) } COMMON_AUDIT_DATA_INIT(&ad, PATH); + ad.selinux_audit_data = &sad; ad.u.path = bprm->file->f_path; if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) @@ -2098,6 +2116,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, struct files_struct *files) { struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; struct file *file, *devnull = NULL; struct tty_struct *tty; struct fdtable *fdt; @@ -2135,6 +2154,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, /* Revalidate access to inherited open files. */ COMMON_AUDIT_DATA_INIT(&ad, INODE); + ad.selinux_audit_data = &sad; spin_lock(&files->file_lock); for (;;) { @@ -2472,6 +2492,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) { const struct cred *cred = current_cred(); struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; int rc; rc = superblock_doinit(sb, data); @@ -2483,6 +2504,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) return 0; COMMON_AUDIT_DATA_INIT(&ad, DENTRY); + ad.selinux_audit_data = &sad; ad.u.dentry = sb->s_root; return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); } @@ -2491,8 +2513,10 @@ static int selinux_sb_statfs(struct dentry *dentry) { const struct cred *cred = current_cred(); struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; COMMON_AUDIT_DATA_INIT(&ad, DENTRY); + ad.selinux_audit_data = &sad; ad.u.dentry = dentry->d_sb->s_root; return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); } @@ -2656,6 +2680,7 @@ static int selinux_inode_permission(struct inode *inode, int mask) { const struct cred *cred = current_cred(); struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 perms; bool from_access; unsigned flags = mask & MAY_NOT_BLOCK; @@ -2668,10 +2693,11 @@ static int selinux_inode_permission(struct inode *inode, int mask) return 0; COMMON_AUDIT_DATA_INIT(&ad, INODE); + ad.selinux_audit_data = &sad; ad.u.inode = inode; if (from_access) - ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; + ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; perms = file_mask_to_av(inode->i_mode, mask); @@ -2737,6 +2763,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, struct inode_security_struct *isec = inode->i_security; struct superblock_security_struct *sbsec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 newsid, sid = current_sid(); int rc = 0; @@ -2751,6 +2778,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, return -EPERM; COMMON_AUDIT_DATA_INIT(&ad, DENTRY); + ad.selinux_audit_data = &sad; ad.u.dentry = dentry; rc = avc_has_perm(sid, isec->sid, isec->sclass, @@ -3345,10 +3373,12 @@ static int selinux_kernel_module_request(char *kmod_name) { u32 sid; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; sid = task_sid(current); COMMON_AUDIT_DATA_INIT(&ad, KMOD); + ad.selinux_audit_data = &sad; ad.u.kmod_name = kmod_name; return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, @@ -3721,12 +3751,14 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) { struct sk_security_struct *sksec = sk->sk_security; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 tsid = task_sid(task); if (sksec->sid == SECINITSID_KERNEL) return 0; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.sk = sk; return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); @@ -3805,6 +3837,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in char *addrp; struct sk_security_struct *sksec = sk->sk_security; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; struct sockaddr_in *addr4 = NULL; struct sockaddr_in6 *addr6 = NULL; unsigned short snum; @@ -3831,6 +3864,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in if (err) goto out; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.sport = htons(snum); ad.u.net.family = family; err = avc_has_perm(sksec->sid, sid, @@ -3864,6 +3898,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in goto out; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.sport = htons(snum); ad.u.net.family = family; @@ -3897,6 +3932,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, if (sksec->sclass == SECCLASS_TCP_SOCKET || sksec->sclass == SECCLASS_DCCP_SOCKET) { struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; struct sockaddr_in *addr4 = NULL; struct sockaddr_in6 *addr6 = NULL; unsigned short snum; @@ -3922,6 +3958,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.dport = htons(snum); ad.u.net.family = sk->sk_family; err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); @@ -4012,9 +4049,11 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, struct sk_security_struct *sksec_other = other->sk_security; struct sk_security_struct *sksec_new = newsk->sk_security; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; int err; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.sk = other; err = avc_has_perm(sksec_sock->sid, sksec_other->sid, @@ -4042,8 +4081,10 @@ static int selinux_socket_unix_may_send(struct socket *sock, struct sk_security_struct *ssec = sock->sk->sk_security; struct sk_security_struct *osec = other->sk->sk_security; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.sk = other->sk; return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, @@ -4080,9 +4121,11 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, struct sk_security_struct *sksec = sk->sk_security; u32 sk_sid = sksec->sid; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; char *addrp; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.netif = skb->skb_iif; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); @@ -4111,6 +4154,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) u16 family = sk->sk_family; u32 sk_sid = sksec->sid; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; char *addrp; u8 secmark_active; u8 peerlbl_active; @@ -4135,6 +4179,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) return 0; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.netif = skb->skb_iif; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); @@ -4471,6 +4516,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, char *addrp; u32 peer_sid; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u8 secmark_active; u8 netlbl_active; u8 peerlbl_active; @@ -4488,6 +4534,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, return NF_DROP; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.netif = ifindex; ad.u.net.family = family; if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) @@ -4576,6 +4623,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, struct sock *sk = skb->sk; struct sk_security_struct *sksec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; char *addrp; u8 proto; @@ -4584,6 +4632,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, sksec = sk->sk_security; COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.netif = ifindex; ad.u.net.family = family; if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) @@ -4607,6 +4656,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, u32 peer_sid; struct sock *sk; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; char *addrp; u8 secmark_active; u8 peerlbl_active; @@ -4653,6 +4703,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, } COMMON_AUDIT_DATA_INIT(&ad, NET); + ad.selinux_audit_data = &sad; ad.u.net.netif = ifindex; ad.u.net.family = family; if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) @@ -4769,11 +4820,13 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, { struct ipc_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); isec = ipc_perms->security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = ipc_perms->key; return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); @@ -4794,6 +4847,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) { struct ipc_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); int rc; @@ -4804,6 +4858,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) isec = msq->q_perm.security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = msq->q_perm.key; rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, @@ -4824,11 +4879,13 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) { struct ipc_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); isec = msq->q_perm.security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = msq->q_perm.key; return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, @@ -4868,6 +4925,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, struct ipc_security_struct *isec; struct msg_security_struct *msec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); int rc; @@ -4889,6 +4947,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, } COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = msq->q_perm.key; /* Can this process write to the queue? */ @@ -4913,6 +4972,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, struct ipc_security_struct *isec; struct msg_security_struct *msec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = task_sid(target); int rc; @@ -4920,6 +4980,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, msec = msg->security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = msq->q_perm.key; rc = avc_has_perm(sid, isec->sid, @@ -4935,6 +4996,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) { struct ipc_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); int rc; @@ -4945,6 +5007,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) isec = shp->shm_perm.security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = shp->shm_perm.key; rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, @@ -4965,11 +5028,13 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) { struct ipc_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); isec = shp->shm_perm.security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = shp->shm_perm.key; return avc_has_perm(sid, isec->sid, SECCLASS_SHM, @@ -5027,6 +5092,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) { struct ipc_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); int rc; @@ -5037,6 +5103,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) isec = sma->sem_perm.security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = sma->sem_perm.key; rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, @@ -5057,11 +5124,13 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg) { struct ipc_security_struct *isec; struct common_audit_data ad; + struct selinux_audit_data sad = {0,}; u32 sid = current_sid(); isec = sma->sem_perm.security; COMMON_AUDIT_DATA_INIT(&ad, IPC); + ad.selinux_audit_data = &sad; ad.u.ipc_id = sma->sem_perm.key; return avc_has_perm(sid, isec->sid, SECCLASS_SEM, diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 005a91b..fa13f17 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -46,6 +46,22 @@ struct avc_cache_stats { unsigned int frees; }; +struct selinux_audit_data { + u32 ssid; + u32 tsid; + u16 tclass; + u32 requested; + u32 audited; + u32 denied; + /* + * auditdeny is a bit tricky and unintuitive. See the + * comments in avc.c for it's meaning and usage. + */ + u32 auditdeny; + struct av_decision *avd; + int result; +}; + /* * AVC operations */ diff --git a/security/smack/smack.h b/security/smack/smack.h index 2ad0065..ccba382 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -185,6 +185,15 @@ struct smack_known { */ #define SMK_NUM_ACCESS_TYPE 5 +/* SMACK data */ +struct smack_audit_data { + const char *function; + char *subject; + char *object; + char *request; + int result; +}; + /* * Smack audit data; is empty if CONFIG_AUDIT not set * to save some stack @@ -192,6 +201,7 @@ struct smack_known { struct smk_audit_info { #ifdef CONFIG_AUDIT struct common_audit_data a; + struct smack_audit_data sad; #endif }; /* @@ -311,7 +321,8 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func, { memset(a, 0, sizeof(*a)); a->a.type = type; - a->a.smack_audit_data.function = func; + a->a.smack_audit_data = &a->sad; + a->a.smack_audit_data->function = func; } static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index cc7cb6e..2af7fcc 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -275,9 +275,9 @@ static inline void smack_str_from_perm(char *string, int access) static void smack_log_callback(struct audit_buffer *ab, void *a) { struct common_audit_data *ad = a; - struct smack_audit_data *sad = &ad->smack_audit_data; + struct smack_audit_data *sad = ad->smack_audit_data; audit_log_format(ab, "lsm=SMACK fn=%s action=%s", - ad->smack_audit_data.function, + ad->smack_audit_data->function, sad->result ? "denied" : "granted"); audit_log_format(ab, " subject="); audit_log_untrustedstring(ab, sad->subject); @@ -310,11 +310,12 @@ void smack_log(char *subject_label, char *object_label, int request, if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) return; - if (a->smack_audit_data.function == NULL) - a->smack_audit_data.function = "unknown"; + sad = a->smack_audit_data; + + if (sad->function == NULL) + sad->function = "unknown"; /* end preparing the audit data */ - sad = &a->smack_audit_data; smack_str_from_perm(request_buffer, request); sad->subject = subject_label; sad->object = object_label; -- cgit v0.10.2 From 48c62af68a403ef1655546bd3e021070c8508573 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 2 Apr 2012 13:15:44 -0400 Subject: LSM: shrink the common_audit_data data union After shrinking the common_audit_data stack usage for private LSM data I'm not going to shrink the data union. To do this I'm going to move anything larger than 2 void * ptrs to it's own structure and require it to be declared separately on the calling stack. Thus hot paths which don't need more than a couple pointer don't have to declare space to hold large unneeded structures. I could get this down to one void * by dealing with the key struct and the struct path. We'll see if that is helpful after taking care of networking. Signed-off-by: Eric Paris Signed-off-by: Linus Torvalds diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index 6f4fb37..d1b073f 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h @@ -22,6 +22,23 @@ #include #include +struct lsm_network_audit { + int netif; + struct sock *sk; + u16 family; + __be16 dport; + __be16 sport; + union { + struct { + __be32 daddr; + __be32 saddr; + } v4; + struct { + struct in6_addr daddr; + struct in6_addr saddr; + } v6; + } fam; +}; /* Auxiliary data to use in generating the audit record. */ struct common_audit_data { @@ -41,23 +58,7 @@ struct common_audit_data { struct path path; struct dentry *dentry; struct inode *inode; - struct { - int netif; - struct sock *sk; - u16 family; - __be16 dport; - __be16 sport; - union { - struct { - __be32 daddr; - __be32 saddr; - } v4; - struct { - struct in6_addr daddr; - struct in6_addr saddr; - } v6; - } fam; - } net; + struct lsm_network_audit *net; int cap; int ipc_id; struct task_struct *tsk; diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 8b8f090..e96c6aa 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -49,8 +49,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, if (ih == NULL) return -EINVAL; - ad->u.net.v4info.saddr = ih->saddr; - ad->u.net.v4info.daddr = ih->daddr; + ad->u.net->v4info.saddr = ih->saddr; + ad->u.net->v4info.daddr = ih->daddr; if (proto) *proto = ih->protocol; @@ -64,8 +64,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, if (th == NULL) break; - ad->u.net.sport = th->source; - ad->u.net.dport = th->dest; + ad->u.net->sport = th->source; + ad->u.net->dport = th->dest; break; } case IPPROTO_UDP: { @@ -73,8 +73,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, if (uh == NULL) break; - ad->u.net.sport = uh->source; - ad->u.net.dport = uh->dest; + ad->u.net->sport = uh->source; + ad->u.net->dport = uh->dest; break; } case IPPROTO_DCCP: { @@ -82,16 +82,16 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, if (dh == NULL) break; - ad->u.net.sport = dh->dccph_sport; - ad->u.net.dport = dh->dccph_dport; + ad->u.net->sport = dh->dccph_sport; + ad->u.net->dport = dh->dccph_dport; break; } case IPPROTO_SCTP: { struct sctphdr *sh = sctp_hdr(skb); if (sh == NULL) break; - ad->u.net.sport = sh->source; - ad->u.net.dport = sh->dest; + ad->u.net->sport = sh->source; + ad->u.net->dport = sh->dest; break; } default: @@ -119,8 +119,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, ip6 = ipv6_hdr(skb); if (ip6 == NULL) return -EINVAL; - ad->u.net.v6info.saddr = ip6->saddr; - ad->u.net.v6info.daddr = ip6->daddr; + ad->u.net->v6info.saddr = ip6->saddr; + ad->u.net->v6info.daddr = ip6->daddr; ret = 0; /* IPv6 can have several extension header before the Transport header * skip them */ @@ -140,8 +140,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, if (th == NULL) break; - ad->u.net.sport = th->source; - ad->u.net.dport = th->dest; + ad->u.net->sport = th->source; + ad->u.net->dport = th->dest; break; } case IPPROTO_UDP: { @@ -151,8 +151,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, if (uh == NULL) break; - ad->u.net.sport = uh->source; - ad->u.net.dport = uh->dest; + ad->u.net->sport = uh->source; + ad->u.net->dport = uh->dest; break; } case IPPROTO_DCCP: { @@ -162,8 +162,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, if (dh == NULL) break; - ad->u.net.sport = dh->dccph_sport; - ad->u.net.dport = dh->dccph_dport; + ad->u.net->sport = dh->dccph_sport; + ad->u.net->dport = dh->dccph_dport; break; } case IPPROTO_SCTP: { @@ -172,8 +172,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); if (sh == NULL) break; - ad->u.net.sport = sh->source; - ad->u.net.dport = sh->dest; + ad->u.net->sport = sh->source; + ad->u.net->dport = sh->dest; break; } default: @@ -281,8 +281,8 @@ static void dump_common_audit_data(struct audit_buffer *ab, } break; case LSM_AUDIT_DATA_NET: - if (a->u.net.sk) { - struct sock *sk = a->u.net.sk; + if (a->u.net->sk) { + struct sock *sk = a->u.net->sk; struct unix_sock *u; int len = 0; char *p = NULL; @@ -330,29 +330,29 @@ static void dump_common_audit_data(struct audit_buffer *ab, } } - switch (a->u.net.family) { + switch (a->u.net->family) { case AF_INET: - print_ipv4_addr(ab, a->u.net.v4info.saddr, - a->u.net.sport, + print_ipv4_addr(ab, a->u.net->v4info.saddr, + a->u.net->sport, "saddr", "src"); - print_ipv4_addr(ab, a->u.net.v4info.daddr, - a->u.net.dport, + print_ipv4_addr(ab, a->u.net->v4info.daddr, + a->u.net->dport, "daddr", "dest"); break; case AF_INET6: - print_ipv6_addr(ab, &a->u.net.v6info.saddr, - a->u.net.sport, + print_ipv6_addr(ab, &a->u.net->v6info.saddr, + a->u.net->sport, "saddr", "src"); - print_ipv6_addr(ab, &a->u.net.v6info.daddr, - a->u.net.dport, + print_ipv6_addr(ab, &a->u.net->v6info.daddr, + a->u.net->dport, "daddr", "dest"); break; } - if (a->u.net.netif > 0) { + if (a->u.net->netif > 0) { struct net_device *dev; /* NOTE: we always use init's namespace */ - dev = dev_get_by_index(&init_net, a->u.net.netif); + dev = dev_get_by_index(&init_net, a->u.net->netif); if (dev) { audit_log_format(ab, " netif=%s", dev->name); dev_put(dev); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3861ce4..d85b793 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3517,8 +3517,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, if (ihlen < sizeof(_iph)) goto out; - ad->u.net.v4info.saddr = ih->saddr; - ad->u.net.v4info.daddr = ih->daddr; + ad->u.net->v4info.saddr = ih->saddr; + ad->u.net->v4info.daddr = ih->daddr; ret = 0; if (proto) @@ -3536,8 +3536,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, if (th == NULL) break; - ad->u.net.sport = th->source; - ad->u.net.dport = th->dest; + ad->u.net->sport = th->source; + ad->u.net->dport = th->dest; break; } @@ -3552,8 +3552,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, if (uh == NULL) break; - ad->u.net.sport = uh->source; - ad->u.net.dport = uh->dest; + ad->u.net->sport = uh->source; + ad->u.net->dport = uh->dest; break; } @@ -3568,8 +3568,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, if (dh == NULL) break; - ad->u.net.sport = dh->dccph_sport; - ad->u.net.dport = dh->dccph_dport; + ad->u.net->sport = dh->dccph_sport; + ad->u.net->dport = dh->dccph_dport; break; } @@ -3596,8 +3596,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, if (ip6 == NULL) goto out; - ad->u.net.v6info.saddr = ip6->saddr; - ad->u.net.v6info.daddr = ip6->daddr; + ad->u.net->v6info.saddr = ip6->saddr; + ad->u.net->v6info.daddr = ip6->daddr; ret = 0; nexthdr = ip6->nexthdr; @@ -3617,8 +3617,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, if (th == NULL) break; - ad->u.net.sport = th->source; - ad->u.net.dport = th->dest; + ad->u.net->sport = th->source; + ad->u.net->dport = th->dest; break; } @@ -3629,8 +3629,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, if (uh == NULL) break; - ad->u.net.sport = uh->source; - ad->u.net.dport = uh->dest; + ad->u.net->sport = uh->source; + ad->u.net->dport = uh->dest; break; } @@ -3641,8 +3641,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, if (dh == NULL) break; - ad->u.net.sport = dh->dccph_sport; - ad->u.net.dport = dh->dccph_dport; + ad->u.net->sport = dh->dccph_sport; + ad->u.net->dport = dh->dccph_dport; break; } @@ -3662,13 +3662,13 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, char *addrp; int ret; - switch (ad->u.net.family) { + switch (ad->u.net->family) { case PF_INET: ret = selinux_parse_skb_ipv4(skb, ad, proto); if (ret) goto parse_error; - addrp = (char *)(src ? &ad->u.net.v4info.saddr : - &ad->u.net.v4info.daddr); + addrp = (char *)(src ? &ad->u.net->v4info.saddr : + &ad->u.net->v4info.daddr); goto okay; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -3676,8 +3676,8 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, ret = selinux_parse_skb_ipv6(skb, ad, proto); if (ret) goto parse_error; - addrp = (char *)(src ? &ad->u.net.v6info.saddr : - &ad->u.net.v6info.daddr); + addrp = (char *)(src ? &ad->u.net->v6info.saddr : + &ad->u.net->v6info.daddr); goto okay; #endif /* IPV6 */ default: @@ -3752,6 +3752,7 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) struct sk_security_struct *sksec = sk->sk_security; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; u32 tsid = task_sid(task); if (sksec->sid == SECINITSID_KERNEL) @@ -3759,7 +3760,8 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.sk = sk; + ad.u.net = &net; + ad.u.net->sk = sk; return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); } @@ -3838,6 +3840,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in struct sk_security_struct *sksec = sk->sk_security; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; struct sockaddr_in *addr4 = NULL; struct sockaddr_in6 *addr6 = NULL; unsigned short snum; @@ -3865,8 +3868,9 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in goto out; COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.sport = htons(snum); - ad.u.net.family = family; + ad.u.net = &net; + ad.u.net->sport = htons(snum); + ad.u.net->family = family; err = avc_has_perm(sksec->sid, sid, sksec->sclass, SOCKET__NAME_BIND, &ad); @@ -3899,13 +3903,14 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.sport = htons(snum); - ad.u.net.family = family; + ad.u.net = &net; + ad.u.net->sport = htons(snum); + ad.u.net->family = family; if (family == PF_INET) - ad.u.net.v4info.saddr = addr4->sin_addr.s_addr; + ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; else - ad.u.net.v6info.saddr = addr6->sin6_addr; + ad.u.net->v6info.saddr = addr6->sin6_addr; err = avc_has_perm(sksec->sid, sid, sksec->sclass, node_perm, &ad); @@ -3933,6 +3938,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, sksec->sclass == SECCLASS_DCCP_SOCKET) { struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; struct sockaddr_in *addr4 = NULL; struct sockaddr_in6 *addr6 = NULL; unsigned short snum; @@ -3959,8 +3965,9 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.dport = htons(snum); - ad.u.net.family = sk->sk_family; + ad.u.net = &net; + ad.u.net->dport = htons(snum); + ad.u.net->family = sk->sk_family; err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); if (err) goto out; @@ -4050,11 +4057,13 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, struct sk_security_struct *sksec_new = newsk->sk_security; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; int err; COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.sk = other; + ad.u.net = &net; + ad.u.net->sk = other; err = avc_has_perm(sksec_sock->sid, sksec_other->sid, sksec_other->sclass, @@ -4082,10 +4091,12 @@ static int selinux_socket_unix_may_send(struct socket *sock, struct sk_security_struct *osec = other->sk->sk_security; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.sk = other->sk; + ad.u.net = &net; + ad.u.net->sk = other->sk; return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, &ad); @@ -4122,12 +4133,14 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, u32 sk_sid = sksec->sid; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; char *addrp; COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.netif = skb->skb_iif; - ad.u.net.family = family; + ad.u.net = &net; + ad.u.net->netif = skb->skb_iif; + ad.u.net->family = family; err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); if (err) return err; @@ -4155,6 +4168,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) u32 sk_sid = sksec->sid; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; char *addrp; u8 secmark_active; u8 peerlbl_active; @@ -4180,8 +4194,9 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.netif = skb->skb_iif; - ad.u.net.family = family; + ad.u.net = &net; + ad.u.net->netif = skb->skb_iif; + ad.u.net->family = family; err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); if (err) return err; @@ -4517,6 +4532,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, u32 peer_sid; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; u8 secmark_active; u8 netlbl_active; u8 peerlbl_active; @@ -4535,8 +4551,9 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.netif = ifindex; - ad.u.net.family = family; + ad.u.net = &net; + ad.u.net->netif = ifindex; + ad.u.net->family = family; if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) return NF_DROP; @@ -4624,6 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, struct sk_security_struct *sksec; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; char *addrp; u8 proto; @@ -4633,8 +4651,9 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.netif = ifindex; - ad.u.net.family = family; + ad.u.net = &net; + ad.u.net->netif = ifindex; + ad.u.net->family = family; if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) return NF_DROP; @@ -4657,6 +4676,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, struct sock *sk; struct common_audit_data ad; struct selinux_audit_data sad = {0,}; + struct lsm_network_audit net = {0,}; char *addrp; u8 secmark_active; u8 peerlbl_active; @@ -4704,8 +4724,9 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, COMMON_AUDIT_DATA_INIT(&ad, NET); ad.selinux_audit_data = &sad; - ad.u.net.netif = ifindex; - ad.u.net.family = family; + ad.u.net = &net; + ad.u.net->netif = ifindex; + ad.u.net->family = family; if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) return NF_DROP; diff --git a/security/smack/smack.h b/security/smack/smack.h index ccba382..4ede719 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -325,6 +325,14 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func, a->a.smack_audit_data->function = func; } +static inline void smk_ad_init_net(struct smk_audit_info *a, const char *func, + char type, struct lsm_network_audit *net) +{ + smk_ad_init(a, func, type); + memset(net, 0, sizeof(*net)); + a->a.u.net = net; +} + static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, struct task_struct *t) { @@ -348,7 +356,7 @@ static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a, static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a, struct sock *sk) { - a->a.u.net.sk = sk; + a->a.u.net->sk = sk; } #else /* no AUDIT */ diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index cd667b4..81c03a5 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1939,16 +1939,17 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) char *hostsp; struct socket_smack *ssp = sk->sk_security; struct smk_audit_info ad; + struct lsm_network_audit net; rcu_read_lock(); hostsp = smack_host_label(sap); if (hostsp != NULL) { sk_lbl = SMACK_UNLABELED_SOCKET; #ifdef CONFIG_AUDIT - smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); - ad.a.u.net.family = sap->sin_family; - ad.a.u.net.dport = sap->sin_port; - ad.a.u.net.v4info.daddr = sap->sin_addr.s_addr; + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); + ad.a.u.net->family = sap->sin_family; + ad.a.u.net->dport = sap->sin_port; + ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; #endif rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); } else { @@ -2808,9 +2809,10 @@ static int smack_unix_stream_connect(struct sock *sock, struct socket_smack *osp = other->sk_security; struct socket_smack *nsp = newsk->sk_security; struct smk_audit_info ad; + struct lsm_network_audit net; int rc = 0; - smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other); if (!capable(CAP_MAC_OVERRIDE)) @@ -2840,9 +2842,10 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) struct socket_smack *ssp = sock->sk->sk_security; struct socket_smack *osp = other->sk->sk_security; struct smk_audit_info ad; + struct lsm_network_audit net; int rc = 0; - smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other->sk); if (!capable(CAP_MAC_OVERRIDE)) @@ -2990,6 +2993,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) char *csp; int rc; struct smk_audit_info ad; + struct lsm_network_audit net; if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) return 0; @@ -3007,9 +3011,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) netlbl_secattr_destroy(&secattr); #ifdef CONFIG_AUDIT - smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); - ad.a.u.net.family = sk->sk_family; - ad.a.u.net.netif = skb->skb_iif; + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); + ad.a.u.net->family = sk->sk_family; + ad.a.u.net->netif = skb->skb_iif; ipv4_skb_to_auditdata(skb, &ad.a, NULL); #endif /* @@ -3152,6 +3156,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, char *sp; int rc; struct smk_audit_info ad; + struct lsm_network_audit net; /* handle mapped IPv4 packets arriving via IPv6 sockets */ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) @@ -3166,9 +3171,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, netlbl_secattr_destroy(&secattr); #ifdef CONFIG_AUDIT - smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); - ad.a.u.net.family = family; - ad.a.u.net.netif = skb->skb_iif; + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); + ad.a.u.net->family = family; + ad.a.u.net->netif = skb->skb_iif; ipv4_skb_to_auditdata(skb, &ad.a, NULL); #endif /* -- cgit v0.10.2 From 7f6a47cf1477ffae9cff1d6ee181e2ce6bfb2f02 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 2 Apr 2012 13:15:50 -0400 Subject: SELinux: remove avd from selinux_audit_data We do not use it. Remove it. Signed-off-by: Eric Paris Signed-off-by: Linus Torvalds diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index fa13f17..09c3eda 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -58,7 +58,6 @@ struct selinux_audit_data { * comments in avc.c for it's meaning and usage. */ u32 auditdeny; - struct av_decision *avd; int result; }; -- cgit v0.10.2 From f8294f1144ad0630075918df4bf94075f5384604 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 2 Apr 2012 13:15:55 -0400 Subject: SELinux: remove avd from slow_avc_audit() We don't use the argument, so remove it. Signed-off-by: Eric Paris Signed-off-by: Linus Torvalds diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 00f3860..b5545a8 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -460,7 +460,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) /* This is the slow part of avc audit with big stack footprint */ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, u32 audited, u32 denied, - struct av_decision *avd, struct common_audit_data *a, + struct common_audit_data *a, unsigned flags) { struct common_audit_data stack_data; @@ -553,7 +553,7 @@ inline int avc_audit(u32 ssid, u32 tsid, return slow_avc_audit(ssid, tsid, tclass, requested, audited, denied, - avd, a, flags); + a, flags); } /** -- cgit v0.10.2 From 3f0882c48286e7bdb0bbdec9c4bfa934e0db8e09 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Apr 2012 09:38:00 -0700 Subject: SELinux: do not allocate stack space for AVC data unless needed Instead of declaring the entire selinux_audit_data on the stack when we start an operation on declare it on the stack if we are going to use it. We know it's usefulness at the end of the security decision and can declare it there. Signed-off-by: Eric Paris Signed-off-by: Linus Torvalds diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b5545a8..36c42bb 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) { struct common_audit_data *ad = a; audit_log_format(ab, "avc: %s ", - ad->selinux_audit_data->denied ? "denied" : "granted"); - avc_dump_av(ab, ad->selinux_audit_data->tclass, - ad->selinux_audit_data->audited); + ad->selinux_audit_data->slad->denied ? "denied" : "granted"); + avc_dump_av(ab, ad->selinux_audit_data->slad->tclass, + ad->selinux_audit_data->slad->audited); audit_log_format(ab, " for "); } @@ -452,9 +452,9 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) { struct common_audit_data *ad = a; audit_log_format(ab, " "); - avc_dump_query(ab, ad->selinux_audit_data->ssid, - ad->selinux_audit_data->tsid, - ad->selinux_audit_data->tclass); + avc_dump_query(ab, ad->selinux_audit_data->slad->ssid, + ad->selinux_audit_data->slad->tsid, + ad->selinux_audit_data->slad->tclass); } /* This is the slow part of avc audit with big stack footprint */ @@ -465,6 +465,7 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, { struct common_audit_data stack_data; struct selinux_audit_data sad = {0,}; + struct selinux_late_audit_data slad; if (!a) { a = &stack_data; @@ -483,12 +484,14 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, (flags & MAY_NOT_BLOCK)) return -ECHILD; - a->selinux_audit_data->tclass = tclass; - a->selinux_audit_data->requested = requested; - a->selinux_audit_data->ssid = ssid; - a->selinux_audit_data->tsid = tsid; - a->selinux_audit_data->audited = audited; - a->selinux_audit_data->denied = denied; + slad.tclass = tclass; + slad.requested = requested; + slad.ssid = ssid; + slad.tsid = tsid; + slad.audited = audited; + slad.denied = denied; + + a->selinux_audit_data->slad = &slad; a->lsm_pre_audit = avc_audit_pre_callback; a->lsm_post_audit = avc_audit_post_callback; common_lsm_audit(a); diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 09c3eda..1931370 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -46,19 +46,29 @@ struct avc_cache_stats { unsigned int frees; }; -struct selinux_audit_data { +/* + * We only need this data after we have decided to send an audit message. + */ +struct selinux_late_audit_data { u32 ssid; u32 tsid; u16 tclass; u32 requested; u32 audited; u32 denied; + int result; +}; + +/* + * We collect this at the beginning or during an selinux security operation + */ +struct selinux_audit_data { /* * auditdeny is a bit tricky and unintuitive. See the * comments in avc.c for it's meaning and usage. */ u32 auditdeny; - int result; + struct selinux_late_audit_data *slad; }; /* -- cgit v0.10.2 From b61c37f57988567c84359645f8202a7c84bc798a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 2 Apr 2012 15:48:12 -0700 Subject: lsm_audit: don't specify the audit pre/post callbacks in 'struct common_audit_data' It just bloats the audit data structure for no good reason, since the only time those fields are filled are just before calling the common_lsm_audit() function, which is also the only user of those fields. So just make them be the arguments to common_lsm_audit(), rather than bloating that structure that is passed around everywhere, and is initialized in hot paths. Signed-off-by: Linus Torvalds diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index d1b073f..fad48aa 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h @@ -82,9 +82,6 @@ struct common_audit_data { struct apparmor_audit_data *apparmor_audit_data; #endif }; /* per LSM data pointer union */ - /* these callback will be implemented by a specific LSM */ - void (*lsm_pre_audit)(struct audit_buffer *, void *); - void (*lsm_post_audit)(struct audit_buffer *, void *); }; #define v4info fam.v4 @@ -101,6 +98,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, { memset((_d), 0, sizeof(struct common_audit_data)); \ (_d)->type = LSM_AUDIT_DATA_##_t; } -void common_lsm_audit(struct common_audit_data *a); +void common_lsm_audit(struct common_audit_data *a, + void (*pre_audit)(struct audit_buffer *, void *), + void (*post_audit)(struct audit_buffer *, void *)); #endif diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 23f7eb6..cc3520d 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -160,9 +160,7 @@ void aa_audit_msg(int type, struct common_audit_data *sa, void (*cb) (struct audit_buffer *, void *)) { sa->aad->type = type; - sa->lsm_pre_audit = audit_pre; - sa->lsm_post_audit = cb; - common_lsm_audit(sa); + common_lsm_audit(sa, audit_pre, cb); } /** diff --git a/security/lsm_audit.c b/security/lsm_audit.c index e96c6aa..90c129b 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -378,11 +378,15 @@ static void dump_common_audit_data(struct audit_buffer *ab, /** * common_lsm_audit - generic LSM auditing function * @a: auxiliary audit data + * @pre_audit: lsm-specific pre-audit callback + * @post_audit: lsm-specific post-audit callback * * setup the audit buffer for common security information * uses callback to print LSM specific information */ -void common_lsm_audit(struct common_audit_data *a) +void common_lsm_audit(struct common_audit_data *a, + void (*pre_audit)(struct audit_buffer *, void *), + void (*post_audit)(struct audit_buffer *, void *)) { struct audit_buffer *ab; @@ -394,13 +398,13 @@ void common_lsm_audit(struct common_audit_data *a) if (ab == NULL) return; - if (a->lsm_pre_audit) - a->lsm_pre_audit(ab, a); + if (pre_audit) + pre_audit(ab, a); dump_common_audit_data(ab, a); - if (a->lsm_post_audit) - a->lsm_post_audit(ab, a); + if (post_audit) + post_audit(ab, a); audit_log_end(ab); } diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 36c42bb..8ee42b2 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -492,9 +492,7 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, slad.denied = denied; a->selinux_audit_data->slad = &slad; - a->lsm_pre_audit = avc_audit_pre_callback; - a->lsm_post_audit = avc_audit_post_callback; - common_lsm_audit(a); + common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); return 0; } diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 2af7fcc..c8115f7 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -321,9 +321,8 @@ void smack_log(char *subject_label, char *object_label, int request, sad->object = object_label; sad->request = request_buffer; sad->result = result; - a->lsm_pre_audit = smack_log_callback; - common_lsm_audit(a); + common_lsm_audit(a, smack_log_callback, NULL); } #else /* #ifdef CONFIG_AUDIT */ void smack_log(char *subject_label, char *object_label, int request, -- cgit v0.10.2 From 54da0784e24d955eab5f750a8c7c602aa8d4b4e3 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Fri, 23 Mar 2012 02:21:33 -0700 Subject: ARM: OMAP2+: smsc911x: Remove odd gpmc_cfg/board_data redirection This seems to be a leftover from when gpmc-smsc911x.c was copied from gpmc-smc91x.c. Signed-off-by: Russ Dill Tested-by: Igor Grinberg Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c index 5e5880d..aa0c296 100644 --- a/arch/arm/mach-omap2/gpmc-smsc911x.c +++ b/arch/arm/mach-omap2/gpmc-smsc911x.c @@ -26,8 +26,6 @@ #include #include -static struct omap_smsc911x_platform_data *gpmc_cfg; - static struct resource gpmc_smsc911x_resources[] = { [0] = { .flags = IORESOURCE_MEM, @@ -93,14 +91,12 @@ static struct platform_device gpmc_smsc911x_regulator = { * assume that pin multiplexing is done in the board-*.c file, * or in the bootloader. */ -void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data) +void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) { struct platform_device *pdev; unsigned long cs_mem_base; int ret; - gpmc_cfg = board_data; - if (!gpmc_cfg->id) { ret = platform_device_register(&gpmc_smsc911x_regulator); if (ret < 0) { -- cgit v0.10.2 From a0dbf2a726e5387251a567c8531d9fd3e34d2dfb Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Fri, 23 Mar 2012 02:21:34 -0700 Subject: ARM: OMAP2+ smsc911x: Fix possible stale smsc911x flags If this function is called the first time with flags set, and the second time without flags set then the leftover flags from the first called will be used rather than the desired default flags. Signed-off-by: Russ Dill Tested-by: Igor Grinberg Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c index aa0c296..f9446ea 100644 --- a/arch/arm/mach-omap2/gpmc-smsc911x.c +++ b/arch/arm/mach-omap2/gpmc-smsc911x.c @@ -39,7 +39,6 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = { .phy_interface = PHY_INTERFACE_MODE_MII, .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, - .flags = SMSC911X_USE_16BIT, }; static struct regulator_consumer_supply gpmc_smsc911x_supply[] = { @@ -135,8 +134,7 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) gpio_set_value(gpmc_cfg->gpio_reset, 1); } - if (gpmc_cfg->flags) - gpmc_smsc911x_config.flags = gpmc_cfg->flags; + gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT; pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id, gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources), -- cgit v0.10.2 From a297068c1fa529c350e7923b85372ca3b38dcdc5 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Fri, 23 Mar 2012 02:21:35 -0700 Subject: ARM: OMAP2+: smsc911x: Remove unused rate calculation Looking back into git history, this code was never used and was probably left over from a copy/paste. Signed-off-by: Russ Dill Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 4c90f07..b90b319 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -114,15 +114,6 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = { static inline void __init omap3evm_init_smsc911x(void) { - struct clk *l3ck; - unsigned int rate; - - l3ck = clk_get(NULL, "l3_ck"); - if (IS_ERR(l3ck)) - rate = 100000000; - else - rate = clk_get_rate(l3ck); - /* Configure ethernet controller reset gpio */ if (cpu_is_omap3430()) { if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1) diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 6410043..de95352 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -72,15 +72,6 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = { static inline void __init omap3stalker_init_eth(void) { - struct clk *l3ck; - unsigned int rate; - - l3ck = clk_get(NULL, "l3_ck"); - if (IS_ERR(l3ck)) - rate = 100000000; - else - rate = clk_get_rate(l3ck); - omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP); gpmc_smsc911x_init(&smsc911x_cfg); } -- cgit v0.10.2 From bdacbce65492f54e02a97c23328ec4bbcc31554a Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Fri, 23 Mar 2012 02:21:36 -0700 Subject: ARM: OMAP2+: smsc911x: Remove regulator support from gmpc-smsc911x Adding in support for regulators here creates several headaches. - Boards that declare their own regulator cannot use this function. - Multiple calls to this function require special handling. - Boards that declare id's other than '0' need special handling. Now that there is a simple regulator_register_fixed, we can push this registration back into the board files. Signed-off-by: Russ Dill Tested-by: Igor Grinberg Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c index f9446ea..b6c77be 100644 --- a/arch/arm/mach-omap2/gpmc-smsc911x.c +++ b/arch/arm/mach-omap2/gpmc-smsc911x.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include @@ -41,50 +39,6 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = { .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, }; -static struct regulator_consumer_supply gpmc_smsc911x_supply[] = { - REGULATOR_SUPPLY("vddvario", "smsc911x.0"), - REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), -}; - -/* Generic regulator definition to satisfy smsc911x */ -static struct regulator_init_data gpmc_smsc911x_reg_init_data = { - .constraints = { - .min_uV = 3300000, - .max_uV = 3300000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(gpmc_smsc911x_supply), - .consumer_supplies = gpmc_smsc911x_supply, -}; - -static struct fixed_voltage_config gpmc_smsc911x_fixed_reg_data = { - .supply_name = "gpmc_smsc911x", - .microvolts = 3300000, - .gpio = -EINVAL, - .startup_delay = 0, - .enable_high = 0, - .enabled_at_boot = 1, - .init_data = &gpmc_smsc911x_reg_init_data, -}; - -/* - * Platform device id of 42 is a temporary fix to avoid conflicts - * with other reg-fixed-voltage devices. The real fix should - * involve the driver core providing a way of dynamically - * assigning a unique id on registration for platform devices - * in the same name space. - */ -static struct platform_device gpmc_smsc911x_regulator = { - .name = "reg-fixed-voltage", - .id = 42, - .dev = { - .platform_data = &gpmc_smsc911x_fixed_reg_data, - }, -}; - /* * Initialize smsc911x device connected to the GPMC. Note that we * assume that pin multiplexing is done in the board-*.c file, @@ -96,15 +50,6 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) unsigned long cs_mem_base; int ret; - if (!gpmc_cfg->id) { - ret = platform_device_register(&gpmc_smsc911x_regulator); - if (ret < 0) { - pr_err("Unable to register smsc911x regulators: %d\n", - ret); - return; - } - } - if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) { pr_err("Failed to request GPMC mem region\n"); return; -- cgit v0.10.2 From 5b3689f4c16bc692a2e2b9808e5efc457aeae371 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Fri, 23 Mar 2012 02:21:37 -0700 Subject: ARM: OMAP2+: smsc911x: Add fixed board regulators Initialize fixed regulators in the board files. Trying to do this in a generic way in gpmc-smsc911x.c gets messy as the regulator may be provided by drivers, such as twl4030, for some boards. Signed-off-by: Russ Dill Signed-off-by: Igor Grinberg [tony@atomide.com: combined into one patch, updated comments] Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 41b0a2f..909a8b9 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -81,8 +82,23 @@ static struct omap_smsc911x_platform_data sb_t35_smsc911x_cfg = { .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, }; +static struct regulator_consumer_supply cm_t35_smsc911x_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + +static struct regulator_consumer_supply sb_t35_smsc911x_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.1"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.1"), +}; + static void __init cm_t35_init_ethernet(void) { + regulator_register_fixed(0, cm_t35_smsc911x_supplies, + ARRAY_SIZE(cm_t35_smsc911x_supplies)); + regulator_register_fixed(1, sb_t35_smsc911x_supplies, + ARRAY_SIZE(sb_t35_smsc911x_supplies)); + gpmc_smsc911x_init(&cm_t35_smsc911x_cfg); gpmc_smsc911x_init(&sb_t35_smsc911x_cfg); } diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index e558800..930c0d3 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -634,8 +634,14 @@ static void __init igep_wlan_bt_init(void) static inline void __init igep_wlan_bt_init(void) { } #endif +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + static void __init igep_init(void) { + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); /* Get IGEP2 hardware revision */ diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index d50a562a..1b60495 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -410,8 +411,14 @@ static struct mtd_partition ldp_nand_partitions[] = { }; +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + static void __init omap_ldp_init(void) { + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); ldp_init_smsc911x(); omap_i2c_init(); diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index b90b319..49df127 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -623,9 +623,15 @@ static void __init omap3_evm_wl12xx_init(void) #endif } +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + static void __init omap3_evm_init(void) { omap3_evm_get_revision(); + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); if (cpu_is_omap3630()) omap3_mux_init(omap36x_board_mux, OMAP_PACKAGE_CBB); diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c index 4a7d8c8..9b3c141 100644 --- a/arch/arm/mach-omap2/board-omap3logic.c +++ b/arch/arm/mach-omap2/board-omap3logic.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -188,8 +189,14 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + static void __init omap3logic_init(void) { + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3torpedo_fix_pbias_voltage(); omap3logic_i2c_init(); diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index de95352..4dffc95 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -410,8 +411,14 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + static void __init omap3_stalker_init(void) { + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); omap3_mux_init(board_mux, OMAP_PACKAGE_CUS); omap_board_config = omap3_stalker_config; omap_board_config_size = ARRAY_SIZE(omap3_stalker_config); diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 668533e..33aa391 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -498,10 +498,18 @@ static struct gpio overo_bt_gpios[] __initdata = { { OVERO_GPIO_BT_NRESET, GPIOF_OUT_INIT_HIGH, "lcd bl enable" }, }; +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), + REGULATOR_SUPPLY("vddvario", "smsc911x.1"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.1"), +}; + static void __init overo_init(void) { int ret; + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap_hsmmc_init(mmc); overo_i2c_init(); diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c index 1e8540e..f64f441 100644 --- a/arch/arm/mach-omap2/board-zoom-debugboard.c +++ b/arch/arm/mach-omap2/board-zoom-debugboard.c @@ -14,6 +14,9 @@ #include #include +#include +#include + #include #include @@ -117,11 +120,17 @@ static struct platform_device *zoom_devices[] __initdata = { &zoom_debugboard_serial_device, }; +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x.0"), + REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), +}; + int __init zoom_debugboard_init(void) { if (!omap_zoom_debugboard_detect()) return 0; + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); zoom_init_smsc911x(); zoom_init_quaduart(); return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices)); -- cgit v0.10.2 From b7782d3f08b69bea64ed639284b5be948f63c6df Mon Sep 17 00:00:00 2001 From: R Sricharan Date: Fri, 30 Mar 2012 14:27:43 +0530 Subject: ARM: OMAP2+: Fix omap2+ build error With CONFIG_OMAP4_ERRATA_I688 enabled, omap2+ build was broken as below: arch/arm/kernel/io.c: In function '_memcpy_toio': arch/arm/kernel/io.c:29: error: implicit declaration of function 'outer_sync' make[1]: *** [arch/arm/kernel/io.o] Error 1 This was caused by commit 9f97da78 (Disintegrate asm/system.h for ARM). Signed-off-by: R Sricharan Acked-by: Santosh Shilimkar [tony@atomide.com: updated comments] Signed-off-by: Tony Lindgren diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h index 44f4a09..0511238 100644 --- a/arch/arm/include/asm/barrier.h +++ b/arch/arm/include/asm/barrier.h @@ -2,6 +2,7 @@ #define __ASM_BARRIER_H #ifndef __ASSEMBLY__ +#include #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); @@ -39,7 +40,6 @@ #ifdef CONFIG_ARCH_HAS_BARRIERS #include #elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP) -#include #define mb() do { dsb(); outer_sync(); } while (0) #define rmb() dsb() #define wmb() mb() -- cgit v0.10.2 From 1512f0dbfb9e355bc451fc6ded815a79d00bc6f3 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 26 Mar 2012 16:51:10 +0200 Subject: ARM: OMAP: fix section mismatches in usb-host.c Fix the below section mismatch warning and alike: WARNING: vmlinux.o(.text+0x281d4): Section mismatch in reference from the function setup_ehci_io_mux() to the function .init.text:omap_mux_init_signal() The function setup_ehci_io_mux() references the function __init omap_mux_init_signal(). This is often because setup_ehci_io_mux lacks a __init annotation or the annotation of omap_mux_init_signal is wrong. Signed-off-by: Igor Grinberg Reviewed-by: Shubhrajyoti D Acked-by: Felipe Balbi Signed-off-by: Tony Lindgren diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index f51348d..dde8a11 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c @@ -54,7 +54,7 @@ static struct omap_device_pm_latency omap_uhhtll_latency[] = { /* * setup_ehci_io_mux - initialize IO pad mux for USBHOST */ -static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode) +static void __init setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode) { switch (port_mode[0]) { case OMAP_EHCI_PORT_MODE_PHY: @@ -197,7 +197,8 @@ static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode) return; } -static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode) +static +void __init setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode) { switch (port_mode[0]) { case OMAP_EHCI_PORT_MODE_PHY: @@ -315,7 +316,7 @@ static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode) } } -static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) +static void __init setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) { switch (port_mode[0]) { case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: @@ -412,7 +413,8 @@ static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) } } -static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) +static +void __init setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) { switch (port_mode[0]) { case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: -- cgit v0.10.2 From 2def16ae6b0c77571200f18ba4be049b03d75579 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 2 Apr 2012 22:33:02 +0000 Subject: net: fix /proc/net/dev regression Commit f04565ddf52 (dev: use name hash for dev_seq_ops) added a second regression, as some devices are missing from /proc/net/dev if many devices are defined. When seq_file buffer is filled, the last ->next/show() method is canceled (pos value is reverted to value prior ->next() call) Problem is after above commit, we dont restart the lookup at right position in ->start() method. Fix this by removing the internal 'pos' pointer added in commit, since we need to use the 'loff_t *pos' provided by seq_file layer. This also reverts commit 5cac98dd0 (net: Fix corruption in /proc/*/net/dev_mcast), since its not needed anymore. Reported-by: Ben Greear Signed-off-by: Eric Dumazet Cc: Mihai Maruseac Tested-by: Ben Greear Signed-off-by: David S. Miller diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1f77540..5cbaa20 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2604,8 +2604,6 @@ extern void net_disable_timestamp(void); extern void *dev_seq_start(struct seq_file *seq, loff_t *pos); extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos); extern void dev_seq_stop(struct seq_file *seq, void *v); -extern int dev_seq_open_ops(struct inode *inode, struct file *file, - const struct seq_operations *ops); #endif extern int netdev_class_create_file(struct class_attribute *class_attr); diff --git a/net/core/dev.c b/net/core/dev.c index 6c7dc9d..c25d453 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4028,54 +4028,41 @@ static int dev_ifconf(struct net *net, char __user *arg) #ifdef CONFIG_PROC_FS -#define BUCKET_SPACE (32 - NETDEV_HASHBITS) - -struct dev_iter_state { - struct seq_net_private p; - unsigned int pos; /* bucket << BUCKET_SPACE + offset */ -}; +#define BUCKET_SPACE (32 - NETDEV_HASHBITS - 1) #define get_bucket(x) ((x) >> BUCKET_SPACE) #define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1)) #define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o)) -static inline struct net_device *dev_from_same_bucket(struct seq_file *seq) +static inline struct net_device *dev_from_same_bucket(struct seq_file *seq, loff_t *pos) { - struct dev_iter_state *state = seq->private; struct net *net = seq_file_net(seq); struct net_device *dev; struct hlist_node *p; struct hlist_head *h; - unsigned int count, bucket, offset; + unsigned int count = 0, offset = get_offset(*pos); - bucket = get_bucket(state->pos); - offset = get_offset(state->pos); - h = &net->dev_name_head[bucket]; - count = 0; + h = &net->dev_name_head[get_bucket(*pos)]; hlist_for_each_entry_rcu(dev, p, h, name_hlist) { - if (count++ == offset) { - state->pos = set_bucket_offset(bucket, count); + if (++count == offset) return dev; - } } return NULL; } -static inline struct net_device *dev_from_new_bucket(struct seq_file *seq) +static inline struct net_device *dev_from_bucket(struct seq_file *seq, loff_t *pos) { - struct dev_iter_state *state = seq->private; struct net_device *dev; unsigned int bucket; - bucket = get_bucket(state->pos); do { - dev = dev_from_same_bucket(seq); + dev = dev_from_same_bucket(seq, pos); if (dev) return dev; - bucket++; - state->pos = set_bucket_offset(bucket, 0); + bucket = get_bucket(*pos) + 1; + *pos = set_bucket_offset(bucket, 1); } while (bucket < NETDEV_HASHENTRIES); return NULL; @@ -4088,33 +4075,20 @@ static inline struct net_device *dev_from_new_bucket(struct seq_file *seq) void *dev_seq_start(struct seq_file *seq, loff_t *pos) __acquires(RCU) { - struct dev_iter_state *state = seq->private; - rcu_read_lock(); if (!*pos) return SEQ_START_TOKEN; - /* check for end of the hash */ - if (state->pos == 0 && *pos > 1) + if (get_bucket(*pos) >= NETDEV_HASHENTRIES) return NULL; - return dev_from_new_bucket(seq); + return dev_from_bucket(seq, pos); } void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct net_device *dev; - ++*pos; - - if (v == SEQ_START_TOKEN) - return dev_from_new_bucket(seq); - - dev = dev_from_same_bucket(seq); - if (dev) - return dev; - - return dev_from_new_bucket(seq); + return dev_from_bucket(seq, pos); } void dev_seq_stop(struct seq_file *seq, void *v) @@ -4213,13 +4187,7 @@ static const struct seq_operations dev_seq_ops = { static int dev_seq_open(struct inode *inode, struct file *file) { return seq_open_net(inode, file, &dev_seq_ops, - sizeof(struct dev_iter_state)); -} - -int dev_seq_open_ops(struct inode *inode, struct file *file, - const struct seq_operations *ops) -{ - return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state)); + sizeof(struct seq_net_private)); } static const struct file_operations dev_seq_fops = { diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 29c07fe..626698f 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -696,7 +696,8 @@ static const struct seq_operations dev_mc_seq_ops = { static int dev_mc_seq_open(struct inode *inode, struct file *file) { - return dev_seq_open_ops(inode, file, &dev_mc_seq_ops); + return seq_open_net(inode, file, &dev_mc_seq_ops, + sizeof(struct seq_net_private)); } static const struct file_operations dev_mc_seq_fops = { -- cgit v0.10.2 From e675f0cc9a872fd152edc0c77acfed19bf28b81e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 26 Mar 2012 00:03:42 +0000 Subject: ppp: Don't stop and restart queue on every TX packet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For every transmitted packet, ppp_start_xmit() will stop the netdev queue and then, if appropriate, restart it. This causes the TX softirq to run, entirely gratuitously. This is "only" a waste of CPU time in the normal case, but it's actively harmful when the PPP device is a TEQL slave — the wakeup will cause the offending device to receive the next TX packet from the TEQL queue, when it *should* have gone to the next slave in the list. We end up seeing large bursts of packets on just *one* slave device, rather than using the full available bandwidth over all slaves. This patch fixes the problem by *not* unconditionally stopping the queue in ppp_start_xmit(). It adds a return value from ppp_xmit_process() which indicates whether the queue should be stopped or not. It *doesn't* remove the call to netif_wake_queue() from ppp_xmit_process(), because other code paths (especially from ppp_output_wakeup()) need it there and it's messy to push it out to the other callers to do it based on the return value. So we leave it in place — it's a no-op in the case where the queue wasn't stopped, so it's harmless in the TX path. Signed-off-by: David Woodhouse Signed-off-by: David S. Miller diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 159da29..33f8c51 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -235,7 +235,7 @@ struct ppp_net { /* Prototypes. */ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, struct file *file, unsigned int cmd, unsigned long arg); -static void ppp_xmit_process(struct ppp *ppp); +static int ppp_xmit_process(struct ppp *ppp); static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); static void ppp_push(struct ppp *ppp); static void ppp_channel_push(struct channel *pch); @@ -968,9 +968,9 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) proto = npindex_to_proto[npi]; put_unaligned_be16(proto, pp); - netif_stop_queue(dev); skb_queue_tail(&ppp->file.xq, skb); - ppp_xmit_process(ppp); + if (!ppp_xmit_process(ppp)) + netif_stop_queue(dev); return NETDEV_TX_OK; outf: @@ -1048,10 +1048,11 @@ static void ppp_setup(struct net_device *dev) * Called to do any work queued up on the transmit side * that can now be done. */ -static void +static int ppp_xmit_process(struct ppp *ppp) { struct sk_buff *skb; + int ret = 0; ppp_xmit_lock(ppp); if (!ppp->closing) { @@ -1061,10 +1062,13 @@ ppp_xmit_process(struct ppp *ppp) ppp_send_frame(ppp, skb); /* If there's no work left to do, tell the core net code that we can accept some more. */ - if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) + if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) { netif_wake_queue(ppp->dev); + ret = 1; + } } ppp_xmit_unlock(ppp); + return ret; } static inline struct sk_buff * -- cgit v0.10.2 From 2f53384424251c06038ae612e56231b96ab610ee Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 3 Apr 2012 09:37:01 +0000 Subject: tcp: allow splice() to build full TSO packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vmsplice()/splice(pipe, socket) call do_tcp_sendpages() one page at a time, adding at most 4096 bytes to an skb. (assuming PAGE_SIZE=4096) The call to tcp_push() at the end of do_tcp_sendpages() forces an immediate xmit when pipe is not already filled, and tso_fragment() try to split these skb to MSS multiples. 4096 bytes are usually split in a skb with 2 MSS, and a remaining sub-mss skb (assuming MTU=1500) This makes slow start suboptimal because many small frames are sent to qdisc/driver layers instead of big ones (constrained by cwnd and packets in flight of course) In fact, applications using sendmsg() (adding an additional memory copy) instead of vmsplice()/splice()/sendfile() are a bit faster because of this anomaly, especially if serving small files in environments with large initial [c]wnd. Call tcp_push() only if MSG_MORE is not set in the flags parameter. This bit is automatically provided by splice() internals but for the last page, or on all pages if user specified SPLICE_F_MORE splice() flag. In some workloads, this can reduce number of sent logical packets by an order of magnitude, making zero-copy TCP actually faster than one-copy :) Reported-by: Tom Herbert Cc: Nandita Dukkipati Cc: Neal Cardwell Cc: Tom Herbert Cc: Yuchung Cheng Cc: H.K. Jerry Chu Cc: Maciej Żenczykowski Cc: Mahesh Bandewar Cc: Ilpo Järvinen Signed-off-by: Eric Dumazet com> Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index cfd7edd..2ff6f45 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -860,7 +860,7 @@ wait_for_memory: } out: - if (copied) + if (copied && !(flags & MSG_MORE)) tcp_push(sk, flags, mss_now, tp->nonagle); return copied; -- cgit v0.10.2 From 5d6bd8619db5a30668093c1b2967674645cf0736 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Tue, 3 Apr 2012 08:41:40 +0000 Subject: TCP: update ip_local_port_range documentation The explanation of ip_local_port_range in Documentation/networking/ip-sysctl.txt contains several factual errors: - The default value of ip_local_port_range does not depend on the amount of memory available in the system. - tcp_tw_recycle is not enabled by default. - 1024-4999 is not the default value. - Etc. Clean up the mess. Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: David S. Miller diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index ad3e80e..bd80ba5 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -604,15 +604,8 @@ IP Variables: ip_local_port_range - 2 INTEGERS Defines the local port range that is used by TCP and UDP to choose the local port. The first number is the first, the - second the last local port number. Default value depends on - amount of memory available on the system: - > 128Mb 32768-61000 - < 128Mb 1024-4999 or even less. - This number defines number of active connections, which this - system can issue simultaneously to systems not supporting - TCP extensions (timestamps). With tcp_tw_recycle enabled - (i.e. by default) range 1024-4999 is enough to issue up to - 2000 connections per second to systems supporting timestamps. + second the last local port number. The default values are + 32768 and 61000 respectively. ip_local_reserved_ports - list of comma separated ranges Specify the ports which are reserved for known third-party -- cgit v0.10.2 From f03fb3f455c6c3a3dfcef6c7f2dcab104c813f4b Mon Sep 17 00:00:00 2001 From: Jan Seiffert Date: Fri, 30 Mar 2012 05:08:19 +0000 Subject: bpf jit: Make the filter.c::__load_pointer helper non-static for the jits The function is renamed to make it a little more clear what it does. It is not added to any .h because it is not for general consumption, only for bpf internal use (and so by the jits). Signed-of-by: Jan Seiffert Acked-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/core/filter.c b/net/core/filter.c index cf4989a..6f755cc 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -39,8 +39,11 @@ #include #include -/* No hurry in this branch */ -static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size) +/* No hurry in this branch + * + * Exported for the bpf jit load helper. + */ +void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, unsigned int size) { u8 *ptr = NULL; @@ -59,7 +62,7 @@ static inline void *load_pointer(const struct sk_buff *skb, int k, { if (k >= 0) return skb_header_pointer(skb, k, size, buffer); - return __load_pointer(skb, k, size); + return bpf_internal_load_pointer_neg_helper(skb, k, size); } /** -- cgit v0.10.2 From a998d4342337c82dacdc0897d30a9364de1576a1 Mon Sep 17 00:00:00 2001 From: Jan Seiffert Date: Fri, 30 Mar 2012 05:24:05 +0000 Subject: bpf jit: Let the x86 jit handle negative offsets Now the helper function from filter.c for negative offsets is exported, it can be used it in the jit to handle negative offsets. First modify the asm load helper functions to handle: - know positive offsets - know negative offsets - any offset then the compiler can be modified to explicitly use these helper when appropriate. This fixes the case of a negative X register and allows to lift the restriction that bpf programs with negative offsets can't be jited. Signed-of-by: Jan Seiffert Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S index 6687022..877b9a1 100644 --- a/arch/x86/net/bpf_jit.S +++ b/arch/x86/net/bpf_jit.S @@ -18,17 +18,17 @@ * r9d : hlen = skb->len - skb->data_len */ #define SKBDATA %r8 - -sk_load_word_ind: - .globl sk_load_word_ind - - add %ebx,%esi /* offset += X */ -# test %esi,%esi /* if (offset < 0) goto bpf_error; */ - js bpf_error +#define SKF_MAX_NEG_OFF $(-0x200000) /* SKF_LL_OFF from filter.h */ sk_load_word: .globl sk_load_word + test %esi,%esi + js bpf_slow_path_word_neg + +sk_load_word_positive_offset: + .globl sk_load_word_positive_offset + mov %r9d,%eax # hlen sub %esi,%eax # hlen - offset cmp $3,%eax @@ -37,16 +37,15 @@ sk_load_word: bswap %eax /* ntohl() */ ret - -sk_load_half_ind: - .globl sk_load_half_ind - - add %ebx,%esi /* offset += X */ - js bpf_error - sk_load_half: .globl sk_load_half + test %esi,%esi + js bpf_slow_path_half_neg + +sk_load_half_positive_offset: + .globl sk_load_half_positive_offset + mov %r9d,%eax sub %esi,%eax # hlen - offset cmp $1,%eax @@ -55,14 +54,15 @@ sk_load_half: rol $8,%ax # ntohs() ret -sk_load_byte_ind: - .globl sk_load_byte_ind - add %ebx,%esi /* offset += X */ - js bpf_error - sk_load_byte: .globl sk_load_byte + test %esi,%esi + js bpf_slow_path_byte_neg + +sk_load_byte_positive_offset: + .globl sk_load_byte_positive_offset + cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ jle bpf_slow_path_byte movzbl (SKBDATA,%rsi),%eax @@ -73,25 +73,21 @@ sk_load_byte: * * Implements BPF_S_LDX_B_MSH : ldxb 4*([offset]&0xf) * Must preserve A accumulator (%eax) - * Inputs : %esi is the offset value, already known positive + * Inputs : %esi is the offset value */ -ENTRY(sk_load_byte_msh) - CFI_STARTPROC +sk_load_byte_msh: + .globl sk_load_byte_msh + test %esi,%esi + js bpf_slow_path_byte_msh_neg + +sk_load_byte_msh_positive_offset: + .globl sk_load_byte_msh_positive_offset cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte_msh */ jle bpf_slow_path_byte_msh movzbl (SKBDATA,%rsi),%ebx and $15,%bl shl $2,%bl ret - CFI_ENDPROC -ENDPROC(sk_load_byte_msh) - -bpf_error: -# force a return 0 from jit handler - xor %eax,%eax - mov -8(%rbp),%rbx - leaveq - ret /* rsi contains offset and can be scratched */ #define bpf_slow_path_common(LEN) \ @@ -138,3 +134,67 @@ bpf_slow_path_byte_msh: shl $2,%al xchg %eax,%ebx ret + +#define sk_negative_common(SIZE) \ + push %rdi; /* save skb */ \ + push %r9; \ + push SKBDATA; \ +/* rsi already has offset */ \ + mov $SIZE,%ecx; /* size */ \ + call bpf_internal_load_pointer_neg_helper; \ + test %rax,%rax; \ + pop SKBDATA; \ + pop %r9; \ + pop %rdi; \ + jz bpf_error + + +bpf_slow_path_word_neg: + cmp SKF_MAX_NEG_OFF, %esi /* test range */ + jl bpf_error /* offset lower -> error */ +sk_load_word_negative_offset: + .globl sk_load_word_negative_offset + sk_negative_common(4) + mov (%rax), %eax + bswap %eax + ret + +bpf_slow_path_half_neg: + cmp SKF_MAX_NEG_OFF, %esi + jl bpf_error +sk_load_half_negative_offset: + .globl sk_load_half_negative_offset + sk_negative_common(2) + mov (%rax),%ax + rol $8,%ax + movzwl %ax,%eax + ret + +bpf_slow_path_byte_neg: + cmp SKF_MAX_NEG_OFF, %esi + jl bpf_error +sk_load_byte_negative_offset: + .globl sk_load_byte_negative_offset + sk_negative_common(1) + movzbl (%rax), %eax + ret + +bpf_slow_path_byte_msh_neg: + cmp SKF_MAX_NEG_OFF, %esi + jl bpf_error +sk_load_byte_msh_negative_offset: + .globl sk_load_byte_msh_negative_offset + xchg %eax,%ebx /* dont lose A , X is about to be scratched */ + sk_negative_common(1) + movzbl (%rax),%eax + and $15,%al + shl $2,%al + xchg %eax,%ebx + ret + +bpf_error: +# force a return 0 from jit handler + xor %eax,%eax + mov -8(%rbp),%rbx + leaveq + ret diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 5a5b6e4..0597f95 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -30,7 +30,10 @@ int bpf_jit_enable __read_mostly; * assembly code in arch/x86/net/bpf_jit.S */ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[]; -extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[]; +extern u8 sk_load_word_positive_offset[], sk_load_half_positive_offset[]; +extern u8 sk_load_byte_positive_offset[], sk_load_byte_msh_positive_offset[]; +extern u8 sk_load_word_negative_offset[], sk_load_half_negative_offset[]; +extern u8 sk_load_byte_negative_offset[], sk_load_byte_msh_negative_offset[]; static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) { @@ -117,6 +120,8 @@ static inline void bpf_flush_icache(void *start, void *end) set_fs(old_fs); } +#define CHOOSE_LOAD_FUNC(K, func) \ + ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) void bpf_jit_compile(struct sk_filter *fp) { @@ -473,44 +478,46 @@ void bpf_jit_compile(struct sk_filter *fp) #endif break; case BPF_S_LD_W_ABS: - func = sk_load_word; + func = CHOOSE_LOAD_FUNC(K, sk_load_word); common_load: seen |= SEEN_DATAREF; - if ((int)K < 0) { - /* Abort the JIT because __load_pointer() is needed. */ - goto out; - } t_offset = func - (image + addrs[i]); EMIT1_off32(0xbe, K); /* mov imm32,%esi */ EMIT1_off32(0xe8, t_offset); /* call */ break; case BPF_S_LD_H_ABS: - func = sk_load_half; + func = CHOOSE_LOAD_FUNC(K, sk_load_half); goto common_load; case BPF_S_LD_B_ABS: - func = sk_load_byte; + func = CHOOSE_LOAD_FUNC(K, sk_load_byte); goto common_load; case BPF_S_LDX_B_MSH: - if ((int)K < 0) { - /* Abort the JIT because __load_pointer() is needed. */ - goto out; - } + func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh); seen |= SEEN_DATAREF | SEEN_XREG; - t_offset = sk_load_byte_msh - (image + addrs[i]); + t_offset = func - (image + addrs[i]); EMIT1_off32(0xbe, K); /* mov imm32,%esi */ EMIT1_off32(0xe8, t_offset); /* call sk_load_byte_msh */ break; case BPF_S_LD_W_IND: - func = sk_load_word_ind; + func = sk_load_word; common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG; t_offset = func - (image + addrs[i]); - EMIT1_off32(0xbe, K); /* mov imm32,%esi */ + if (K) { + if (is_imm8(K)) { + EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx), %esi */ + } else { + EMIT2(0x8d, 0xb3); /* lea imm32(%rbx),%esi */ + EMIT(K, 4); + } + } else { + EMIT2(0x89,0xde); /* mov %ebx,%esi */ + } EMIT1_off32(0xe8, t_offset); /* call sk_load_xxx_ind */ break; case BPF_S_LD_H_IND: - func = sk_load_half_ind; + func = sk_load_half; goto common_load_ind; case BPF_S_LD_B_IND: - func = sk_load_byte_ind; + func = sk_load_byte; goto common_load_ind; case BPF_S_JMP_JA: t_offset = addrs[i + K] - addrs[i]; -- cgit v0.10.2 From aacc1bea190d731755a65cb8ec31dd756f4e263e Mon Sep 17 00:00:00 2001 From: "Multanen, Eric W" Date: Wed, 28 Mar 2012 07:49:09 +0000 Subject: ixgbe: driver fix for link flap Fix up code so that changes in DCB settings are detected only when ixgbe_dcbnl_set_all is called. Previously, a series of 'change' commands followed by a call to ixgbe_dcbnl_set_all() would always be handled as a HW change - even if the net change was zero. This patch checks for this case of no actual change and skips going through the HW set process. Without this fix, the link could reset and result in a link flap. The core change in this patch is to check for changes in the ixgbe_copy_dcb_cfg() routine - and return a bitmask of detected changes. The other places where changes were detected previously can be removed. Signed-off-by: Eric Multanen Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c index dde65f9..652e4b0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c @@ -44,62 +44,94 @@ #define DCB_NO_HW_CHG 1 /* DCB configuration did not change */ #define DCB_HW_CHG 2 /* DCB configuration changed, no reset */ -int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, - struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) +int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *scfg, + struct ixgbe_dcb_config *dcfg, int tc_max) { - struct tc_configuration *src_tc_cfg = NULL; - struct tc_configuration *dst_tc_cfg = NULL; - int i; + struct tc_configuration *src = NULL; + struct tc_configuration *dst = NULL; + int i, j; + int tx = DCB_TX_CONFIG; + int rx = DCB_RX_CONFIG; + int changes = 0; - if (!src_dcb_cfg || !dst_dcb_cfg) - return -EINVAL; + if (!scfg || !dcfg) + return changes; for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) { - src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; - dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; + src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0]; + dst = &dcfg->tc_config[i - DCB_PG_ATTR_TC_0]; - dst_tc_cfg->path[DCB_TX_CONFIG].prio_type = - src_tc_cfg->path[DCB_TX_CONFIG].prio_type; + if (dst->path[tx].prio_type != src->path[tx].prio_type) { + dst->path[tx].prio_type = src->path[tx].prio_type; + changes |= BIT_PG_TX; + } - dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id = - src_tc_cfg->path[DCB_TX_CONFIG].bwg_id; + if (dst->path[tx].bwg_id != src->path[tx].bwg_id) { + dst->path[tx].bwg_id = src->path[tx].bwg_id; + changes |= BIT_PG_TX; + } - dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent = - src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent; + if (dst->path[tx].bwg_percent != src->path[tx].bwg_percent) { + dst->path[tx].bwg_percent = src->path[tx].bwg_percent; + changes |= BIT_PG_TX; + } - dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap = - src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap; + if (dst->path[tx].up_to_tc_bitmap != + src->path[tx].up_to_tc_bitmap) { + dst->path[tx].up_to_tc_bitmap = + src->path[tx].up_to_tc_bitmap; + changes |= (BIT_PG_TX | BIT_PFC | BIT_APP_UPCHG); + } - dst_tc_cfg->path[DCB_RX_CONFIG].prio_type = - src_tc_cfg->path[DCB_RX_CONFIG].prio_type; + if (dst->path[rx].prio_type != src->path[rx].prio_type) { + dst->path[rx].prio_type = src->path[rx].prio_type; + changes |= BIT_PG_RX; + } - dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id = - src_tc_cfg->path[DCB_RX_CONFIG].bwg_id; + if (dst->path[rx].bwg_id != src->path[rx].bwg_id) { + dst->path[rx].bwg_id = src->path[rx].bwg_id; + changes |= BIT_PG_RX; + } - dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent = - src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent; + if (dst->path[rx].bwg_percent != src->path[rx].bwg_percent) { + dst->path[rx].bwg_percent = src->path[rx].bwg_percent; + changes |= BIT_PG_RX; + } - dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap = - src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap; + if (dst->path[rx].up_to_tc_bitmap != + src->path[rx].up_to_tc_bitmap) { + dst->path[rx].up_to_tc_bitmap = + src->path[rx].up_to_tc_bitmap; + changes |= (BIT_PG_RX | BIT_PFC | BIT_APP_UPCHG); + } } for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) { - dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG] - [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage - [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; - dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG] - [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage - [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; + j = i - DCB_PG_ATTR_BW_ID_0; + if (dcfg->bw_percentage[tx][j] != scfg->bw_percentage[tx][j]) { + dcfg->bw_percentage[tx][j] = scfg->bw_percentage[tx][j]; + changes |= BIT_PG_TX; + } + if (dcfg->bw_percentage[rx][j] != scfg->bw_percentage[rx][j]) { + dcfg->bw_percentage[rx][j] = scfg->bw_percentage[rx][j]; + changes |= BIT_PG_RX; + } } for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) { - dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc = - src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc; + j = i - DCB_PFC_UP_ATTR_0; + if (dcfg->tc_config[j].dcb_pfc != scfg->tc_config[j].dcb_pfc) { + dcfg->tc_config[j].dcb_pfc = scfg->tc_config[j].dcb_pfc; + changes |= BIT_PFC; + } } - dst_dcb_cfg->pfc_mode_enable = src_dcb_cfg->pfc_mode_enable; + if (dcfg->pfc_mode_enable != scfg->pfc_mode_enable) { + dcfg->pfc_mode_enable = scfg->pfc_mode_enable; + changes |= BIT_PFC; + } - return 0; + return changes; } static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) @@ -179,20 +211,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, if (up_map != DCB_ATTR_VALUE_UNDEFINED) adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap = up_map; - - if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type != - adapter->dcb_cfg.tc_config[tc].path[0].prio_type) || - (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id != - adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) || - (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != - adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || - (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap != - adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) - adapter->dcb_set_bitmap |= BIT_PG_TX; - - if (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap != - adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap) - adapter->dcb_set_bitmap |= BIT_PFC | BIT_APP_UPCHG; } static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, @@ -201,10 +219,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, struct ixgbe_adapter *adapter = netdev_priv(netdev); adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; - - if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != - adapter->dcb_cfg.bw_percentage[0][bwg_id]) - adapter->dcb_set_bitmap |= BIT_PG_TX; } static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, @@ -223,20 +237,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, if (up_map != DCB_ATTR_VALUE_UNDEFINED) adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap = up_map; - - if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type != - adapter->dcb_cfg.tc_config[tc].path[1].prio_type) || - (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id != - adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) || - (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != - adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || - (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap != - adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) - adapter->dcb_set_bitmap |= BIT_PG_RX; - - if (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap != - adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap) - adapter->dcb_set_bitmap |= BIT_PFC; } static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, @@ -245,10 +245,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, struct ixgbe_adapter *adapter = netdev_priv(netdev); adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; - - if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != - adapter->dcb_cfg.bw_percentage[1][bwg_id]) - adapter->dcb_set_bitmap |= BIT_PG_RX; } static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, @@ -298,10 +294,8 @@ static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority, adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting; if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc != - adapter->dcb_cfg.tc_config[priority].dcb_pfc) { - adapter->dcb_set_bitmap |= BIT_PFC; + adapter->dcb_cfg.tc_config[priority].dcb_pfc) adapter->temp_dcb_cfg.pfc_mode_enable = true; - } } static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority, @@ -336,7 +330,8 @@ static void ixgbe_dcbnl_devreset(struct net_device *dev) static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - int ret, i; + int ret = DCB_NO_HW_CHG; + int i; #ifdef IXGBE_FCOE struct dcb_app app = { .selector = DCB_APP_IDTYPE_ETHTYPE, @@ -355,12 +350,13 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) /* Fail command if not in CEE mode */ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) - return 1; + return ret; - ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, - MAX_TRAFFIC_CLASS); - if (ret) - return DCB_NO_HW_CHG; + adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, + &adapter->dcb_cfg, + MAX_TRAFFIC_CLASS); + if (!adapter->dcb_set_bitmap) + return ret; if (adapter->dcb_cfg.pfc_mode_enable) { switch (adapter->hw.mac.type) { @@ -420,6 +416,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) netdev_set_prio_tc_map(netdev, i, prio_tc[i]); + + ret = DCB_HW_CHG_RST; } if (adapter->dcb_set_bitmap & BIT_PFC) { @@ -430,7 +428,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) DCB_TX_CONFIG, prio_tc); ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en); ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc); - ret = DCB_HW_CHG; + if (ret != DCB_HW_CHG_RST) + ret = DCB_HW_CHG; } if (adapter->dcb_cfg.pfc_mode_enable) @@ -531,9 +530,6 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) struct ixgbe_adapter *adapter = netdev_priv(netdev); adapter->temp_dcb_cfg.pfc_mode_enable = state; - if (adapter->temp_dcb_cfg.pfc_mode_enable != - adapter->dcb_cfg.pfc_mode_enable) - adapter->dcb_set_bitmap |= BIT_PFC; } /** -- cgit v0.10.2 From bb9e44d0d0f45da356c39e485edacff6e14ba961 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 21 Mar 2012 00:39:12 +0000 Subject: e1000e: prevent oops when adapter is being closed and reset simultaneously When the adapter is closed while it is simultaneously going through a reset, it can cause a null-pointer dereference when the two different code paths simultaneously cleanup up the Tx/Rx resources. Signed-off-by: Bruce Allan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index 86cdd47..b83897f 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -161,6 +161,12 @@ struct e1000_info; /* Time to wait before putting the device into D3 if there's no link (in ms). */ #define LINK_TIMEOUT 100 +/* + * Count for polling __E1000_RESET condition every 10-20msec. + * Experimentation has shown the reset can take approximately 210msec. + */ +#define E1000_CHECK_RESET_COUNT 25 + #define DEFAULT_RDTR 0 #define DEFAULT_RADV 8 #define BURST_RDTR 0x20 diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 2c38a65..6878601 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3968,6 +3968,10 @@ static int e1000_close(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct pci_dev *pdev = adapter->pdev; + int count = E1000_CHECK_RESET_COUNT; + + while (test_bit(__E1000_RESETTING, &adapter->state) && count--) + usleep_range(10000, 20000); WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); @@ -5472,6 +5476,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, netif_device_detach(netdev); if (netif_running(netdev)) { + int count = E1000_CHECK_RESET_COUNT; + + while (test_bit(__E1000_RESETTING, &adapter->state) && count--) + usleep_range(10000, 20000); + WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); e1000e_down(adapter); e1000_free_irq(adapter); -- cgit v0.10.2 From bf03085f85112eac2d19036ea3003071220285bb Mon Sep 17 00:00:00 2001 From: Matthew Vick Date: Fri, 16 Mar 2012 09:03:00 +0000 Subject: e1000e: Guarantee descriptor writeback flush success. In rare circumstances, a descriptor writeback flush may not work if it arrives on a specific clock cycle as a writeback request is going out. Signed-off-by: Matthew Vick Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 6878601..19ab215 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1059,6 +1059,13 @@ static void e1000_print_hw_hang(struct work_struct *work) ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); /* execute the writes immediately */ e1e_flush(); + /* + * Due to rare timing issues, write to TIDV again to ensure + * the write is successful + */ + ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); + /* execute the writes immediately */ + e1e_flush(); adapter->tx_hang_recheck = true; return; } @@ -3616,6 +3623,16 @@ static void e1000e_flush_descriptors(struct e1000_adapter *adapter) /* execute the writes immediately */ e1e_flush(); + + /* + * due to rare timing issues, write to TIDV/RDTR again to ensure the + * write is successful + */ + ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); + ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD); + + /* execute the writes immediately */ + e1e_flush(); } static void e1000e_update_stats(struct e1000_adapter *adapter); -- cgit v0.10.2 From b3300146aa8efc5d3937fd33f3cfdc580a3843bc Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 2 Apr 2012 00:02:09 +0000 Subject: phy:icplus:fix Auto Power Saving in ip101a_config_init. This patch fixes Auto Power Saving configuration in ip101a_config_init which was broken as there is no phy register write followed after setting IP101A_APS_ON flag. This patch also fixes the return value of ip101a_config_init. Without this patch ip101a_config_init returns 2 which is not an error accroding to IS_ERR and the mac driver will continue accessing 2 as valid pointer to phy_dev resulting in memory fault. Signed-off-by: Srinivas Kandagatla Signed-off-by: David S. Miller diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index 0856e1b..f08c85a 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c @@ -162,7 +162,8 @@ static int ip101a_g_config_init(struct phy_device *phydev) /* Enable Auto Power Saving mode */ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); c |= IP101A_G_APS_ON; - return c; + + return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); } static int ip175c_read_status(struct phy_device *phydev) -- cgit v0.10.2 From f2ed5ee1b050495be49e5a0d5df152663558ef08 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Tue, 3 Apr 2012 00:07:11 +0000 Subject: bnx2x: correction to firmware interface Commit 621b4d6 updated the bnx2x driver to a new FW version, but lacked a commit to a header file with changes to the firmware's interface. The missing interface change causes iscsi and fcoe to misbehave with the updated firmware. Signed-off-by: Yuval Mintz Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein CC: Michael Chan CC: Bhanu Prakash Gollapudi Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h index cd6dfa9..b9b2633 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h @@ -25,31 +25,31 @@ (IRO[149].base + ((funcId) * IRO[149].m1)) #define CSTORM_IGU_MODE_OFFSET (IRO[157].base) #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \ - (IRO[315].base + ((pfId) * IRO[315].m1)) -#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \ (IRO[316].base + ((pfId) * IRO[316].m1)) +#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \ + (IRO[317].base + ((pfId) * IRO[317].m1)) #define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \ - (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2)) + (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2)) #define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \ - (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2)) + (IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2)) #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \ - (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2)) + (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2)) #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \ - (IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2)) + (IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2)) #define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \ - (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * IRO[307].m2)) + (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2)) #define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \ - (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2)) + (IRO[314].base + ((pfId) * IRO[314].m1) + ((iscsiEqId) * IRO[314].m2)) #define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \ - (IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2)) + (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2)) #define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \ - (IRO[314].base + ((pfId) * IRO[314].m1)) + (IRO[315].base + ((pfId) * IRO[315].m1)) #define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ - (IRO[306].base + ((pfId) * IRO[306].m1)) + (IRO[307].base + ((pfId) * IRO[307].m1)) #define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ - (IRO[305].base + ((pfId) * IRO[305].m1)) + (IRO[306].base + ((pfId) * IRO[306].m1)) #define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ - (IRO[304].base + ((pfId) * IRO[304].m1)) + (IRO[305].base + ((pfId) * IRO[305].m1)) #define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ (IRO[151].base + ((funcId) * IRO[151].m1)) #define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \ @@ -96,37 +96,37 @@ #define TSTORM_FUNC_EN_OFFSET(funcId) \ (IRO[103].base + ((funcId) * IRO[103].m1)) #define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \ - (IRO[271].base + ((pfId) * IRO[271].m1)) -#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \ (IRO[272].base + ((pfId) * IRO[272].m1)) -#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \ +#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \ (IRO[273].base + ((pfId) * IRO[273].m1)) -#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \ +#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \ (IRO[274].base + ((pfId) * IRO[274].m1)) +#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \ + (IRO[275].base + ((pfId) * IRO[275].m1)) #define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ - (IRO[270].base + ((pfId) * IRO[270].m1)) + (IRO[271].base + ((pfId) * IRO[271].m1)) #define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ - (IRO[269].base + ((pfId) * IRO[269].m1)) + (IRO[270].base + ((pfId) * IRO[270].m1)) #define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ - (IRO[268].base + ((pfId) * IRO[268].m1)) + (IRO[269].base + ((pfId) * IRO[269].m1)) #define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \ - (IRO[267].base + ((pfId) * IRO[267].m1)) + (IRO[268].base + ((pfId) * IRO[268].m1)) #define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \ - (IRO[276].base + ((pfId) * IRO[276].m1)) + (IRO[277].base + ((pfId) * IRO[277].m1)) #define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \ - (IRO[263].base + ((pfId) * IRO[263].m1)) -#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \ (IRO[264].base + ((pfId) * IRO[264].m1)) -#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \ +#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \ (IRO[265].base + ((pfId) * IRO[265].m1)) -#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \ +#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \ (IRO[266].base + ((pfId) * IRO[266].m1)) +#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \ + (IRO[267].base + ((pfId) * IRO[267].m1)) #define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \ (IRO[202].base + ((pfId) * IRO[202].m1)) #define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ (IRO[105].base + ((funcId) * IRO[105].m1)) #define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \ - (IRO[216].base + ((pfId) * IRO[216].m1)) + (IRO[217].base + ((pfId) * IRO[217].m1)) #define TSTORM_VF_TO_PF_OFFSET(funcId) \ (IRO[104].base + ((funcId) * IRO[104].m1)) #define USTORM_AGG_DATA_OFFSET (IRO[206].base) @@ -140,29 +140,29 @@ #define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \ (IRO[183].base + ((portId) * IRO[183].m1)) #define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \ - (IRO[317].base + ((pfId) * IRO[317].m1)) + (IRO[318].base + ((pfId) * IRO[318].m1)) #define USTORM_FUNC_EN_OFFSET(funcId) \ (IRO[178].base + ((funcId) * IRO[178].m1)) #define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \ - (IRO[281].base + ((pfId) * IRO[281].m1)) -#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \ (IRO[282].base + ((pfId) * IRO[282].m1)) +#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \ + (IRO[283].base + ((pfId) * IRO[283].m1)) #define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \ - (IRO[286].base + ((pfId) * IRO[286].m1)) + (IRO[287].base + ((pfId) * IRO[287].m1)) #define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \ - (IRO[283].base + ((pfId) * IRO[283].m1)) + (IRO[284].base + ((pfId) * IRO[284].m1)) #define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ - (IRO[279].base + ((pfId) * IRO[279].m1)) + (IRO[280].base + ((pfId) * IRO[280].m1)) #define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ - (IRO[278].base + ((pfId) * IRO[278].m1)) + (IRO[279].base + ((pfId) * IRO[279].m1)) #define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ - (IRO[277].base + ((pfId) * IRO[277].m1)) + (IRO[278].base + ((pfId) * IRO[278].m1)) #define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \ - (IRO[280].base + ((pfId) * IRO[280].m1)) + (IRO[281].base + ((pfId) * IRO[281].m1)) #define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \ - (IRO[284].base + ((pfId) * IRO[284].m1)) -#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \ (IRO[285].base + ((pfId) * IRO[285].m1)) +#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \ + (IRO[286].base + ((pfId) * IRO[286].m1)) #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \ (IRO[182].base + ((pfId) * IRO[182].m1)) #define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ @@ -188,39 +188,39 @@ #define XSTORM_FUNC_EN_OFFSET(funcId) \ (IRO[47].base + ((funcId) * IRO[47].m1)) #define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \ - (IRO[294].base + ((pfId) * IRO[294].m1)) + (IRO[295].base + ((pfId) * IRO[295].m1)) #define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \ - (IRO[297].base + ((pfId) * IRO[297].m1)) -#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \ (IRO[298].base + ((pfId) * IRO[298].m1)) -#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \ +#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \ (IRO[299].base + ((pfId) * IRO[299].m1)) -#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \ +#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \ (IRO[300].base + ((pfId) * IRO[300].m1)) -#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \ +#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \ (IRO[301].base + ((pfId) * IRO[301].m1)) -#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \ +#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \ (IRO[302].base + ((pfId) * IRO[302].m1)) -#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \ +#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \ (IRO[303].base + ((pfId) * IRO[303].m1)) +#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \ + (IRO[304].base + ((pfId) * IRO[304].m1)) #define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ - (IRO[293].base + ((pfId) * IRO[293].m1)) + (IRO[294].base + ((pfId) * IRO[294].m1)) #define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ - (IRO[292].base + ((pfId) * IRO[292].m1)) + (IRO[293].base + ((pfId) * IRO[293].m1)) #define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ - (IRO[291].base + ((pfId) * IRO[291].m1)) + (IRO[292].base + ((pfId) * IRO[292].m1)) #define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \ - (IRO[296].base + ((pfId) * IRO[296].m1)) + (IRO[297].base + ((pfId) * IRO[297].m1)) #define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \ - (IRO[295].base + ((pfId) * IRO[295].m1)) + (IRO[296].base + ((pfId) * IRO[296].m1)) #define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \ - (IRO[290].base + ((pfId) * IRO[290].m1)) + (IRO[291].base + ((pfId) * IRO[291].m1)) #define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \ - (IRO[289].base + ((pfId) * IRO[289].m1)) + (IRO[290].base + ((pfId) * IRO[290].m1)) #define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \ - (IRO[288].base + ((pfId) * IRO[288].m1)) + (IRO[289].base + ((pfId) * IRO[289].m1)) #define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \ - (IRO[287].base + ((pfId) * IRO[287].m1)) + (IRO[288].base + ((pfId) * IRO[288].m1)) #define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \ (IRO[44].base + ((pfId) * IRO[44].m1)) #define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ -- cgit v0.10.2 From 1023807458b6365e28c66095648e1b66e04a4259 Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Wed, 28 Mar 2012 18:07:08 +0100 Subject: Remove unnecessary check for NULL in password parser The password parser has an unnecessary check for a NULL value which triggers warnings in source checking tools. The code contains artifacts from the old parsing code which are no longer required. Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Reported-by: Dan Carpenter Signed-off-by: Steve French diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 302a15c..0511fdb 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1565,8 +1565,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, /* Obtain the value string */ value = strchr(data, '='); - if (value != NULL) - *value++ = '\0'; + value++; /* Set tmp_end to end of the string */ tmp_end = (char *) value + strlen(value); -- cgit v0.10.2 From cff4c16296754888b6fd8c886bc860a888e20257 Mon Sep 17 00:00:00 2001 From: Artem Savkov Date: Tue, 3 Apr 2012 10:29:11 +0000 Subject: r8169: enable napi on resume. NAPI is disabled during suspend and needs to be enabled on resume. Without this the driver locks up during resume in rtl_reset_work() trying to disable NAPI again. Signed-off-by: Artem Savkov Acked-by: Francois Romieu Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 7b23554..f545093 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -5810,7 +5810,10 @@ static void __rtl8169_resume(struct net_device *dev) rtl_pll_power_up(tp); + rtl_lock_work(tp); + napi_enable(&tp->napi); set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); + rtl_unlock_work(tp); rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } -- cgit v0.10.2 From ca53e4405347a1e19eaf59c757ceaaaa1a784758 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 3 Apr 2012 12:32:15 +0200 Subject: netfilter: xt_CT: allocation has to be GFP_ATOMIC under rcu_read_lock section Reported-by: Tetsuo Handa Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 138b75e..4babb27 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -261,7 +261,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) goto err4; } timeout_ext = nf_ct_timeout_ext_add(ct, timeout, - GFP_KERNEL); + GFP_ATOMIC); if (timeout_ext == NULL) { ret = -ENOMEM; goto err4; -- cgit v0.10.2 From ee14186f8d2338227888f3c00a06caf31f94de38 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 3 Apr 2012 14:50:07 +0200 Subject: netfilter: xt_CT: fix missing put timeout object in error path The error path misses putting the timeout object. This patch adds new function xt_ct_tg_timeout_put() to put the timeout object. Reported-by: Tetsuo Handa Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 4babb27..59530e9 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -150,6 +150,17 @@ err1: return ret; } +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT +static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) +{ + typeof(nf_ct_timeout_put_hook) timeout_put; + + timeout_put = rcu_dereference(nf_ct_timeout_put_hook); + if (timeout_put) + timeout_put(timeout); +} +#endif + static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) { struct xt_ct_target_info_v1 *info = par->targinfo; @@ -158,7 +169,9 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) struct nf_conn *ct; int ret = 0; u8 proto; - +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT + struct ctnl_timeout *timeout; +#endif if (info->flags & ~XT_CT_NOTRACK) return -EINVAL; @@ -216,7 +229,6 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) #ifdef CONFIG_NF_CONNTRACK_TIMEOUT if (info->timeout) { typeof(nf_ct_timeout_find_get_hook) timeout_find_get; - struct ctnl_timeout *timeout; struct nf_conn_timeout *timeout_ext; rcu_read_lock(); @@ -245,7 +257,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) pr_info("Timeout policy `%s' can only be " "used by L3 protocol number %d\n", info->timeout, timeout->l3num); - goto err4; + goto err5; } /* Make sure the timeout policy matches any existing * protocol tracker, otherwise default to generic. @@ -258,13 +270,13 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) "used by L4 protocol number %d\n", info->timeout, timeout->l4proto->l4proto); - goto err4; + goto err5; } timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); if (timeout_ext == NULL) { ret = -ENOMEM; - goto err4; + goto err5; } } else { ret = -ENOENT; @@ -282,6 +294,8 @@ out: return 0; #ifdef CONFIG_NF_CONNTRACK_TIMEOUT +err5: + __xt_ct_tg_timeout_put(timeout); err4: rcu_read_unlock(); #endif -- cgit v0.10.2 From d96fc659aeb27686cef42d305cfd0c9702f8841c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 3 Apr 2012 16:45:54 +0200 Subject: netfilter: nf_conntrack: fix count leak in error path of __nf_conntrack_alloc We have to decrement the conntrack counter if we fail to access the zone extension. Reported-by: Tetsuo Handa Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index cbdb754..3cc4487 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -735,6 +735,7 @@ __nf_conntrack_alloc(struct net *net, u16 zone, #ifdef CONFIG_NF_CONNTRACK_ZONES out_free: + atomic_dec(&net->ct.count); kmem_cache_free(net->ct.nf_conntrack_cachep, ct); return ERR_PTR(-ENOMEM); #endif -- cgit v0.10.2 From e16de9137c8beab02d78fb4fa82bb96e9f3d0ac3 Mon Sep 17 00:00:00 2001 From: Graeme Smecher Date: Tue, 3 Apr 2012 19:42:21 -0400 Subject: hwmon: (ad7314) Adds missing spi_dev initialization This driver was recently moved from IIO (where it worked) to hwmon (where it doesn't.) This breakage occured because the hwmon version neglected to correctly initialize a reference to spi_dev in its drvdata. The result is a segfault every time the temperature is queried. Signed-off-by: Graeme Smecher Cc: stable@vger.kernel.org # 3.2+ Signed-off-by: Guenter Roeck diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index 0e0cfcc..ce43642 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c @@ -128,6 +128,7 @@ static int __devinit ad7314_probe(struct spi_device *spi_dev) ret = PTR_ERR(chip->hwmon_dev); goto error_remove_group; } + chip->spi_dev = spi_dev; return 0; error_remove_group: -- cgit v0.10.2 From e4b41fb9dafb9af4fecb602bf73d858ab651eeed Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Wed, 4 Apr 2012 01:58:56 +0100 Subject: Fix UNC parsing on mount The code cleanup of cifs_parse_mount_options resulted in a new bug being introduced in the parsing of the UNC. This results in vol->UNC being modified before vol->UNC was allocated. Reported-by: Steve French Signed-off-by: Sachin Prabhu Signed-off-by: Steve French diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 0511fdb..d81e933 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1648,6 +1648,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, goto cifs_parse_mount_err; } + vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); + if (vol->UNC == NULL) { + printk(KERN_WARNING "CIFS: no memory for UNC\n"); + goto cifs_parse_mount_err; + } + strcpy(vol->UNC, string); + if (strncmp(string, "//", 2) == 0) { vol->UNC[0] = '\\'; vol->UNC[1] = '\\'; @@ -1657,13 +1664,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, goto cifs_parse_mount_err; } - vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); - if (vol->UNC == NULL) { - printk(KERN_WARNING "CIFS: no memory " - "for UNC\n"); - goto cifs_parse_mount_err; - } - strcpy(vol->UNC, string); break; case Opt_domain: string = match_strdup(args); -- cgit v0.10.2 From ca6f327dfdc6b3b90aa0c5247182ae023dce6450 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Wed, 4 Apr 2012 09:35:06 +0200 Subject: serial/sunzilog: fix keyboard on SUN SPARCstation The keyboard on my SUN SPARCstation 5 no longer worked. The culprint was: d4e33fac2408d37f7b52e80ca2a89f9fb482914f ("serial: Kill off NO_IRQ") Fix up logic for no irq / irq so the keyboard works again. Signed-off-by: Sam Ravnborg Cc: Alan Cox Cc: Greg Kroah-Hartman Signed-off-by: David S. Miller diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index b3b70b0..babd947 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -1581,7 +1581,7 @@ static int __init sunzilog_init(void) if (err) goto out_unregister_uart; - if (!zilog_irq) { + if (zilog_irq) { struct uart_sunzilog_port *up = sunzilog_irq_chain; err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, "zs", sunzilog_irq_chain); @@ -1622,7 +1622,7 @@ static void __exit sunzilog_exit(void) { platform_driver_unregister(&zs_driver); - if (!zilog_irq) { + if (zilog_irq) { struct uart_sunzilog_port *up = sunzilog_irq_chain; /* Disable Interrupts */ -- cgit v0.10.2 From ec3e82d6dc46cac7309b01ff9761f469b0263019 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 4 Apr 2012 14:21:02 +0200 Subject: MCE, AMD: Drop too granulary family model checks MCA details seldom change inbetween the models of a family so don't be too conservative and enable decoding on everything starting from K8 onwards. Minor adjustments can come in later but most importantly, we have some decoding infrastructure in place for upcoming models by default. Signed-off-by: Borislav Petkov diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 36e1486..d0c372e 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c @@ -754,9 +754,7 @@ static int __init mce_amd_init(void) if (c->x86_vendor != X86_VENDOR_AMD) return 0; - if ((c->x86 < 0xf || c->x86 > 0x12) && - (c->x86 != 0x14 || c->x86_model > 0xf) && - (c->x86 != 0x15 || c->x86_model > 0xf)) + if (c->x86 < 0xf || c->x86 > 0x15) return 0; fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); @@ -797,7 +795,7 @@ static int __init mce_amd_init(void) break; default: - printk(KERN_WARNING "Huh? What family is that: %d?!\n", c->x86); + printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86); kfree(fam_ops); return -EINVAL; } -- cgit v0.10.2 From 7a82ebd9ee78f8ba3a2ba66e003bfa57954a1a04 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 4 Apr 2012 08:25:25 -0600 Subject: ARM: OMAP44xx: clockdomain data: correct the emu_sys_clkdm CLKTRCTRL data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the 4430 ES2.0 TRM vX Table 3-744 "CM_EMU_CLKSTCTRL", the emu_sys clockdomain data in mainline is incorrect. The emu_sys clockdomain does not support the DISABLE_AUTO state, and instead it supports the FORCE_WAKEUP state. Signed-off-by: Paul Walmsley Cc: Benoît Cousson Cc: Kevin Hilman Cc: Santosh Shilimkar Cc: Ming Lei Cc: Will Deacon diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index 9299ac2..bd7ed13 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -390,7 +390,7 @@ static struct clockdomain emu_sys_44xx_clkdm = { .prcm_partition = OMAP4430_PRM_PARTITION, .cm_inst = OMAP4430_PRM_EMU_CM_INST, .clkdm_offs = OMAP4430_PRM_EMU_CM_EMU_CDOFFS, - .flags = CLKDM_CAN_HWSUP, + .flags = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_FORCE_WAKEUP, }; static struct clockdomain l3_dma_44xx_clkdm = { -- cgit v0.10.2 From 26c547fd130aae7480523a3af3f1df2ef1144743 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Fri, 16 Mar 2012 14:49:54 +0200 Subject: ARM: OMAP3xxx: HSMMC: avoid erratum workaround when transceiver is attached If transceiver is attached to a MMC host of ES2.1 OMAP35xx, it seems 2.1.1.128 erratum doesn't apply and there is no data corruption, probably because of different signal timing. The workaround for this erratum disables multiblock reads, which causes dramatic loss of performance (over 75% slower), so avoid it when transceiver is present. Cc: Paul Walmsley Signed-off-by: Grazvydas Ignotas [paul@pwsan.com: edited commit message slightly] Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 100db62..b0268ea 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -506,6 +506,13 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, if (oh->dev_attr != NULL) { mmc_dev_attr = oh->dev_attr; mmc_data->controller_flags = mmc_dev_attr->flags; + /* + * erratum 2.1.1.128 doesn't apply if board has + * a transceiver is attached + */ + if (hsmmcinfo->transceiver) + mmc_data->controller_flags &= + ~OMAP_HSMMC_BROKEN_MULTIBLOCK_READ; } pdev = platform_device_alloc(name, ctrl_nr - 1); -- cgit v0.10.2 From ac387330a67635b4e4b946416e792bc9dd4b8f05 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Mon, 26 Mar 2012 00:08:07 +0300 Subject: ARM: OMAP3xxx: clock data: fix DPLL4 CLKSEL masks Commit 2a9f5a4d455 "OMAP3 clock: remove unnecessary duplicate of dpll4_m2_ck, added for 36xx" consolidated dpll4 clock structures between 34xx and 36xx, but left 34xx CLKSEL masks for most dpll4 related clocks, which causes clock code to not behave correctly when booting on DM3730 with higher (36xx only) divisors set: [ 0.000000] WARNING: at arch/arm/mach-omap2/clkt_clksel.c:375 omap2_init_clksel_parent+0x104/0x114() [ 0.000000] clock: dpll4_m3_ck: init parent: could not find regval 0 [ 0.000000] WARNING: at arch/arm/mach-omap2/clkt_clksel.c:194 omap2_clksel_recalc+0xd4/0xe4() [ 0.000000] clock: Could not find fieldval 0 for clock dpll4_m3_ck parent dpll4_ck Fix this by switching to 36xx masks, as valid divisors will be limited by clksel_rate lists. Cc: Paul Walmsley Signed-off-by: Grazvydas Ignotas Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 480fb8f..19c1dc8 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -747,7 +747,7 @@ static struct clk dpll4_m3_ck = { .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_TV_MASK, + .clksel_mask = OMAP3630_CLKSEL_TV_MASK, .clksel = dpll4_clksel, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, @@ -832,7 +832,7 @@ static struct clk dpll4_m4_ck = { .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK, + .clksel_mask = OMAP3630_CLKSEL_DSS1_MASK, .clksel = dpll4_clksel, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, @@ -859,7 +859,7 @@ static struct clk dpll4_m5_ck = { .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), - .clksel_mask = OMAP3430_CLKSEL_CAM_MASK, + .clksel_mask = OMAP3630_CLKSEL_CAM_MASK, .clksel = dpll4_clksel, .clkdm_name = "dpll4_clkdm", .set_rate = &omap2_clksel_set_rate, @@ -886,7 +886,7 @@ static struct clk dpll4_m6_ck = { .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_DIV_DPLL4_MASK, + .clksel_mask = OMAP3630_DIV_DPLL4_MASK, .clksel = dpll4_clksel, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, -- cgit v0.10.2 From a052d2c31b7b87e9b4bdee634af666b5e830e56f Mon Sep 17 00:00:00 2001 From: "Shimoda, Yoshihiro" Date: Wed, 4 Apr 2012 11:56:07 +0900 Subject: sh: fix clock-sh7757 for the latest sh_mobile_sdhi driver The commit 996bc8aebd2cd5b6d4c5d85085f171fa2447f364 (mmc: sh_mobile_sdhi: do not manage PM clocks manually) modified the sh_mobile_sdhi driver to remove the clk_enable/clk_disable. So, we need to change the "CLKDEV_CON_ID" to "CLKDEV_DEV_ID". If we don't change this, we will see the following error from the driver: sh_mobile_sdhi sh_mobile_sdhi.0: timeout waiting for hardware interrupt (CMD52) Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index 5853989..04ab5ae 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c @@ -113,7 +113,7 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), /* MSTP32 clocks */ - CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]), + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP004]), CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]), CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]), CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]), -- cgit v0.10.2 From 503d0ea24d1d3dd3db95e5e0edd693da7a2a23eb Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 4 Apr 2012 09:11:48 -0600 Subject: ARM: OMAP4: hwmod data: Add aliases for McBSP fclk clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLKS signal for McBSP ports can be selected from internal (PRCM) or external (ABE_CLKS pin) source. To be able to use existing code we need to create clock aliases consistent among OMAP2/3/4. Based on a patch from Péter Ujfalusi ; the patch description above is his. Signed-off-by: Paul Walmsley Cc: Péter Ujfalusi Cc: Tony Lindgren Acked-by: Peter Ujfalusi diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 08daa5e..cc9bd10 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2996,6 +2996,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = { &omap44xx_l4_abe__mcbsp1_dma, }; +static struct omap_hwmod_opt_clk mcbsp1_opt_clks[] = { + { .role = "pad_fck", .clk = "pad_clks_ck" }, + { .role = "prcm_clk", .clk = "mcbsp1_sync_mux_ck" }, +}; + static struct omap_hwmod omap44xx_mcbsp1_hwmod = { .name = "mcbsp1", .class = &omap44xx_mcbsp_hwmod_class, @@ -3012,6 +3017,8 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = { }, .slaves = omap44xx_mcbsp1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp1_slaves), + .opt_clks = mcbsp1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp1_opt_clks), }; /* mcbsp2 */ @@ -3071,6 +3078,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = { &omap44xx_l4_abe__mcbsp2_dma, }; +static struct omap_hwmod_opt_clk mcbsp2_opt_clks[] = { + { .role = "pad_fck", .clk = "pad_clks_ck" }, + { .role = "prcm_clk", .clk = "mcbsp2_sync_mux_ck" }, +}; + static struct omap_hwmod omap44xx_mcbsp2_hwmod = { .name = "mcbsp2", .class = &omap44xx_mcbsp_hwmod_class, @@ -3087,6 +3099,8 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = { }, .slaves = omap44xx_mcbsp2_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp2_slaves), + .opt_clks = mcbsp2_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp2_opt_clks), }; /* mcbsp3 */ @@ -3146,6 +3160,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = { &omap44xx_l4_abe__mcbsp3_dma, }; +static struct omap_hwmod_opt_clk mcbsp3_opt_clks[] = { + { .role = "pad_fck", .clk = "pad_clks_ck" }, + { .role = "prcm_clk", .clk = "mcbsp3_sync_mux_ck" }, +}; + static struct omap_hwmod omap44xx_mcbsp3_hwmod = { .name = "mcbsp3", .class = &omap44xx_mcbsp_hwmod_class, @@ -3162,6 +3181,8 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = { }, .slaves = omap44xx_mcbsp3_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp3_slaves), + .opt_clks = mcbsp3_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp3_opt_clks), }; /* mcbsp4 */ @@ -3200,6 +3221,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = { &omap44xx_l4_per__mcbsp4, }; +static struct omap_hwmod_opt_clk mcbsp4_opt_clks[] = { + { .role = "pad_fck", .clk = "pad_clks_ck" }, + { .role = "prcm_clk", .clk = "mcbsp4_sync_mux_ck" }, +}; + static struct omap_hwmod omap44xx_mcbsp4_hwmod = { .name = "mcbsp4", .class = &omap44xx_mcbsp_hwmod_class, @@ -3216,6 +3242,8 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = { }, .slaves = omap44xx_mcbsp4_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp4_slaves), + .opt_clks = mcbsp4_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(mcbsp4_opt_clks), }; /* -- cgit v0.10.2 From f3718a818f7fb3636130d5f34bde8df34f45c5e5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 4 Apr 2012 08:16:25 -0700 Subject: Revert "nouveau/bios: Fix tracking of BIOS image data" This reverts commit d06221c0617ab6d0bc41c4980cefdd9c8cc9a1c1. It turns out to trigger the "BUG_ON(!PageCompound(page))" in kfree(), apparently because the code ends up trying to free somethng that was never kmalloced in the first place. BenH points out that the patch was untested and wasn't meant to go into the upstream kernel that quickly in the first place. Backtrace: bios_shadow bios_shadow_prom nv_mask init_io bios_shadow nouveau_bios_init NVReadVgaCrtc NVSetOwner nouveau_card_init nouveau_load Reported-by: Meelis Roos Requested-by: Dave Airlie Acked-by: Benjamin Herrenschmidt Cc: Ben Skeggs Signed-off-by: Linus Torvalds diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 1947d61..80963d0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -273,7 +273,6 @@ bios_shadow(struct drm_device *dev) mthd->score = score_vbios(bios, mthd->rw); mthd->size = bios->length; mthd->data = bios->data; - bios->data = NULL; } while (mthd->score != 3 && (++mthd)->shadow); mthd = shadow_methods; @@ -282,8 +281,7 @@ bios_shadow(struct drm_device *dev) if (mthd->score > best->score) { kfree(best->data); best = mthd; - } else - kfree(mthd->data); + } } while ((++mthd)->shadow); if (best->score) { -- cgit v0.10.2 From 0eb4fd9b3e4d08973f7f086dbdb14a0ad5c3d76d Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 15 Mar 2012 13:24:31 -0500 Subject: ARM: OMAP: clock: fix race in disable all clocks clk_disable_unused is invoked when CONFIG_OMAP_RESET_CLOCKS=y. Since clk_disable_unused is called as lateinitcall, there can be more than a few workqueues executing off secondary CPU(s). The current code does the following: a) checks if clk is unused b) holds lock c) disables clk d) unlocks Between (a) and (b) being executed on CPU0, It is possible to have a driver executing on CPU1 which could do a get_sync->clk_get (and increase the use_count) of the clock which was just about to be disabled by clk_disable_unused. We ensure instead that the entire list traversal is protected by the lock allowing for parent child clock traversal which could be potentially be done by runtime operations to be safe as well. Reported-by: Todd Poynor Signed-off-by: Nishanth Menon Signed-off-by: Paul Walmsley diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 56b6f8b..8506cbb 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -441,6 +441,8 @@ static int __init clk_disable_unused(void) return 0; pr_info("clock: disabling unused clocks to save power\n"); + + spin_lock_irqsave(&clockfw_lock, flags); list_for_each_entry(ck, &clocks, node) { if (ck->ops == &clkops_null) continue; @@ -448,10 +450,9 @@ static int __init clk_disable_unused(void) if (ck->usecount > 0 || !ck->enable_reg) continue; - spin_lock_irqsave(&clockfw_lock, flags); arch_clock->clk_disable_unused(ck); - spin_unlock_irqrestore(&clockfw_lock, flags); } + spin_unlock_irqrestore(&clockfw_lock, flags); return 0; } -- cgit v0.10.2 From 167d82152079debd0a76726972a76ea032d82043 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 3 Apr 2012 19:14:04 -0400 Subject: avr32: fix nop compile fails from system.h split up To fix: In file included from kernel/exit.c:61: arch/avr32/include/asm/mmu_context.h: In function 'enable_mmu': arch/avr32/include/asm/mmu_context.h:135: error: implicit declaration of function 'nop' It needs an include of the new file created in commit ae4739465866 ("Disintegrate asm/system.h for AVR32"), but since that file only contains "nop", and since other arch already have precedent of putting nop in asm/barrier.h we should just delete the new file and put nop in barrier.h Suggested-and-acked-by: David Howells Cc: Haavard Skinnemoen Cc: Hans-Christian Egtvedt Signed-off-by: Paul Gortmaker Signed-off-by: Linus Torvalds diff --git a/arch/avr32/include/asm/barrier.h b/arch/avr32/include/asm/barrier.h index 808001c..0961275 100644 --- a/arch/avr32/include/asm/barrier.h +++ b/arch/avr32/include/asm/barrier.h @@ -8,6 +8,8 @@ #ifndef __ASM_AVR32_BARRIER_H #define __ASM_AVR32_BARRIER_H +#define nop() asm volatile("nop") + #define mb() asm volatile("" : : : "memory") #define rmb() mb() #define wmb() asm volatile("sync 0" : : : "memory") diff --git a/arch/avr32/include/asm/special_insns.h b/arch/avr32/include/asm/special_insns.h deleted file mode 100644 index f922218..0000000 --- a/arch/avr32/include/asm/special_insns.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef __ASM_AVR32_SPECIAL_INSNS_H -#define __ASM_AVR32_SPECIAL_INSNS_H - -#define nop() asm volatile("nop") - -#endif /* __ASM_AVR32_SPECIAL_INSNS_H */ -- cgit v0.10.2 From 59269b94483eabeacbc9a535944b3dafac92a303 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Wed, 21 Dec 2011 00:27:14 +0100 Subject: ARM: OMAP AM3517/3505: clock data: change EMAC clocks aliases Rename EMAC clocks to match driver expectations: both davinci_emac and davinci_mdio drivers call clk_get(dev, NULL) so we have to provide ("davinci_emac", NULL) and ("davinci_mdio.0", NULL) clocks instead of ("davinci_emac", "emac_clk") and ("davinci_emac", "phy_clk") resp. Cc: Paul Walmsley Signed-off-by: Ilya Yanok Tested-by: Yegor Yefremov Tested-by: Matt Porter Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 19c1dc8..f3a9a4a 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3467,8 +3467,8 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX), CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX), CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX), - CLK("davinci_emac", "emac_clk", &emac_ick, CK_AM35XX), - CLK("davinci_emac", "phy_clk", &emac_fck, CK_AM35XX), + CLK("davinci_emac", NULL, &emac_ick, CK_AM35XX), + CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX), CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX), CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX), CLK("musb-am35x", "ick", &hsotgusb_ick_am35xx, CK_AM35XX), -- cgit v0.10.2 From fd9abe1b5beafe776c51507dac32486f627c6ad8 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 4 Apr 2012 09:27:19 -0700 Subject: ARM: EXYNOS: fix CONFIG_DEBUG_LL addruart cannot read from the physical address of the chipid register, that will fail as soon as the mmu is turned on. Fixing it to read from the physical or virtual address depending on the mmu state also does not work, because there is a period between head.S and exynos_map_io where the mmu is on, the uart is mapped and used, but the chipid mapping is not yet present. Fix addruart to use the ARM Main ID cp15 register to determine if the core is Cortex A15 (EXYNOS5) or not (EXYNOS4). Signed-off-by: Colin Cross Tested-by: Marek Szyprowski Tested-by: Thomas Abraham Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/include/mach/debug-macro.S b/arch/arm/mach-exynos/include/mach/debug-macro.S index 6c857ff..e0c86ea 100644 --- a/arch/arm/mach-exynos/include/mach/debug-macro.S +++ b/arch/arm/mach-exynos/include/mach/debug-macro.S @@ -21,10 +21,9 @@ */ .macro addruart, rp, rv, tmp - mov \rp, #0x10000000 - ldr \rp, [\rp, #0x0] - and \rp, \rp, #0xf00000 - teq \rp, #0x500000 @@ EXYNOS5 + mrc p15, 0, \tmp, c0, c0, 0 + and \tmp, \tmp, #0xf0 + teq \tmp, #0xf0 @@ A15 ldreq \rp, =EXYNOS5_PA_UART movne \rp, #EXYNOS4_PA_UART @@ EXYNOS4 ldr \rv, =S3C_VA_UART -- cgit v0.10.2 From 6aa51068f58022ca616fad40b6773a1de50599f0 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 4 Apr 2012 09:27:37 -0700 Subject: ARM: EXYNOS: use chip_id reg in uncompress to select uart base phys Signed-off-by: Dima Zavin Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/include/mach/uncompress.h b/arch/arm/mach-exynos/include/mach/uncompress.h index 493f4f3..2979995 100644 --- a/arch/arm/mach-exynos/include/mach/uncompress.h +++ b/arch/arm/mach-exynos/include/mach/uncompress.h @@ -20,9 +20,24 @@ volatile u8 *uart_base; #include +static unsigned int __raw_readl(unsigned int ptr) +{ + return *((volatile unsigned int *)ptr); +} + static void arch_detect_cpu(void) { - if (machine_is_smdk5250()) + u32 chip_id = __raw_readl(EXYNOS_PA_CHIPID); + + /* + * product_id is bits 31:12 + * bits 23:20 describe the exynosX family + * + */ + chip_id >>= 20; + chip_id &= 0xf; + + if (chip_id == 0x5) uart_base = (volatile u8 *)EXYNOS5_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT); else uart_base = (volatile u8 *)EXYNOS4_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT); -- cgit v0.10.2 From 1e7caf8bcf1b49eae152ad7cf442775472dd587c Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 21 Mar 2012 14:38:55 +0100 Subject: USB: ohci-at91: fix vbus_pin_active_low handling The information is not properly taken into account for {get|set}_power() functions. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Alan Stern Cc: stable [3.2+] diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index db8963f..4d266ae 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -247,7 +247,7 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int return; gpio_set_value(pdata->vbus_pin[port], - !pdata->vbus_pin_active_low[port] ^ enable); + pdata->vbus_pin_active_low[port] ^ enable); } static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) @@ -259,7 +259,7 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) return -EINVAL; return gpio_get_value(pdata->vbus_pin[port]) ^ - !pdata->vbus_pin_active_low[port]; + pdata->vbus_pin_active_low[port]; } /* -- cgit v0.10.2 From cca0355a09b1bfe9f8985285199a346e13cacf39 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 28 Mar 2012 11:56:28 +0200 Subject: ARM: at91/USB host: specify and handle properly vbus_pin_active_low Due to an error while handling vbus_pin_active_low in ohci-at91 driver, the specification of this property was not good in devices/board files. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Cc: stable [3.2+] diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 53688c46..27cfce3 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -72,7 +72,8 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) /* Enable VBus control for UHP ports */ for (i = 0; i < data->ports; i++) { if (gpio_is_valid(data->vbus_pin[i])) - at91_set_gpio_output(data->vbus_pin[i], 0); + at91_set_gpio_output(data->vbus_pin[i], + data->vbus_pin_active_low[i]); } /* Enable overcurrent notification */ diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 698479f..ddf210a 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -127,7 +127,8 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) /* Enable VBus control for UHP ports */ for (i = 0; i < data->ports; i++) { if (gpio_is_valid(data->vbus_pin[i])) - at91_set_gpio_output(data->vbus_pin[i], 0); + at91_set_gpio_output(data->vbus_pin[i], + data->vbus_pin_active_low[i]); } /* Enable overcurrent notification */ @@ -188,7 +189,8 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) /* Enable VBus control for UHP ports */ for (i = 0; i < data->ports; i++) { if (gpio_is_valid(data->vbus_pin[i])) - at91_set_gpio_output(data->vbus_pin[i], 0); + at91_set_gpio_output(data->vbus_pin[i], + data->vbus_pin_active_low[i]); } usbh_ehci_data = *data; diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 66f0ddf..2ffe50f 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -74,6 +74,7 @@ static void __init ek_init_early(void) static struct at91_usbh_data __initdata ek_usbh_data = { .ports = 2, .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 }, + .vbus_pin_active_low = {1, 1}, .overcurrent_pin= {-EINVAL, -EINVAL}, }; diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index e1bea73..c88e908 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -71,6 +71,7 @@ static void __init ek_init_early(void) static struct at91_usbh_data __initdata ek_usbh_hs_data = { .ports = 2, .vbus_pin = {AT91_PIN_PD1, AT91_PIN_PD3}, + .vbus_pin_active_low = {1, 1}, .overcurrent_pin= {-EINVAL, -EINVAL}, }; -- cgit v0.10.2 From 74adcb210685e7191425b6203e67c08d759412fa Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 21 Mar 2012 14:48:23 +0100 Subject: ARM: at91/dts: USB host vbus is active low Change vbus gpio configuration in .dts files to switch to active low configuration. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Cc: stable diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts index ac0dc00..7829a4d 100644 --- a/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/arch/arm/boot/dts/at91sam9g25ek.dts @@ -37,8 +37,8 @@ usb0: ohci@00600000 { status = "okay"; num-ports = <2>; - atmel,vbus-gpio = <&pioD 19 0 - &pioD 20 0 + atmel,vbus-gpio = <&pioD 19 1 + &pioD 20 1 >; }; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index c4c8ae4..6abb571 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -73,8 +73,8 @@ usb0: ohci@00700000 { status = "okay"; num-ports = <2>; - atmel,vbus-gpio = <&pioD 1 0 - &pioD 3 0>; + atmel,vbus-gpio = <&pioD 1 1 + &pioD 3 1>; }; usb1: ehci@00800000 { -- cgit v0.10.2 From aaf9f5fc67c18259760d6302e679dcb3e36709a7 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 21 Mar 2012 16:58:11 +0100 Subject: USB: ohci-at91: rework and fix initialization The DT information are filled in a pdata structure and then passed on to the usual check code of the probe function. Thus we do not need to redo the gpio checking and irq configuration in the DT-related code. On the other hand, we setup GPIO direction in driver for vbus and overcurrent. It will be useful when moving to pinctrl subsystem. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Alan Stern diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 4d266ae..c30da6a 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -492,7 +492,7 @@ static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32); static int __devinit ohci_at91_of_init(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - int i, ret, gpio; + int i, gpio; enum of_gpio_flags flags; struct at91_usbh_data *pdata; u32 ports; @@ -520,42 +520,11 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev) if (!gpio_is_valid(gpio)) continue; pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; - ret = gpio_request(gpio, "ohci_vbus"); - if (ret) { - dev_warn(&pdev->dev, "can't request vbus gpio %d", gpio); - continue; - } - ret = gpio_direction_output(gpio, !(flags & OF_GPIO_ACTIVE_LOW) ^ 1); - if (ret) - dev_warn(&pdev->dev, "can't put vbus gpio %d as output %d", - !(flags & OF_GPIO_ACTIVE_LOW) ^ 1, gpio); } - for (i = 0; i < 2; i++) { - gpio = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); - pdata->overcurrent_pin[i] = gpio; - if (!gpio_is_valid(gpio)) - continue; - ret = gpio_request(gpio, "ohci_overcurrent"); - if (ret) { - dev_err(&pdev->dev, "can't request overcurrent gpio %d", gpio); - continue; - } - - ret = gpio_direction_input(gpio); - if (ret) { - dev_err(&pdev->dev, "can't configure overcurrent gpio %d as input", gpio); - continue; - } - - ret = request_irq(gpio_to_irq(gpio), - ohci_hcd_at91_overcurrent_irq, - IRQF_SHARED, "ohci_overcurrent", pdev); - if (ret) { - gpio_free(gpio); - dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n"); - } - } + for (i = 0; i < 2; i++) + pdata->overcurrent_pin[i] = + of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); pdev->dev.platform_data = pdata; @@ -574,6 +543,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) { struct at91_usbh_data *pdata; int i; + int gpio; + int ret; i = ohci_at91_of_init(pdev); @@ -586,23 +557,56 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { if (!gpio_is_valid(pdata->vbus_pin[i])) continue; - gpio_request(pdata->vbus_pin[i], "ohci_vbus"); + gpio = pdata->vbus_pin[i]; + + ret = gpio_request(gpio, "ohci_vbus"); + if (ret) { + dev_err(&pdev->dev, + "can't request vbus gpio %d\n", gpio); + continue; + } + ret = gpio_direction_output(gpio, + !pdata->vbus_pin_active_low[i]); + if (ret) { + dev_err(&pdev->dev, + "can't put vbus gpio %d as output %d\n", + gpio, !pdata->vbus_pin_active_low[i]); + gpio_free(gpio); + continue; + } + ohci_at91_usb_set_power(pdata, i, 1); } for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { - int ret; - if (!gpio_is_valid(pdata->overcurrent_pin[i])) continue; - gpio_request(pdata->overcurrent_pin[i], "ohci_overcurrent"); + gpio = pdata->overcurrent_pin[i]; + + ret = gpio_request(gpio, "ohci_overcurrent"); + if (ret) { + dev_err(&pdev->dev, + "can't request overcurrent gpio %d\n", + gpio); + continue; + } + + ret = gpio_direction_input(gpio); + if (ret) { + dev_err(&pdev->dev, + "can't configure overcurrent gpio %d as input\n", + gpio); + gpio_free(gpio); + continue; + } - ret = request_irq(gpio_to_irq(pdata->overcurrent_pin[i]), + ret = request_irq(gpio_to_irq(gpio), ohci_hcd_at91_overcurrent_irq, IRQF_SHARED, "ohci_overcurrent", pdev); if (ret) { - gpio_free(pdata->overcurrent_pin[i]); - dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n"); + gpio_free(gpio); + dev_err(&pdev->dev, + "can't get gpio IRQ for overcurrent\n"); } } } -- cgit v0.10.2 From 0ee6d1eeef7bf4e08aba37bf1da377b25e8d853a Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 21 Mar 2012 16:53:09 +0100 Subject: USB: ohci-at91: change maximum number of ports Change number of ports to 3 for newer SoCs. Modify pdata structure and ohci-at91 code that was dealing with ports information and check of port indexes. Several coding style errors have been addresses as the patch was touching affected lines of code and was producing errors while run through checkpatch.pl. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Alan Stern diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 544a5d5..49a8211 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -86,14 +86,15 @@ extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *d extern void __init at91_add_device_eth(struct macb_platform_data *data); /* USB Host */ +#define AT91_MAX_USBH_PORTS 3 struct at91_usbh_data { - u8 ports; /* number of ports on root hub */ - int vbus_pin[2]; /* port power-control pin */ - u8 vbus_pin_active_low[2]; + int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */ + int overcurrent_pin[AT91_MAX_USBH_PORTS]; + u8 ports; /* number of ports on root hub */ u8 overcurrent_supported; - int overcurrent_pin[2]; - u8 overcurrent_status[2]; - u8 overcurrent_changed[2]; + u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS]; + u8 overcurrent_status[AT91_MAX_USBH_PORTS]; + u8 overcurrent_changed[AT91_MAX_USBH_PORTS]; }; extern void __init at91_add_device_usbh(struct at91_usbh_data *data); extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data); diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index c30da6a..7cf4797 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -27,6 +27,10 @@ #error "CONFIG_ARCH_AT91 must be defined." #endif +#define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS) +#define at91_for_each_port(index) \ + for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++) + /* interface and function clocks; sometimes also an AHB clock */ static struct clk *iclk, *fclk, *hclk; static int clocked; @@ -240,7 +244,7 @@ ohci_at91_start (struct usb_hcd *hcd) static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable) { - if (port < 0 || port >= 2) + if (!valid_port(port)) return; if (!gpio_is_valid(pdata->vbus_pin[port])) @@ -252,7 +256,7 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) { - if (port < 0 || port >= 2) + if (!valid_port(port)) return -EINVAL; if (!gpio_is_valid(pdata->vbus_pin[port])) @@ -271,9 +275,9 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf) int length = ohci_hub_status_data(hcd, buf); int port; - for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { + at91_for_each_port(port) { if (pdata->overcurrent_changed[port]) { - if (! length) + if (!length) length = 1; buf[0] |= 1 << (port + 1); } @@ -297,11 +301,17 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", hcd, typeReq, wValue, wIndex, buf, wLength); + wIndex--; + switch (typeReq) { case SetPortFeature: if (wValue == USB_PORT_FEAT_POWER) { dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); - ohci_at91_usb_set_power(pdata, wIndex - 1, 1); + if (valid_port(wIndex)) { + ohci_at91_usb_set_power(pdata, wIndex, 1); + ret = 0; + } + goto out; } break; @@ -312,9 +322,9 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dev_dbg(hcd->self.controller, "ClearPortFeature: C_OVER_CURRENT\n"); - if (wIndex == 1 || wIndex == 2) { - pdata->overcurrent_changed[wIndex-1] = 0; - pdata->overcurrent_status[wIndex-1] = 0; + if (valid_port(wIndex)) { + pdata->overcurrent_changed[wIndex] = 0; + pdata->overcurrent_status[wIndex] = 0; } goto out; @@ -323,9 +333,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dev_dbg(hcd->self.controller, "ClearPortFeature: OVER_CURRENT\n"); - if (wIndex == 1 || wIndex == 2) { - pdata->overcurrent_status[wIndex-1] = 0; - } + if (valid_port(wIndex)) + pdata->overcurrent_status[wIndex] = 0; goto out; @@ -333,15 +342,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dev_dbg(hcd->self.controller, "ClearPortFeature: POWER\n"); - if (wIndex == 1 || wIndex == 2) { - ohci_at91_usb_set_power(pdata, wIndex - 1, 0); + if (valid_port(wIndex)) { + ohci_at91_usb_set_power(pdata, wIndex, 0); return 0; } } break; } - ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); + ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength); if (ret) goto out; @@ -377,18 +386,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); - if (wIndex == 1 || wIndex == 2) { - if (! ohci_at91_usb_get_power(pdata, wIndex-1)) { + if (valid_port(wIndex)) { + if (!ohci_at91_usb_get_power(pdata, wIndex)) *data &= ~cpu_to_le32(RH_PS_PPS); - } - if (pdata->overcurrent_changed[wIndex-1]) { + if (pdata->overcurrent_changed[wIndex]) *data |= cpu_to_le32(RH_PS_OCIC); - } - if (pdata->overcurrent_status[wIndex-1]) { + if (pdata->overcurrent_status[wIndex]) *data |= cpu_to_le32(RH_PS_POCI); - } } } @@ -450,14 +456,14 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) /* From the GPIO notifying the over-current situation, find * out the corresponding port */ - for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { + at91_for_each_port(port) { if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { gpio = pdata->overcurrent_pin[port]; break; } } - if (port == ARRAY_SIZE(pdata->overcurrent_pin)) { + if (port == AT91_MAX_USBH_PORTS) { dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n"); return IRQ_HANDLED; } @@ -467,7 +473,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) /* When notified of an over-current situation, disable power on the corresponding port, and mark this port in over-current. */ - if (! val) { + if (!val) { ohci_at91_usb_set_power(pdata, port, 0); pdata->overcurrent_status[port] = 1; pdata->overcurrent_changed[port] = 1; @@ -514,7 +520,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev) if (!of_property_read_u32(np, "num-ports", &ports)) pdata->ports = ports; - for (i = 0; i < 2; i++) { + at91_for_each_port(i) { gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags); pdata->vbus_pin[i] = gpio; if (!gpio_is_valid(gpio)) @@ -522,7 +528,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev) pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; } - for (i = 0; i < 2; i++) + at91_for_each_port(i) pdata->overcurrent_pin[i] = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); @@ -554,7 +560,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; if (pdata) { - for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { + at91_for_each_port(i) { if (!gpio_is_valid(pdata->vbus_pin[i])) continue; gpio = pdata->vbus_pin[i]; @@ -578,7 +584,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) ohci_at91_usb_set_power(pdata, i, 1); } - for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { + at91_for_each_port(i) { if (!gpio_is_valid(pdata->overcurrent_pin[i])) continue; gpio = pdata->overcurrent_pin[i]; @@ -621,14 +627,14 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) int i; if (pdata) { - for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { + at91_for_each_port(i) { if (!gpio_is_valid(pdata->vbus_pin[i])) continue; ohci_at91_usb_set_power(pdata, i, 0); gpio_free(pdata->vbus_pin[i]); } - for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { + at91_for_each_port(i) { if (!gpio_is_valid(pdata->overcurrent_pin[i])) continue; free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev); -- cgit v0.10.2 From 1887ab2bf236596a5ac7c0e7a90127b468c24081 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 28 Mar 2012 11:49:01 +0200 Subject: USB: ohci-at91: trivial return code name change Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Alan Stern diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 7cf4797..09f597a 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -552,10 +552,9 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) int gpio; int ret; - i = ohci_at91_of_init(pdev); - - if (i) - return i; + ret = ohci_at91_of_init(pdev); + if (ret) + return ret; pdata = pdev->dev.platform_data; -- cgit v0.10.2 From 4352808cfd4567d1912c15c18096b1ece79ce5bf Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 22 Mar 2012 14:47:40 +0100 Subject: ARM: at91/at91sam9x5.dtsi: fix NAND ale/cle in DT file Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index c111001..6597177 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -201,8 +201,8 @@ >; atmel,nand-addr-offset = <21>; atmel,nand-cmd-offset = <22>; - gpios = <&pioC 8 0 - &pioC 14 0 + gpios = <&pioD 5 0 + &pioD 4 0 0 >; status = "disabled"; -- cgit v0.10.2 From c16524e6a957bc96ed02738d5396d355c0027d00 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 22 Mar 2012 14:48:47 +0100 Subject: ARM: at91/NAND DT bindings: add comments Add comments to NAND "gpios" property to make it clearer. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt index 5903ecf..a200695 100644 --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt @@ -27,13 +27,13 @@ nand0: nand@40000000,0 { reg = <0x40000000 0x10000000 0xffffe800 0x200 >; - atmel,nand-addr-offset = <21>; - atmel,nand-cmd-offset = <22>; + atmel,nand-addr-offset = <21>; /* ale */ + atmel,nand-cmd-offset = <22>; /* cle */ nand-on-flash-bbt; nand-ecc-mode = "soft"; - gpios = <&pioC 13 0 - &pioC 14 0 - 0 + gpios = <&pioC 13 0 /* rdy */ + &pioC 14 0 /* nce */ + 0 /* cd */ >; partition@0 { ... -- cgit v0.10.2 From 9475375a5eb2ab9380e644d45173f67cbca0da80 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 27 Mar 2012 18:23:31 +0200 Subject: USB: ehci-atmel: add needed of.h header file Compilation error in case of non-DT configuration without this of.h header file. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Alan Stern diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 19f318a..cf14c95 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -13,6 +13,7 @@ #include #include +#include #include /* interface and function clocks */ -- cgit v0.10.2 From 0c2c1f624d4f99825851f0253f1308dd591df6ef Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 28 Mar 2012 11:58:58 +0200 Subject: ARM: at91: fix check of valid GPIO for SPI and USB SPI chip select pins have to be checked by gpio_is_valid(). The USB host overcurrent_pin checking was missing. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 7e5651e..5652dde 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -598,6 +598,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) else cs_pin = spi1_standard_cs[devices[i].chip_select]; + if (!gpio_is_valid(cs_pin)) + continue; + if (devices[i].bus_num == 0) enable_spi0 = 1; else diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 096da87..4db961a 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -415,6 +415,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) else cs_pin = spi1_standard_cs[devices[i].chip_select]; + if (!gpio_is_valid(cs_pin)) + continue; + if (devices[i].bus_num == 0) enable_spi0 = 1; else diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 27cfce3..fe99206 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -672,6 +672,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) else cs_pin = spi1_standard_cs[devices[i].chip_select]; + if (!gpio_is_valid(cs_pin)) + continue; + if (devices[i].bus_num == 0) enable_spi0 = 1; else diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index ddf210a..6b008ae 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -133,7 +133,7 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) /* Enable overcurrent notification */ for (i = 0; i < data->ports; i++) { - if (data->overcurrent_pin[i]) + if (gpio_is_valid(data->overcurrent_pin[i])) at91_set_gpio_input(data->overcurrent_pin[i], 1); } @@ -787,6 +787,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) else cs_pin = spi1_standard_cs[devices[i].chip_select]; + if (!gpio_is_valid(cs_pin)) + continue; + if (devices[i].bus_num == 0) enable_spi0 = 1; else diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index eda72e8..fe4ae22 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -419,6 +419,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) else cs_pin = spi_standard_cs[devices[i].chip_select]; + if (!gpio_is_valid(cs_pin)) + continue; + /* enable chip-select pin */ at91_set_gpio_output(cs_pin, 1); -- cgit v0.10.2 From dcce6ce802c271cd7c21f4730f301150577b2826 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 2 Apr 2012 20:44:20 +0200 Subject: ARM: at91: dt: remove unit-address part for memory nodes Because of the inclusion of skeleton.dtsi, the memory node is named "memory" we where not modifying the already included one but creating a new one. It caused bad memory node detection during early_init_dt_scan_memory() so we modify them. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Cc: Jean-Christophe PLAGNIOL-VILLARD Cc: devicetree-discuss@lists.ozlabs.org diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index 92f3662..799ad18 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -35,7 +35,7 @@ }; }; - memory@20000000 { + memory { reg = <0x20000000 0x08000000>; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 3d0c32f..9e6eb6e 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -36,7 +36,7 @@ }; }; - memory@70000000 { + memory { reg = <0x70000000 0x10000000>; }; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index 6abb571..a3633bd 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -17,7 +17,7 @@ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"; }; - memory@70000000 { + memory { reg = <0x70000000 0x4000000>; }; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 6597177..70ab3a4 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -34,7 +34,7 @@ }; }; - memory@20000000 { + memory { reg = <0x20000000 0x10000000>; }; diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi index 67936f8..31e7be2 100644 --- a/arch/arm/boot/dts/at91sam9x5cm.dtsi +++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi @@ -8,7 +8,7 @@ */ / { - memory@20000000 { + memory { reg = <0x20000000 0x8000000>; }; diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts index 3b3c4e0..7c2399c 100644 --- a/arch/arm/boot/dts/usb_a9g20.dts +++ b/arch/arm/boot/dts/usb_a9g20.dts @@ -16,7 +16,7 @@ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs"; }; - memory@20000000 { + memory { reg = <0x20000000 0x4000000>; }; -- cgit v0.10.2 From 2d1f6310d499f8d23e6726292c89380bd1d9693e Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 4 Apr 2012 10:09:03 -0700 Subject: EXYNOS: fix dependency for EXYNOS_CPUFREQ This fixes the CPUFREQ dependency for regarding EXYNOS SoCs such as EXYNOS4210, EXYNOS4X12 and EXYNOS5250. Its cpufreq driver should be built with selection of SoC arch part. Reported-by: Russell King Acked-by: Dave Jones Signed-off-by: Kukjin Kim diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 32d790d..ffbb446 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -51,9 +51,6 @@ config ARM_S5PV210_CPUFREQ config ARM_EXYNOS_CPUFREQ bool "SAMSUNG EXYNOS SoCs" depends on ARCH_EXYNOS - select ARM_EXYNOS4210_CPUFREQ if CPU_EXYNOS4210 - select ARM_EXYNOS4X12_CPUFREQ if (SOC_EXYNOS4212 || SOC_EXYNOS4412) - select ARM_EXYNOS5250_CPUFREQ if SOC_EXYNOS5250 default y help This adds the CPUFreq driver common part for Samsung @@ -62,20 +59,19 @@ config ARM_EXYNOS_CPUFREQ If in doubt, say N. config ARM_EXYNOS4210_CPUFREQ - bool "Samsung EXYNOS4210" - depends on ARCH_EXYNOS + def_bool CPU_EXYNOS4210 help This adds the CPUFreq driver for Samsung EXYNOS4210 SoC (S5PV310 or S5PC210). config ARM_EXYNOS4X12_CPUFREQ - bool "Samsung EXYNOS4X12" + def_bool (SOC_EXYNOS4212 || SOC_EXYNOS4412) help This adds the CPUFreq driver for Samsung EXYNOS4X12 SoC (EXYNOS4212 or EXYNOS4412). config ARM_EXYNOS5250_CPUFREQ - bool "Samsung EXYNOS5250" + def_bool SOC_EXYNOS5250 help This adds the CPUFreq driver for Samsung EXYNOS5250 SoC. -- cgit v0.10.2 From 5c1e2c9dc684f26fcc78ff4ef15dc97ed0244303 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 16 Mar 2012 17:35:08 -0600 Subject: gpio: tegra: fix register address calculations for Tegra30 Tegra20 and Tegra30 share the same register layout within registers, but the addresses of the registers is a little different. Fix the driver to cope with this. Signed-off-by: Stephen Warren Acked-by: Olof Johansson diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 32de670..7d05a34 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,7 +37,8 @@ #define GPIO_PORT(x) (((x) >> 3) & 0x3) #define GPIO_BIT(x) ((x) & 0x7) -#define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4) +#define GPIO_REG(x) (GPIO_BANK(x) * tegra_gpio_bank_stride + \ + GPIO_PORT(x) * 4) #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) #define GPIO_OE(x) (GPIO_REG(x) + 0x10) @@ -48,12 +49,12 @@ #define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60) #define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70) -#define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800) -#define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810) -#define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820) -#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840) -#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850) -#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860) +#define GPIO_MSK_CNF(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x00) +#define GPIO_MSK_OE(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x10) +#define GPIO_MSK_OUT(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0X20) +#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x40) +#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x50) +#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x60) #define GPIO_INT_LVL_MASK 0x010101 #define GPIO_INT_LVL_EDGE_RISING 0x000101 @@ -78,6 +79,8 @@ struct tegra_gpio_bank { static struct irq_domain *irq_domain; static void __iomem *regs; static u32 tegra_gpio_bank_count; +static u32 tegra_gpio_bank_stride; +static u32 tegra_gpio_upper_offset; static struct tegra_gpio_bank *tegra_gpio_banks; static inline void tegra_gpio_writel(u32 val, u32 reg) @@ -333,6 +336,26 @@ static struct irq_chip tegra_gpio_irq_chip = { #endif }; +struct tegra_gpio_soc_config { + u32 bank_stride; + u32 upper_offset; +}; + +static struct tegra_gpio_soc_config tegra20_gpio_config = { + .bank_stride = 0x80, + .upper_offset = 0x800, +}; + +static struct tegra_gpio_soc_config tegra30_gpio_config = { + .bank_stride = 0x100, + .upper_offset = 0x80, +}; + +static struct of_device_id tegra_gpio_of_match[] __devinitdata = { + { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config }, + { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config }, + { }, +}; /* This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. @@ -341,6 +364,8 @@ static struct lock_class_key gpio_lock_class; static int __devinit tegra_gpio_probe(struct platform_device *pdev) { + const struct of_device_id *match; + struct tegra_gpio_soc_config *config; int irq_base; struct resource *res; struct tegra_gpio_bank *bank; @@ -348,6 +373,15 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) int i; int j; + match = of_match_device(tegra_gpio_of_match, &pdev->dev); + if (match) + config = (struct tegra_gpio_soc_config *)match->data; + else + config = &tegra20_gpio_config; + + tegra_gpio_bank_stride = config->bank_stride; + tegra_gpio_upper_offset = config->upper_offset; + for (;;) { res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count); if (!res) @@ -441,11 +475,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) return 0; } -static struct of_device_id tegra_gpio_of_match[] __devinitdata = { - { .compatible = "nvidia,tegra20-gpio", }, - { }, -}; - static struct platform_driver tegra_gpio_driver = { .driver = { .name = "tegra-gpio", -- cgit v0.10.2 From 4a3398ee9d7d8008ee9bfc8a600b734a1b22af23 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 16 Mar 2012 17:37:24 -0600 Subject: gpio: tegra: Iterate over the correct number of banks When Tegra30 support was added to the Tegra GPIO driver, a few places which iterated over all banks were not converted to use the variable tegra_gpio_bank_count rather than hard-coding the bank count. Fix this. Signed-off-by: Stephen Warren Acked-by: Olof Johansson diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 7d05a34..12f349b3 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -436,7 +436,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) return -ENODEV; } - for (i = 0; i < 7; i++) { + for (i = 0; i < tegra_gpio_bank_count; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio)); @@ -514,7 +514,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) int i; int j; - for (i = 0; i < 7; i++) { + for (i = 0; i < tegra_gpio_bank_count; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); seq_printf(s, -- cgit v0.10.2 From 8b8c3c7895dc8dcf60c58b23bc9231f4ee7887a2 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 12 Mar 2012 20:04:32 +0530 Subject: ARM: OMAP2+: powerdomain: Wait for powerdomain transition in pwrdm_state_switch() Commit b1cbdb00d ("OMAP: clockdomain: Wait for powerdomain to be ON when using clockdomain force wakeup") was assuming that pwrdm_state_switch() does wait for the powerdomain transition which is not the case. The missing wait for the powerdomain transition violates the sequence which the hardware expects, which causes power management failures on some devices. Fix this API by adding the pwrdm_wait_transition(). Signed-off-by: Santosh Shilimkar Cc: Rajendra Nayak Cc: Paul Walmsley [paul@pwsan.com: added some more details in the commit log] Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 8a18d1b..96ad3dbe 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -972,7 +972,13 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm) int pwrdm_state_switch(struct powerdomain *pwrdm) { - return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); + int ret; + + ret = pwrdm_wait_transition(pwrdm); + if (!ret) + ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); + + return ret; } int pwrdm_clkdm_state_switch(struct clockdomain *clkdm) -- cgit v0.10.2 From 91a290c4573679a70e242495ac3dbf12b39fb108 Mon Sep 17 00:00:00 2001 From: Ameya Palande Date: Wed, 4 Apr 2012 10:19:31 -0600 Subject: ARM: OMAP4: clock data: fix mult and div mask for USB_DPLL According to OMAP4 TRM Table 3-1183, CM_CLKSEL_DPLL_USB register defines following fields for multiplication and division factors: DPLL_MULT (bits 19:8) DPLL multiplier factor (2 to 4095) DPLL_DIV (bits 7:0) DPLL divider factor (0 to 255) Acked-by: Benoit Cousson Signed-off-by: Ameya Palande Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index c03c110..984904f 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -957,8 +957,8 @@ static struct dpll_data dpll_usb_dd = { .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), .autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_USB, .idlest_reg = OMAP4430_CM_IDLEST_DPLL_USB, - .mult_mask = OMAP4430_DPLL_MULT_MASK, - .div1_mask = OMAP4430_DPLL_DIV_MASK, + .mult_mask = OMAP4430_DPLL_MULT_USB_MASK, + .div1_mask = OMAP4430_DPLL_DIV_0_7_MASK, .enable_mask = OMAP4430_DPLL_EN_MASK, .autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK, .idlest_mask = OMAP4430_ST_DPLL_CLK_MASK, -- cgit v0.10.2 From 6c4a057bffe9823221eab547e11fac181dc18a2b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Wed, 4 Apr 2012 10:20:01 -0600 Subject: ARM: OMAP4: clock data: Force a DPLL clkdm/pwrdm ON before a relock All DPLLs except USB are in ALWON powerdomain. Make sure the clkdm/pwrdm for USB DPLL (l3init) is turned on before attempting a DPLL relock. So, mark the database accordingly. Without this fix, it was seen that DPLL relock fails while testing relock in a loop of USB DPLL. Cc: Nishanth Menon Tested-by: Ameya Palande Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 984904f..fa6ea65 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -978,6 +978,7 @@ static struct clk dpll_usb_ck = { .recalc = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, + .clkdm_name = "l3_init_clkdm", }; static struct clk dpll_usb_clkdcoldo_ck = { -- cgit v0.10.2 From 5897a391d41d42f19285376a4ad1320d452c2946 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 4 Apr 2012 10:20:15 -0600 Subject: ARM: OMAP3: clock data: fill in some missing clockdomains Several clocks are missing clockdomains. This can cause problems with the hwmod and power management code. Fill these in. Signed-off-by: Paul Walmsley Cc: Matt Porter Cc: Vaibhav Hiremath diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index f3a9a4a..f4a626f7 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -1394,6 +1394,7 @@ static struct clk cpefuse_fck = { .name = "cpefuse_fck", .ops = &clkops_omap2_dflt, .parent = &sys_ck, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT, .recalc = &followparent_recalc, @@ -1403,6 +1404,7 @@ static struct clk ts_fck = { .name = "ts_fck", .ops = &clkops_omap2_dflt, .parent = &omap_32k_fck, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_TS_SHIFT, .recalc = &followparent_recalc, @@ -1412,6 +1414,7 @@ static struct clk usbtll_fck = { .name = "usbtll_fck", .ops = &clkops_omap2_dflt_wait, .parent = &dpll5_m2_ck, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, .recalc = &followparent_recalc, @@ -1617,6 +1620,7 @@ static struct clk fshostusb_fck = { .name = "fshostusb_fck", .ops = &clkops_omap2_dflt_wait, .parent = &core_48m_fck, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT, .recalc = &followparent_recalc, @@ -2043,6 +2047,7 @@ static struct clk omapctrl_ick = { .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT, .flags = ENABLE_ON_INIT, + .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2094,6 +2099,7 @@ static struct clk usb_l4_ick = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK, .clksel = usb_l4_clksel, + .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; -- cgit v0.10.2 From acdd5985364f8dc511a0762fab2e683f29d9d692 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 3 Apr 2012 22:17:53 +0000 Subject: sctp: Allow struct sctp_event_subscribe to grow without breaking binaries getsockopt(..., SCTP_EVENTS, ...) performs a length check and returns an error if the user provides less bytes than the size of struct sctp_event_subscribe. Struct sctp_event_subscribe needs to be extended by an u8 for every new event or notification type that is added. This obviously makes getsockopt fail for binaries that are compiled against an older versions of which do not contain all event types. This patch changes getsockopt behaviour to no longer return an error if not enough bytes are being provided by the user. Instead, it returns as much of sctp_event_subscribe as fits into the provided buffer. This leads to the new behavior that users see what they have been aware of at compile time. The setsockopt(..., SCTP_EVENTS, ...) API is already behaving like this. Signed-off-by: Thomas Graf Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 06b42b7..92ba71d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4133,9 +4133,10 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, int __user *optlen) { - if (len < sizeof(struct sctp_event_subscribe)) + if (len <= 0) return -EINVAL; - len = sizeof(struct sctp_event_subscribe); + if (len > sizeof(struct sctp_event_subscribe)) + len = sizeof(struct sctp_event_subscribe); if (put_user(len, optlen)) return -EFAULT; if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) -- cgit v0.10.2 From 2af73d4b2afe826d23e83f3747f850eefbd867ff Mon Sep 17 00:00:00 2001 From: Shlomo Pongratz Date: Tue, 3 Apr 2012 22:56:19 +0000 Subject: net/bonding: emit address change event also in bond_release commit 7d26bb103c4 "bonding: emit event when bonding changes MAC" didn't take care to emit the NETDEV_CHANGEADDR event in bond_release, where bonding actually changes the mac address (to all zeroes). As a result the neighbours aren't deleted by the core networking code (which does so upon getting that event). Signed-off-by: Shlomo Pongratz Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 941b4e1..5cb85cb 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2034,6 +2034,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) write_unlock_bh(&bond->lock); unblock_netpoll_tx(); + if (bond->slave_cnt == 0) + call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); + bond_compute_features(bond); if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) && (old_features & NETIF_F_VLAN_CHALLENGED)) -- cgit v0.10.2 From 234bcf8a499ee206145c7007d12d9706a254f790 Mon Sep 17 00:00:00 2001 From: Shlomo Pongratz Date: Tue, 3 Apr 2012 22:56:20 +0000 Subject: net/bonding: correctly proxy slave neigh param setup ndo function The current implemenation was buggy for slaves who use ndo_neigh_setup, since the networking stack invokes the bonding device ndo entry (from neigh_params_alloc) before any devices are enslaved, and the bonding driver can't further delegate the call at that point in time. As a result when bonding IPoIB devices, the neigh_cleanup hasn't been called. Fix that by deferring the actual call into the slave ndo_neigh_setup from the time the bonding neigh_setup is called. Signed-off-by: Shlomo Pongratz Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5cb85cb..fc8a8d5 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3704,17 +3704,52 @@ static void bond_set_multicast_list(struct net_device *bond_dev) read_unlock(&bond->lock); } -static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms) +static int bond_neigh_init(struct neighbour *n) { - struct bonding *bond = netdev_priv(dev); + struct bonding *bond = netdev_priv(n->dev); struct slave *slave = bond->first_slave; + const struct net_device_ops *slave_ops; + struct neigh_parms parms; + int ret; + + if (!slave) + return 0; + + slave_ops = slave->dev->netdev_ops; + + if (!slave_ops->ndo_neigh_setup) + return 0; + + parms.neigh_setup = NULL; + parms.neigh_cleanup = NULL; + ret = slave_ops->ndo_neigh_setup(slave->dev, &parms); + if (ret) + return ret; + + /* + * Assign slave's neigh_cleanup to neighbour in case cleanup is called + * after the last slave has been detached. Assumes that all slaves + * utilize the same neigh_cleanup (true at this writing as only user + * is ipoib). + */ + n->parms->neigh_cleanup = parms.neigh_cleanup; + + if (!parms.neigh_setup) + return 0; + + return parms.neigh_setup(n); +} + +/* + * The bonding ndo_neigh_setup is called at init time beofre any + * slave exists. So we must declare proxy setup function which will + * be used at run time to resolve the actual slave neigh param setup. + */ +static int bond_neigh_setup(struct net_device *dev, + struct neigh_parms *parms) +{ + parms->neigh_setup = bond_neigh_init; - if (slave) { - const struct net_device_ops *slave_ops - = slave->dev->netdev_ops; - if (slave_ops->ndo_neigh_setup) - return slave_ops->ndo_neigh_setup(slave->dev, parms); - } return 0; } -- cgit v0.10.2 From 857504d06d565ad5b401d505937932775ddf1c47 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 4 Apr 2012 12:10:27 +0000 Subject: sky2: copy received packets on inefficient unaligned architecture Modified from original patch from Chris. The sky2 driver has to have 8 byte alignment of receive buffer on some chip versions. On architectures which don't support efficient unaligned access this doesn't work very well. The solution is to just copy all received packets which is what the driver already does for small packets. This allows the driver to be used on the Tilera TILEmpower-Gx, since the tile architecture doesn't currently handle kernel unaligned accesses, just userspace. Signed-off-by: Stephen Hemminger Acked-by: Chris Metcalf Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index b806d9b..c9b504e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -2469,6 +2469,17 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) return err; } +static inline bool needs_copy(const struct rx_ring_info *re, + unsigned length) +{ +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* Some architectures need the IP header to be aligned */ + if (!IS_ALIGNED(re->data_addr + ETH_HLEN, sizeof(u32))) + return true; +#endif + return length < copybreak; +} + /* For small just reuse existing skb for next receive */ static struct sk_buff *receive_copy(struct sky2_port *sky2, const struct rx_ring_info *re, @@ -2599,7 +2610,7 @@ static struct sk_buff *sky2_receive(struct net_device *dev, goto error; okay: - if (length < copybreak) + if (needs_copy(re, length)) skb = receive_copy(sky2, re, length); else skb = receive_new(sky2, re, length); -- cgit v0.10.2 From c04c1b9ee8f30c7a3a25e20e406247003f634ebe Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 4 Apr 2012 15:48:33 -0600 Subject: regmap: prevent division by zero in rbtree_show If there are no nodes in the cache, nodes will be 0, so calculating "registers / nodes" will cause division by zero. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 5157fa0..ea76a90 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -138,6 +138,7 @@ static int rbtree_show(struct seq_file *s, void *ignored) unsigned int base, top; int nodes = 0; int registers = 0; + int average; mutex_lock(&map->lock); @@ -152,8 +153,13 @@ static int rbtree_show(struct seq_file *s, void *ignored) registers += top - base + 1; } + if (nodes) + average = registers / nodes; + else + average = 0; + seq_printf(s, "%d nodes, %d registers, average %d registers\n", - nodes, registers, registers / nodes); + nodes, registers, average); mutex_unlock(&map->lock); -- cgit v0.10.2 From 27d9129f5ae830cc031a898e0c220e1cdda69b34 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:28:54 +0000 Subject: bnx2x: PFC fix Fix a problem in which PFC frames are not honored, due to incorrect link attributes synchronization following PMF migration, and verify PFC XON is not stuck from previous link change. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index efa557b..7e2ebba 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -1371,7 +1371,14 @@ static void bnx2x_update_pfc_xmac(struct link_params *params, pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN | XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN | XMAC_PFC_CTRL_HI_REG_RX_PFC_EN | - XMAC_PFC_CTRL_HI_REG_TX_PFC_EN; + XMAC_PFC_CTRL_HI_REG_TX_PFC_EN | + XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON; + /* Write pause and PFC registers */ + REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val); + REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val); + REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val); + pfc1_val &= ~XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON; + } /* Write pause and PFC registers */ @@ -6843,6 +6850,12 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars) SINGLE_MEDIA_DIRECT(params)) && (phy_vars[active_external_phy].fault_detected == 0)); + /* Update the PFC configuration in case it was changed */ + if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) + vars->link_status |= LINK_STATUS_PFC_ENABLED; + else + vars->link_status &= ~LINK_STATUS_PFC_ENABLED; + if (vars->link_up) rc = bnx2x_update_link_up(params, vars, link_10g_plus); else @@ -12049,6 +12062,9 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars) bnx2x_emac_init(params, vars); + if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) + vars->link_status |= LINK_STATUS_PFC_ENABLED; + if (params->num_phys == 0) { DP(NETIF_MSG_LINK, "No phy found for initialization !!\n"); return -EINVAL; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index ab0a250..ecc7fa6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -5354,6 +5354,7 @@ #define XMAC_CTRL_REG_TX_EN (0x1<<0) #define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN (0x1<<18) #define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN (0x1<<17) +#define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON (0x1<<1) #define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN (0x1<<0) #define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN (0x1<<3) #define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN (0x1<<4) -- cgit v0.10.2 From ca05f29cf515ac4a8e162c8e0eee886727f5dcc7 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:28:55 +0000 Subject: bnx2x: Fix BCM57810-KR FC Fix 57810-KR flow-control handling link is achieved via CL37 AN. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 7e2ebba..8c00bbc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -3655,6 +3655,33 @@ static void bnx2x_ext_phy_update_adv_fc(struct bnx2x_phy *phy, if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) { bnx2x_cl22_read(bp, phy, 0x4, &ld_pause); bnx2x_cl22_read(bp, phy, 0x5, &lp_pause); + } else if (CHIP_IS_E3(bp) && + SINGLE_MEDIA_DIRECT(params)) { + u8 lane = bnx2x_get_warpcore_lane(phy, params); + u16 gp_status, gp_mask; + bnx2x_cl45_read(bp, phy, + MDIO_AN_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_4, + &gp_status); + gp_mask = (MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL | + MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP) << + lane; + if ((gp_status & gp_mask) == gp_mask) { + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_ADV_PAUSE, &ld_pause); + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_LP_AUTO_NEG, &lp_pause); + } else { + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_CL37_FC_LD, &ld_pause); + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_CL37_FC_LP, &lp_pause); + ld_pause = ((ld_pause & + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) + << 3); + lp_pause = ((lp_pause & + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) + << 3); + } } else { bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index ecc7fa6..1ea2b95 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -6944,6 +6944,10 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_WC_REG_GP2_STATUS_GP_2_2 0x81d2 #define MDIO_WC_REG_GP2_STATUS_GP_2_3 0x81d3 #define MDIO_WC_REG_GP2_STATUS_GP_2_4 0x81d4 +#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL 0x1000 +#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CMPL 0x0100 +#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP 0x0010 +#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CAP 0x1 #define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP 0x81EE #define MDIO_WC_REG_UC_INFO_B1_VERSION 0x81F0 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE 0x81F2 -- cgit v0.10.2 From 6a51c0d17b8fb6ae300ba5bc42a020160944e1b2 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:28:56 +0000 Subject: bnx2x: Fix BCM57810-KR AN speed transition BCM57810-KR link may not come up in 1G after running loopback test, so set the relevant registers to their default values before starting KR autoneg. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 8c00bbc..ce0b0c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -3732,7 +3732,23 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, u16 val16 = 0, lane, bam37 = 0; struct bnx2x *bp = params->bp; DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n"); - + /* Set to default registers that may be overriden by 10G force */ + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7); + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_WC_REG_PAR_DET_10G_CTRL, 0); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555); + bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, + MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_RX66_CONTROL, 0x7415); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190); /* Disable Autoneg: re-enable it after adv is done. */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0); @@ -4402,7 +4418,7 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, switch (serdes_net_if) { case PORT_HW_CFG_NET_SERDES_IF_KR: /* Enable KR Auto Neg */ - if (params->loopback_mode == LOOPBACK_NONE) + if (params->loopback_mode != LOOPBACK_EXT) bnx2x_warpcore_enable_AN_KR(phy, params, vars); else { DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n"); -- cgit v0.10.2 From 25182fc22237f0fb1789c7ac9a79e871a1898ae5 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:28:57 +0000 Subject: bnx2x: Fix BCM578x0-SFI pre-emphasis settings Fix 578x0-SFI pre-emphasis settings per HW recommendations to achieve better link strength. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index ce0b0c2..1e2fea3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -3994,13 +3994,13 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy, } else { misc1_val |= 0x9; - tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) | - (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) | - (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET)); + tap_val = ((0x0f << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) | + (0x2b << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) | + (0x02 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET)); tx_driver_val = - ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | + ((0x03 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) | - (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)); + (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)); } bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val); -- cgit v0.10.2 From 9379c9be4b20d5cb7bde577f402b749cd7d3caa2 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:28:58 +0000 Subject: bnx2x: Restore 1G LED on BCM57712+BCM8727 designs. Fix no-LED problem when link speed is 1G on BCM57712 + BCM8727 designs, by removing a logic error checking for a different PHY. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 1e2fea3..1438da8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -6216,12 +6216,14 @@ int bnx2x_set_led(struct link_params *params, tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); if (params->phy[EXT_PHY1].type == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) - EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp & 0xfff1); - else { - EMAC_WR(bp, EMAC_REG_EMAC_LED, - (tmp | EMAC_LED_OVERRIDE)); - } + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) + tmp &= ~(EMAC_LED_1000MB_OVERRIDE | + EMAC_LED_100MB_OVERRIDE | + EMAC_LED_10MB_OVERRIDE); + else + tmp |= EMAC_LED_OVERRIDE; + + EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp); break; case LED_MODE_OPER: @@ -6276,10 +6278,15 @@ int bnx2x_set_led(struct link_params *params, hw_led_mode); } else if ((params->phy[EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) && - (mode != LED_MODE_OPER)) { + (mode == LED_MODE_ON)) { REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); - EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp | 0x3); + EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp | + EMAC_LED_OVERRIDE | EMAC_LED_1000MB_OVERRIDE); + /* Break here; otherwise, it'll disable the + * intended override. + */ + break; } else REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode); @@ -6294,13 +6301,9 @@ int bnx2x_set_led(struct link_params *params, LED_BLINK_RATE_VAL_E1X_E2); REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 + port*4, 1); - if ((params->phy[EXT_PHY1].type != - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) && - (mode != LED_MODE_OPER)) { - tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); - EMAC_WR(bp, EMAC_REG_EMAC_LED, - (tmp & (~EMAC_LED_OVERRIDE))); - } + tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); + EMAC_WR(bp, EMAC_REG_EMAC_LED, + (tmp & (~EMAC_LED_OVERRIDE))); if (CHIP_IS_E1(bp) && ((speed == SPEED_2500) || -- cgit v0.10.2 From 59a2e53b826103be8c22d9820355320b749b38ef Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:28:59 +0000 Subject: bnx2x: Fix link issue for BCM8727 boards. This patch fixes a link problem on BCM57712 + BCM8727 designs in which the TX laser is controller by GPIO, after 1.60.xx drivers were previously loaded. On these designs the TX_LASER is enabled by logic AND between the PHY (through MDIO), and the GPIO. When an old driver is used, it disables the MDIO part, hence the GPIO control had no affect de facto. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 1438da8..732b4c8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -8089,7 +8089,9 @@ static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy, netdev_err(bp->dev, "Warning: Unqualified SFP+ module detected," " Port %d from %s part number %s\n", params->port, vendor_name, vendor_pn); - phy->flags |= FLAGS_SFP_NOT_APPROVED; + if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) != + PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG) + phy->flags |= FLAGS_SFP_NOT_APPROVED; return -EINVAL; } @@ -9149,6 +9151,12 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy, tmp2 &= 0xFFEF; bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2); + bnx2x_cl45_read(bp, phy, + MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, + &tmp2); + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, + (tmp2 & 0x7fff)); } return 0; @@ -9329,12 +9337,11 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, ((1<<5) | (1<<2))); } - DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n"); - bnx2x_8727_specific_func(phy, params, ENABLE_TX); - /* If transmitter is disabled, ignore false link up indication */ - bnx2x_cl45_read(bp, phy, - MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1); - if (val1 & (1<<15)) { + + if (!(phy->flags & FLAGS_SFP_NOT_APPROVED)) { + DP(NETIF_MSG_LINK, "Enabling 8727 TX laser\n"); + bnx2x_sfp_set_transmitter(params, phy, 1); + } else { DP(NETIF_MSG_LINK, "Tx is disabled\n"); return 0; } -- cgit v0.10.2 From 8267bbb01f005fa8d0c8d046ecc24ae0b52e4d70 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:29:00 +0000 Subject: bnx2x: Fix BCM84833 PHY FW version presentation Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 732b4c8..b576a3a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -9435,8 +9435,7 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy, if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1); - bnx2x_save_spirom_version(bp, port, - ((fw_ver1 & 0xf000)>>5) | (fw_ver1 & 0x7f), + bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff, phy->ver_addr); } else { /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */ -- cgit v0.10.2 From 99bf7f34368aac9b54dfa8801ae490a2326704f9 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:29:01 +0000 Subject: bnx2x: Clear BCM84833 LED after fan failure Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index b576a3a..ce95ef7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -9858,6 +9858,15 @@ static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy, other_shmem_base_addr)); u32 shmem_base_path[2]; + + /* Work around for 84833 LED failure inside RESET status */ + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_LEGACY_MII_CTRL, + MDIO_AN_REG_8481_MII_CTRL_FORCE_1G); + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_8481_1G_100T_EXT_CTRL, + MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF); + shmem_base_path[0] = params->shmem_base; shmem_base_path[1] = other_shmem_base_addr; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index 1ea2b95..c25803b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -6821,10 +6821,13 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_AN_REG_8481_10GBASE_T_AN_CTRL 0x0020 #define MDIO_AN_REG_8481_LEGACY_MII_CTRL 0xffe0 +#define MDIO_AN_REG_8481_MII_CTRL_FORCE_1G 0x40 #define MDIO_AN_REG_8481_LEGACY_MII_STATUS 0xffe1 #define MDIO_AN_REG_8481_LEGACY_AN_ADV 0xffe4 #define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION 0xffe6 #define MDIO_AN_REG_8481_1000T_CTRL 0xffe9 +#define MDIO_AN_REG_8481_1G_100T_EXT_CTRL 0xfff0 +#define MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF 0x0008 #define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW 0xfff5 #define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS 0xfff7 #define MDIO_AN_REG_8481_AUX_CTRL 0xfff8 -- cgit v0.10.2 From f93fb01628c00d1f26e8b45d2f10b8feb650dd4b Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:29:02 +0000 Subject: bnx2x: Fix BCM57711+BCM84823 link issue Fix a link problem on the second port of BCM57711 + BCM84823 boards due to incorrect macro usage. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index ce95ef7..7e41682 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -10177,7 +10177,7 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy, u8 port; u16 val16; - if (!(CHIP_IS_E1(bp))) + if (!(CHIP_IS_E1x(bp))) port = BP_PATH(bp); else port = params->port; @@ -10204,7 +10204,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, u16 val; u8 port; - if (!(CHIP_IS_E1(bp))) + if (!(CHIP_IS_E1x(bp))) port = BP_PATH(bp); else port = params->port; -- cgit v0.10.2 From ca7b91bbd1f150216e6354cc20818aa993f331f2 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 4 Apr 2012 01:40:02 +0000 Subject: bnx2x: Clear MDC/MDIO warning message This patch clears a warning message of "MDC/MDIO access timeout" which may appear when interface is loaded due to missing clock setting before resetting the LED, and starting periodic function too early. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 44556b7..4b05481 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1874,7 +1874,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) * bnx2x_periodic_task(). */ smp_mb(); - queue_delayed_work(bnx2x_wq, &bp->period_task, 0); } else bp->port.pmf = 0; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 7e41682..ad95324 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -12205,10 +12205,10 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, * Hold it as vars low */ /* clear link led */ + bnx2x_set_mdio_clk(bp, params->chip_id, port); bnx2x_set_led(params, vars, LED_MODE_OFF, 0); if (reset_ext_phy) { - bnx2x_set_mdio_clk(bp, params->chip_id, port); for (phy_index = EXT_PHY1; phy_index < params->num_phys; phy_index++) { if (params->phy[phy_index].link_reset) { -- cgit v0.10.2 From 03f2eecdfc8aadae395ac593c099006390c8085c Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 3 Apr 2012 22:13:01 +0000 Subject: stmmac: re-add IFF_UNICAST_FLT for dwmac1000 In commit (bfab27a stmmac: add the experimental PCI support) the IFF_UNICAST_FLT flag has been removed from the stmmac_mac_device_setup() function. This patch re-adds the flag. Signed-off-by: Marc Kleine-Budde Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e85ffbd..48d56da 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1737,10 +1737,12 @@ static int stmmac_hw_init(struct stmmac_priv *priv) struct mac_device_info *mac; /* Identify the MAC HW device */ - if (priv->plat->has_gmac) + if (priv->plat->has_gmac) { + priv->dev->priv_flags |= IFF_UNICAST_FLT; mac = dwmac1000_setup(priv->ioaddr); - else + } else { mac = dwmac100_setup(priv->ioaddr); + } if (!mac) return -ENOMEM; -- cgit v0.10.2 From 117980c4c994b6fe58e873fe803c9bcdcb4337a3 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 4 Apr 2012 09:40:40 +0000 Subject: mlx4: allocate just enough pages instead of always 4 pages The driver uses a 2-order allocation, which is too much on architectures like ppc64, which has a 64KiB page. This particular allocation is used for large packet fragments that may have a size of 512, 1024, 4096 or fill the whole allocation. So, a minimum size of 16384 is good enough and will be the same size that is used in architectures of 4KiB sized pages. This will avoid allocation failures that we see when the system is under stress, but still has plenty of memory, like the one below. This will also allow us to set the interface MTU to higher values like 9000, which was not possible on ppc64 without this patch. Node 1 DMA: 737*64kB 37*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB 0*16384kB = 51904kB 83137 total pagecache pages 0 pages in swap cache Swap cache stats: add 0, delete 0, find 0/0 Free swap = 10420096kB Total swap = 10420096kB 107776 pages RAM 1184 pages reserved 147343 pages shared 28152 pages non-shared netstat: page allocation failure. order:2, mode:0x4020 Call Trace: [c0000001a4fa3770] [c000000000012f04] .show_stack+0x74/0x1c0 (unreliable) [c0000001a4fa3820] [c00000000016af38] .__alloc_pages_nodemask+0x618/0x930 [c0000001a4fa39a0] [c0000000001a71a0] .alloc_pages_current+0xb0/0x170 [c0000001a4fa3a40] [d00000000dcc3e00] .mlx4_en_alloc_frag+0x200/0x240 [mlx4_en] [c0000001a4fa3b10] [d00000000dcc3f8c] .mlx4_en_complete_rx_desc+0x14c/0x250 [mlx4_en] [c0000001a4fa3be0] [d00000000dcc4eec] .mlx4_en_process_rx_cq+0x62c/0x850 [mlx4_en] [c0000001a4fa3d20] [d00000000dcc5150] .mlx4_en_poll_rx_cq+0x40/0x90 [mlx4_en] [c0000001a4fa3dc0] [c0000000004e2bb8] .net_rx_action+0x178/0x450 [c0000001a4fa3eb0] [c00000000009c9b8] .__do_softirq+0x118/0x290 [c0000001a4fa3f90] [c000000000031df8] .call_do_softirq+0x14/0x24 [c000000184c3b520] [c00000000000e700] .do_softirq+0xf0/0x110 [c000000184c3b5c0] [c00000000009c6d4] .irq_exit+0xb4/0xc0 [c000000184c3b640] [c00000000000e964] .do_IRQ+0x144/0x230 Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Kleber Sacilotto de Souza Tested-by: Kleber Sacilotto de Souza Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 9e2b911..d69fee4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -83,8 +83,9 @@ #define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ) -#define MLX4_EN_ALLOC_ORDER 2 -#define MLX4_EN_ALLOC_SIZE (PAGE_SIZE << MLX4_EN_ALLOC_ORDER) +/* Use the maximum between 16384 and a single page */ +#define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(16384) +#define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE) #define MLX4_EN_MAX_LRO_DESCRIPTORS 32 -- cgit v0.10.2 From 78d50217baf36093ab320f95bae0d6452daec85c Mon Sep 17 00:00:00 2001 From: "RongQing.Li" Date: Wed, 4 Apr 2012 16:47:04 +0000 Subject: ipv6: fix array index in ip6_mc_add_src() Convert array index from the loop bound to the loop index. And remove the void type conversion to ip6_mc_del1_src() return code, seem it is unnecessary, since ip6_mc_del1_src() does not use __must_check similar attribute, no compiler will report the warning when it is removed. v2: enrich the commit header Signed-off-by: RongQing.Li Signed-off-by: David S. Miller diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 16c33e3..b2869ca 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2044,7 +2044,7 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, if (!delta) pmc->mca_sfcount[sfmode]--; for (j=0; jmca_sfcount[MCAST_EXCLUDE] != 0)) { struct ip6_sf_list *psf; -- cgit v0.10.2 From 620f6e8e855d6d447688a5f67a4e176944a084e8 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 4 Apr 2012 11:40:19 -0700 Subject: sysctl: fix write access to dmesg_restrict/kptr_restrict Commit bfdc0b4 adds code to restrict access to dmesg_restrict, however, it incorrectly alters kptr_restrict rather than dmesg_restrict. The original patch from Richard Weinberger (https://lkml.org/lkml/2011/3/14/362) alters dmesg_restrict as expected, and so the patch seems to have been misapplied. This adds the CAP_SYS_ADMIN check to both dmesg_restrict and kptr_restrict, since both are sensitive. Reported-by: Phillip Lougher Signed-off-by: Kees Cook Acked-by: Serge Hallyn Acked-by: Richard Weinberger Cc: stable@vger.kernel.org Signed-off-by: James Morris diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 52b3a06..4ab1187 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -170,7 +170,7 @@ static int proc_taint(struct ctl_table *table, int write, #endif #ifdef CONFIG_PRINTK -static int proc_dmesg_restrict(struct ctl_table *table, int write, +static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); #endif @@ -703,7 +703,7 @@ static struct ctl_table kern_table[] = { .data = &dmesg_restrict, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax_sysadmin, .extra1 = &zero, .extra2 = &one, }, @@ -712,7 +712,7 @@ static struct ctl_table kern_table[] = { .data = &kptr_restrict, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dmesg_restrict, + .proc_handler = proc_dointvec_minmax_sysadmin, .extra1 = &zero, .extra2 = &two, }, @@ -1943,7 +1943,7 @@ static int proc_taint(struct ctl_table *table, int write, } #ifdef CONFIG_PRINTK -static int proc_dmesg_restrict(struct ctl_table *table, int write, +static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { if (write && !capable(CAP_SYS_ADMIN)) -- cgit v0.10.2 From 2a1cc1445a51e3a81c10d294586756cdb9174469 Mon Sep 17 00:00:00 2001 From: "Govindraj.R" Date: Thu, 5 Apr 2012 02:59:32 -0600 Subject: ARM: OMAP2+: omap_hwmod: Allow io_ring wakeup configuration for all modules Some modules doesn't have SYSC_HAS_ENAWAKEUP bit available (ex: usb host uhh module) in absence of this flag omap_hwmod_enable/disable_wakeup avoids configuring pad mux wakeup capability. Configure sysc if SYSC_HAS_ENAWAKEUP is available and for other cases try enabling/disabling wakeup from mux_pad pins. Cc: Paul Walmsley Cc: Kevin Hilman Cc: Rajendra Nayak Signed-off-by: Govindraj.R [paul@pwsan.com: updated function kerneldoc documentation] Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index eba6cd3..5a68010 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2463,26 +2463,28 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh, * @oh: struct omap_hwmod * * * Sets the module OCP socket ENAWAKEUP bit to allow the module to - * send wakeups to the PRCM. Eventually this should sets PRCM wakeup - * registers to cause the PRCM to receive wakeup events from the - * module. Does not set any wakeup routing registers beyond this - * point - if the module is to wake up any other module or subsystem, - * that must be set separately. Called by omap_device code. Returns - * -EINVAL on error or 0 upon success. + * send wakeups to the PRCM, and enable I/O ring wakeup events for + * this IP block if it has dynamic mux entries. Eventually this + * should set PRCM wakeup registers to cause the PRCM to receive + * wakeup events from the module. Does not set any wakeup routing + * registers beyond this point - if the module is to wake up any other + * module or subsystem, that must be set separately. Called by + * omap_device code. Returns -EINVAL on error or 0 upon success. */ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) { unsigned long flags; u32 v; - if (!oh->class->sysc || - !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) - return -EINVAL; - spin_lock_irqsave(&oh->_lock, flags); - v = oh->_sysc_cache; - _enable_wakeup(oh, &v); - _write_sysconfig(v, oh); + + if (oh->class->sysc && + (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) { + v = oh->_sysc_cache; + _enable_wakeup(oh, &v); + _write_sysconfig(v, oh); + } + _set_idle_ioring_wakeup(oh, true); spin_unlock_irqrestore(&oh->_lock, flags); @@ -2494,26 +2496,28 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) * @oh: struct omap_hwmod * * * Clears the module OCP socket ENAWAKEUP bit to prevent the module - * from sending wakeups to the PRCM. Eventually this should clear - * PRCM wakeup registers to cause the PRCM to ignore wakeup events - * from the module. Does not set any wakeup routing registers beyond - * this point - if the module is to wake up any other module or - * subsystem, that must be set separately. Called by omap_device - * code. Returns -EINVAL on error or 0 upon success. + * from sending wakeups to the PRCM, and disable I/O ring wakeup + * events for this IP block if it has dynamic mux entries. Eventually + * this should clear PRCM wakeup registers to cause the PRCM to ignore + * wakeup events from the module. Does not set any wakeup routing + * registers beyond this point - if the module is to wake up any other + * module or subsystem, that must be set separately. Called by + * omap_device code. Returns -EINVAL on error or 0 upon success. */ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh) { unsigned long flags; u32 v; - if (!oh->class->sysc || - !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) - return -EINVAL; - spin_lock_irqsave(&oh->_lock, flags); - v = oh->_sysc_cache; - _disable_wakeup(oh, &v); - _write_sysconfig(v, oh); + + if (oh->class->sysc && + (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) { + v = oh->_sysc_cache; + _disable_wakeup(oh, &v); + _write_sysconfig(v, oh); + } + _set_idle_ioring_wakeup(oh, false); spin_unlock_irqrestore(&oh->_lock, flags); -- cgit v0.10.2 From 2800852a079504f35f88e44faf5c9c96318c0cca Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 13 Mar 2012 22:55:23 +0530 Subject: ARM: OMAP2+: hwmod: Restore sysc after a reset After a softreset, make sure the sysc settings are correctly restored. Reported-by: Anand Gadiyar Signed-off-by: Rajendra Nayak Cc: Benoit Cousson Cc: Paul Walmsley Cc: Shubhrajyoti D [paul@pwsan.com: combined post-reset SYSCONFIG reload code into the _reset() function to avoid duplication and future mistakes] Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 5a68010..d32c1ce 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1477,6 +1477,11 @@ static int _reset(struct omap_hwmod *oh) ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh); + if (oh->class->sysc) { + _update_sysc_cache(oh); + _enable_sysc(oh); + } + return ret; } @@ -1786,20 +1791,9 @@ static int _setup(struct omap_hwmod *oh, void *data) return 0; } - if (!(oh->flags & HWMOD_INIT_NO_RESET)) { + if (!(oh->flags & HWMOD_INIT_NO_RESET)) _reset(oh); - /* - * OCP_SYSCONFIG bits need to be reprogrammed after a softreset. - * The _enable() function should be split to - * avoid the rewrite of the OCP_SYSCONFIG register. - */ - if (oh->class->sysc) { - _update_sysc_cache(oh); - _enable_sysc(oh); - } - } - postsetup_state = oh->_postsetup_state; if (postsetup_state == _HWMOD_STATE_UNKNOWN) postsetup_state = _HWMOD_STATE_ENABLED; -- cgit v0.10.2 From f9a2f9c3fa76eec55928e8e06f3094c8f01df7cb Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 13 Mar 2012 22:55:24 +0530 Subject: ARM: OMAP2+: hwmod: Make omap_hwmod_softreset wait for reset status omap_hwmod_softreset() does not seem to wait for reset status after doing a softreset. Make it use _ocp_softreset() instead which does this correctly. Signed-off-by: Rajendra Nayak Cc: Benoit Cousson Cc: Paul Walmsley Cc: Anand Gadiyar Cc: Shubhrajyoti D Signed-off-by: Paul Walmsley diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index d32c1ce..72903d4 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1901,20 +1901,10 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs) */ int omap_hwmod_softreset(struct omap_hwmod *oh) { - u32 v; - int ret; - - if (!oh || !(oh->_sysc_cache)) + if (!oh) return -EINVAL; - v = oh->_sysc_cache; - ret = _set_softreset(oh, &v); - if (ret) - goto error; - _write_sysconfig(v, oh); - -error: - return ret; + return _ocp_softreset(oh); } /** -- cgit v0.10.2 From 4ce107ccd714e54f7076aba585295421d30ad7f7 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Fri, 17 Feb 2012 16:56:01 +0530 Subject: ARM: OMAP2+: hwmod: Fix wrong SYSC_TYPE1_XXX_MASK bit definitions In the SYSC_TYPE1_XXX_MASK configuration, SYSC_XXX_SHIFT macro is used which is not defined anywhere in the kernel. Until now the build was going through successfully, since it is not being used anywhere in kernel. This bug got introduced by the commit 358f0e630d5409ab3837b86db3595560eae773b6 ("OMAP3: hwmod: support to specify the offset position of various SYSCONFIG register bits.") Signed-off-by: Vaibhav Hiremath Acked-by: Benoit Cousson Signed-off-by: Paul Walmsley diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 9e8e63d..8070145 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -47,17 +47,17 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; * with the original PRCM protocol defined for OMAP2420 */ #define SYSC_TYPE1_MIDLEMODE_SHIFT 12 -#define SYSC_TYPE1_MIDLEMODE_MASK (0x3 << SYSC_MIDLEMODE_SHIFT) +#define SYSC_TYPE1_MIDLEMODE_MASK (0x3 << SYSC_TYPE1_MIDLEMODE_SHIFT) #define SYSC_TYPE1_CLOCKACTIVITY_SHIFT 8 -#define SYSC_TYPE1_CLOCKACTIVITY_MASK (0x3 << SYSC_CLOCKACTIVITY_SHIFT) +#define SYSC_TYPE1_CLOCKACTIVITY_MASK (0x3 << SYSC_TYPE1_CLOCKACTIVITY_SHIFT) #define SYSC_TYPE1_SIDLEMODE_SHIFT 3 -#define SYSC_TYPE1_SIDLEMODE_MASK (0x3 << SYSC_SIDLEMODE_SHIFT) +#define SYSC_TYPE1_SIDLEMODE_MASK (0x3 << SYSC_TYPE1_SIDLEMODE_SHIFT) #define SYSC_TYPE1_ENAWAKEUP_SHIFT 2 -#define SYSC_TYPE1_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT) +#define SYSC_TYPE1_ENAWAKEUP_MASK (1 << SYSC_TYPE1_ENAWAKEUP_SHIFT) #define SYSC_TYPE1_SOFTRESET_SHIFT 1 -#define SYSC_TYPE1_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT) +#define SYSC_TYPE1_SOFTRESET_MASK (1 << SYSC_TYPE1_SOFTRESET_SHIFT) #define SYSC_TYPE1_AUTOIDLE_SHIFT 0 -#define SYSC_TYPE1_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT) +#define SYSC_TYPE1_AUTOIDLE_MASK (1 << SYSC_TYPE1_AUTOIDLE_SHIFT) /* * OCP SYSCONFIG bit shifts/masks TYPE2. These are for IPs compliant -- cgit v0.10.2 From e1b1994e165652d89986e95faa9cf22331375b3a Mon Sep 17 00:00:00 2001 From: Il Han Date: Thu, 5 Apr 2012 07:59:36 -0700 Subject: ARM: EXYNOS: fix ISO C90 warning ISO C90 forbids mixed declarations and code. Fix it. Signed-off-by: Il Han Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index e6cc50e..8614aab 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -583,10 +583,11 @@ core_initcall(exynos_core_init); #ifdef CONFIG_CACHE_L2X0 static int __init exynos4_l2x0_cache_init(void) { + int ret; + if (soc_is_exynos5250()) return 0; - int ret; ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); if (!ret) { l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs); -- cgit v0.10.2 From f011fd164801cd8dd151268ae7adbadef0e3e301 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 5 Apr 2012 08:01:13 -0700 Subject: ARM: EXYNOS: Fix compiler warning in dma.c file Fixes the following warning: warning: 'dma_dmamask' defined but not used [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c index 3983abe..69aaa45 100644 --- a/arch/arm/mach-exynos/dma.c +++ b/arch/arm/mach-exynos/dma.c @@ -35,8 +35,6 @@ #include #include -static u64 dma_dmamask = DMA_BIT_MASK(32); - static u8 exynos4210_pdma0_peri[] = { DMACH_PCM0_RX, DMACH_PCM0_TX, -- cgit v0.10.2 From fea5295324ce7ce6ccfe0909cc6740a2d34aa5a3 Mon Sep 17 00:00:00 2001 From: Sasikantha babu Date: Wed, 21 Mar 2012 18:49:00 +0530 Subject: KVM: PMU: Fix integer constant is too large warning in kvm_pmu_set_msr() Signed-off-by: Sasikantha babu Signed-off-by: Avi Kivity diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index a73f0c1..173df38 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -369,7 +369,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data) case MSR_CORE_PERF_FIXED_CTR_CTRL: if (pmu->fixed_ctr_ctrl == data) return 0; - if (!(data & 0xfffffffffffff444)) { + if (!(data & 0xfffffffffffff444ull)) { reprogram_fixed_counters(pmu, data); return 0; } -- cgit v0.10.2 From 7a4f5ad051e02139a9f1c0f7f4b1acb88915852b Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 27 Mar 2012 19:47:26 -0300 Subject: KVM: VMX: vmx_set_cr0 expects kvm->srcu locked vmx_set_cr0 is called from vcpu run context, therefore it expects kvm->srcu to be held (for setting up the real-mode TSS). Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 280751c..ad85adf 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3906,7 +3906,9 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET; + vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); vmx_set_cr0(&vmx->vcpu, kvm_read_cr0(vcpu)); /* enter rmode */ + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); vmx_set_cr4(&vmx->vcpu, 0); vmx_set_efer(&vmx->vcpu, 0); vmx_fpu_activate(&vmx->vcpu); -- cgit v0.10.2 From e08759215b7dcb7111e94f0f96918dd98e86ca6b Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Wed, 4 Apr 2012 15:30:33 +0300 Subject: KVM: Resolve RCU vs. async page fault problem "Page ready" async PF can kick vcpu out of idle state much like IRQ. We need to tell RCU about this. Reported-by: Sasha Levin Signed-off-by: Gleb Natapov Reviewed-by: Paul E. McKenney Signed-off-by: Avi Kivity diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 694d801..b8ba6e4 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -38,6 +38,7 @@ #include #include #include +#include static int kvmapf = 1; @@ -253,7 +254,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) kvm_async_pf_task_wait((u32)read_cr2()); break; case KVM_PV_REASON_PAGE_READY: + rcu_irq_enter(); + exit_idle(); kvm_async_pf_task_wake((u32)read_cr2()); + rcu_irq_exit(); break; } } -- cgit v0.10.2 From 54f70077768e9aba37d9c5030b43497b6d5084fb Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Tue, 3 Apr 2012 09:37:28 -0700 Subject: ACPI processor: Use safe_halt() rather than halt() in acpi_idle_play_dead() ACPI code is shared by arch/x86 and arch/ia64. ia64 doesn't provide a plain "halt()" function. Use safe_halt() instead. Signed-off-by: Tony Luck Tested-by: Boris Ostrovsky Signed-off-by: Len Brown diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 6b1d32a..784f9a7 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -786,7 +786,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) while (1) { if (cx->entry_method == ACPI_CSTATE_HALT) - halt(); + safe_halt(); else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) { inb(cx->address); /* See comment in acpi_idle_do_entry() */ -- cgit v0.10.2 From 1ac02d795889d1828a66d4b3a3fd66492d1d7cf2 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 4 Apr 2012 17:48:04 -0500 Subject: ARM: fix __io macro for PCMCIA With commit c334bc1 (ARM: make mach/io.h include optional), PCMCIA was broken. PCMCIA depends on __io() returning a valid i/o address, and most ARM platforms require IO_SPACE_LIMIT be set to 0xffffffff for PCMCIA. This needs a better fix with a fixed i/o address mapping, but for now we just restore things to the previous behavior. This fixes at91, omap1, pxa and sa11xx. pxa needs io.h if PCI is enabled, but PCMCIA is not. sa11xx already has IO_SPACE_LIMIT set to 0xffffffff, so it doesn't need an io.h. Signed-off-by: Rob Herring Cc: Joachim Eastwood Cc: Russell King Cc: Andrew Victor Cc: Nicolas Ferre Cc: Jean-Christophe Plagniol-Villard Tested-by: Paul Parsons (pxa270) Acked-by: Tony Lindgren Signed-off-by: Olof Johansson diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9318084..cf006d4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -338,6 +338,7 @@ config ARCH_AT91 select HAVE_CLK select CLKDEV_LOOKUP select IRQ_DOMAIN + select NEED_MACH_IO_H if PCCARD help This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 processors. diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index df0ac0b..9af5563 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -119,7 +119,7 @@ static inline void __iomem *__typesafe_io(unsigned long addr) #ifdef CONFIG_NEED_MACH_IO_H #include #else -#define __io(a) ({ (void)(a); __typesafe_io(0); }) +#define __io(a) __typesafe_io((a) & IO_SPACE_LIMIT) #endif /* diff --git a/arch/arm/mach-at91/include/mach/io.h b/arch/arm/mach-at91/include/mach/io.h new file mode 100644 index 0000000..2d9ca04 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/io.h @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-at91/include/mach/io.h + * + * Copyright (C) 2003 SAN People + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_IO_H +#define __ASM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xFFFFFFFF +#define __io(a) __typesafe_io(a) + +#endif diff --git a/arch/arm/mach-omap1/include/mach/io.h b/arch/arm/mach-omap1/include/mach/io.h new file mode 100644 index 0000000..ce4f800 --- /dev/null +++ b/arch/arm/mach-omap1/include/mach/io.h @@ -0,0 +1,45 @@ +/* + * arch/arm/mach-omap1/include/mach/io.h + * + * IO definitions for TI OMAP processors and boards + * + * Copied from arch/arm/mach-sa1100/include/mach/io.h + * Copyright (C) 1997-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Modifications: + * 06-12-1997 RMK Created. + * 07-04-1999 RMK Major cleanup + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +/* + * We don't actually have real ISA nor PCI buses, but there is so many + * drivers out there that might just work if we fake them... + */ +#define __io(a) __typesafe_io(a) + +#endif diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 109ccd2..fe2d1f8 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -113,6 +113,7 @@ config MACH_ARMCORE select IWMMXT select PXA25x select MIGHT_HAVE_PCI + select NEED_MACH_IO_H if PCI config MACH_EM_X270 bool "CompuLab EM-x270 platform" diff --git a/arch/arm/mach-pxa/include/mach/io.h b/arch/arm/mach-pxa/include/mach/io.h new file mode 100644 index 0000000..cd78b7f --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/io.h @@ -0,0 +1,17 @@ +/* + * arch/arm/mach-pxa/include/mach/io.h + * + * Copied from asm/arch/sa1100/io.h + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +/* + * We don't actually have real ISA nor PCI buses, but there is so many + * drivers out there that might just work if we fake them... + */ +#define __io(a) __typesafe_io(a) + +#endif diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index ce1e9b9..ad95c7a 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -17,6 +17,7 @@ config ARCH_OMAP1 select IRQ_DOMAIN select HAVE_IDE select NEED_MACH_MEMORY_H + select NEED_MACH_IO_H if PCCARD help "Systems based on omap7xx, omap15xx or omap16xx" -- cgit v0.10.2 From 99663be772c827b8f5f594fe87eb4807be1994e5 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Thu, 5 Apr 2012 14:25:04 -0700 Subject: proc: fix mount -t proc -o AAA The proc_parse_options() call from proc_mount() runs only once at boot time. So on any later mount attempt, any mount options are ignored because ->s_root is already initialized. As a consequence, "mount -o " will ignore the options. The only way to change mount options is "mount -o remount,". To fix this, parse the mount options unconditionally. Signed-off-by: Vasiliy Kulikov Reported-by: Arkadiusz Miskiewicz Tested-by: Arkadiusz Miskiewicz Cc: Alexey Dobriyan Cc: Al Viro Cc: Valdis Kletnieks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/root.c b/fs/proc/root.c index 46a15d8..eed44bf 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -115,12 +115,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, if (IS_ERR(sb)) return ERR_CAST(sb); + if (!proc_parse_options(options, ns)) { + deactivate_locked_super(sb); + return ERR_PTR(-EINVAL); + } + if (!sb->s_root) { sb->s_flags = flags; - if (!proc_parse_options(options, ns)) { - deactivate_locked_super(sb); - return ERR_PTR(-EINVAL); - } err = proc_fill_super(sb); if (err) { deactivate_locked_super(sb); -- cgit v0.10.2 From b82c32872db20667d6ee8e2ea1e7bdec791bdcc7 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 5 Apr 2012 14:25:05 -0700 Subject: sysrq: use SEND_SIG_FORCED instead of force_sig() Change send_sig_all() to use do_send_sig_info(SEND_SIG_FORCED) instead of force_sig(SIGKILL). With the recent changes we do not need force_ to kill the CLONE_NEWPID tasks. And this is more correct. force_sig() can race with the exiting thread, while do_send_sig_info(group => true) kill the whole process. Some more notes from Oleg Nesterov: > Just one note. This change makes no difference for sysrq_handle_kill(). > But it obviously changes the behaviour sysrq_handle_term(). I think > this is fine, if you want to really kill the task which blocks/ignores > SIGTERM you can use sysrq_handle_kill(). > > Even ignoring the reasons why force_sig() is simply wrong here, > force_sig(SIGTERM) looks strange. The task won't be killed if it has > a handler, but SIG_IGN can't help. However if it has the handler > but blocks SIGTERM temporary (this is very common) it will be killed. Also, > force_sig() can't kill the process if the main thread has already > exited. IOW, it is trivial to create the process which can't be > killed by sysrq. So, this patch fixes the issue. Suggested-by: Oleg Nesterov Acked-by: Greg Kroah-Hartman Acked-by: Oleg Nesterov Signed-off-by: Anton Vorontsov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 136e86f..05728894 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -327,7 +327,7 @@ static void send_sig_all(int sig) if (is_global_init(p)) continue; - force_sig(sig, p); + do_send_sig_info(sig, SEND_SIG_FORCED, p, true); } read_unlock(&tasklist_lock); } -- cgit v0.10.2 From 703bf2d122c95412a30f72658c53ad6292867b0b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 5 Apr 2012 14:25:06 -0700 Subject: fs/xattr.c: suppress page allocation failure warnings from sys_listxattr() This size is user controllable, up to a maximum of XATTR_LIST_MAX (64k). So it's trivial for someone to trigger a stream of order:4 page allocation errors. Signed-off-by: Dave Jones Cc: Al Viro Cc: Dave Chinner Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/xattr.c b/fs/xattr.c index d6dfd24..a14d842 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -496,7 +496,7 @@ listxattr(struct dentry *d, char __user *list, size_t size) if (size) { if (size > XATTR_LIST_MAX) size = XATTR_LIST_MAX; - klist = kmalloc(size, GFP_KERNEL); + klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL); if (!klist) return -ENOMEM; } -- cgit v0.10.2 From 0d08d7b7e13b5060181b11ecdde82d8fda322123 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 5 Apr 2012 14:25:07 -0700 Subject: fs/xattr.c:listxattr(): fall back to vmalloc() if kmalloc() failed This allocation can be as large as 64k. As David points out, "falling back to vmalloc here is much better solution than failing to retreive the attribute - it will work no matter how fragmented memory gets. That means we don't get incomplete backups occurring after days or months of uptime and successful backups". Cc: Dave Chinner Cc: Dave Jones Cc: David Rientjes Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/xattr.c b/fs/xattr.c index a14d842..d14afba 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -19,8 +19,9 @@ #include #include #include -#include +#include +#include /* * Check permissions for extended attribute access. This is a bit complicated @@ -492,13 +493,18 @@ listxattr(struct dentry *d, char __user *list, size_t size) { ssize_t error; char *klist = NULL; + char *vlist = NULL; /* If non-NULL, we used vmalloc() */ if (size) { if (size > XATTR_LIST_MAX) size = XATTR_LIST_MAX; klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL); - if (!klist) - return -ENOMEM; + if (!klist) { + vlist = vmalloc(size); + if (!vlist) + return -ENOMEM; + klist = vlist; + } } error = vfs_listxattr(d, klist, size); @@ -510,7 +516,10 @@ listxattr(struct dentry *d, char __user *list, size_t size) than XATTR_LIST_MAX bytes. Not possible. */ error = -E2BIG; } - kfree(klist); + if (vlist) + vfree(vlist); + else + kfree(klist); return error; } -- cgit v0.10.2 From 44c824982fd37a578da23cc90885e9690a6a3f0e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 5 Apr 2012 14:25:07 -0700 Subject: fs/xattr.c:setxattr(): improve handling of allocation failures This allocation can be as large as 64k. - Add __GFP_NOWARN so the a falied kmalloc() is silent - Fall back to vmalloc() if the kmalloc() failed Cc: Dave Chinner Cc: Dave Jones Cc: David Rientjes Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/xattr.c b/fs/xattr.c index d14afba..3c8c1cc 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -321,6 +321,7 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value, { int error; void *kvalue = NULL; + void *vvalue = NULL; /* If non-NULL, we used vmalloc() */ char kname[XATTR_NAME_MAX + 1]; if (flags & ~(XATTR_CREATE|XATTR_REPLACE)) @@ -335,13 +336,25 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value, if (size) { if (size > XATTR_SIZE_MAX) return -E2BIG; - kvalue = memdup_user(value, size); - if (IS_ERR(kvalue)) - return PTR_ERR(kvalue); + kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); + if (!kvalue) { + vvalue = vmalloc(size); + if (!vvalue) + return -ENOMEM; + kvalue = vvalue; + } + if (copy_from_user(kvalue, value, size)) { + error = -EFAULT; + goto out; + } } error = vfs_setxattr(d, kname, kvalue, size, flags); - kfree(kvalue); +out: + if (vvalue) + vfree(vvalue); + else + kfree(kvalue); return error; } -- cgit v0.10.2 From fd835d1f2d4826a19530bc045579ffda5775b8f7 Mon Sep 17 00:00:00 2001 From: "Jett.Zhou" Date: Thu, 5 Apr 2012 14:25:08 -0700 Subject: drivers/rtc/rtc-88pm860x.c: fix rtc irq enable callback According to 88pm860x spec, rtc alarm irq enable control is bit3 for RTC_ALARM_EN, so fix it. Signed-off-by: Jett.Zhou Cc: Axel Lin Cc: Haojian Zhuang Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index f04761e..8b72b4c 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -72,9 +72,9 @@ static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) struct pm860x_rtc_info *info = dev_get_drvdata(dev); if (enabled) - pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM); + pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, ALARM_EN); else - pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0); + pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0); return 0; } -- cgit v0.10.2 From 7563ec4c211ba59c2331dc6b94a068250345c387 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Thu, 5 Apr 2012 14:25:09 -0700 Subject: hugetlbfs: remove unregister_filesystem() when initializing module It was introduced by d1d5e05ffdc1 ("hugetlbfs: return error code when initializing module") but as Al pointed out, is a bad idea. Quoted comments from Al: "Note that unregister_filesystem() in module init is *always* wrong; it's not an issue here (it's done too early to care about and realistically the box is not going anywhere - it'll panic when attempt to exec /sbin/init fails, if not earlier), but it's a damn bad example. Consider a normal fs module. Somebody loads it and in parallel with that we get a mount attempt on that fs type. It comes between register and failure exits that causes unregister; at that point we are screwed since grabbing a reference to module as done by mount is enough to prevent exit, but not to prevent the failure of init. As the result, module will get freed when init fails, mounted fs of that type be damned." So remove it. Signed-off-by: Hillf Danton Cc: David Rientjes Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index ea25174..28cf06e 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -1031,7 +1031,6 @@ static int __init init_hugetlbfs_fs(void) } error = PTR_ERR(vfsmount); - unregister_filesystem(&hugetlbfs_fs_type); out: kmem_cache_destroy(hugetlbfs_inode_cachep); -- cgit v0.10.2 From 20955e891d828b2027281fe3295dae6af8e0423b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 5 Apr 2012 14:25:09 -0700 Subject: libfs: add simple_open() debugfs and a few other drivers use an open-coded version of simple_open() to pass a pointer from the file to the read/write file ops. Add support for this simple case to libfs so that we can remove the many duplicate copies of this simple function. Signed-off-by: Stephen Boyd Cc: Al Viro Cc: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/libfs.c b/fs/libfs.c index 4a0d1f0..358094f 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -264,6 +264,13 @@ Enomem: return ERR_PTR(-ENOMEM); } +int simple_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + return 0; +} + int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; @@ -984,6 +991,7 @@ EXPORT_SYMBOL(simple_dir_operations); EXPORT_SYMBOL(simple_empty); EXPORT_SYMBOL(simple_fill_super); EXPORT_SYMBOL(simple_getattr); +EXPORT_SYMBOL(simple_open); EXPORT_SYMBOL(simple_link); EXPORT_SYMBOL(simple_lookup); EXPORT_SYMBOL(simple_pin_fs); diff --git a/include/linux/fs.h b/include/linux/fs.h index c437f91..c64c31d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2502,6 +2502,7 @@ extern int dcache_readdir(struct file *, void *, filldir_t); extern int simple_setattr(struct dentry *, struct iattr *); extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int simple_statfs(struct dentry *, struct kstatfs *); +extern int simple_open(struct inode *inode, struct file *file); extern int simple_link(struct dentry *, struct inode *, struct dentry *); extern int simple_unlink(struct inode *, struct dentry *); extern int simple_rmdir(struct inode *, struct dentry *); -- cgit v0.10.2 From 9b3ae64be658a573b33d05a8dc73b08d3345fa44 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 5 Apr 2012 14:25:10 -0700 Subject: scripts/coccinelle/api/simple_open.cocci: semantic patch for simple_open() Find instances of an open-coded simple_open() and replace them with calls to simple_open(). Signed-off-by: Julia Lawall Reported-by: Stephen Boyd Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/coccinelle/api/simple_open.cocci b/scripts/coccinelle/api/simple_open.cocci new file mode 100644 index 0000000..05962f7 --- /dev/null +++ b/scripts/coccinelle/api/simple_open.cocci @@ -0,0 +1,70 @@ +/// This removes an open coded simple_open() function +/// and replaces file operations references to the function +/// with simple_open() instead. +/// +// Confidence: High +// Comments: +// Options: -no_includes -include_headers + +virtual patch +virtual report + +@ open depends on patch @ +identifier open_f != simple_open; +identifier i, f; +@@ +-int open_f(struct inode *i, struct file *f) +-{ +( +-if (i->i_private) +-f->private_data = i->i_private; +| +-f->private_data = i->i_private; +) +-return 0; +-} + +@ has_open depends on open @ +identifier fops; +identifier open.open_f; +@@ +struct file_operations fops = { +..., +-.open = open_f, ++.open = simple_open, +... +}; + +@ openr depends on report @ +identifier open_f != simple_open; +identifier i, f; +position p; +@@ +int open_f@p(struct inode *i, struct file *f) +{ +( +if (i->i_private) +f->private_data = i->i_private; +| +f->private_data = i->i_private; +) +return 0; +} + +@ has_openr depends on openr @ +identifier fops; +identifier openr.open_f; +position p; +@@ +struct file_operations fops = { +..., +.open = open_f@p, +... +}; + +@script:python@ +pf << openr.p; +ps << has_openr.p; +@@ + +coccilib.report.print_report(pf[0],"WARNING opportunity for simple_open, see also structure on line %s"%(ps[0].line)) -- cgit v0.10.2 From 234e340582901211f40d8c732afc49f0630ecf05 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 5 Apr 2012 14:25:11 -0700 Subject: simple_open: automatically convert to simple_open() Many users of debugfs copy the implementation of default_open() when they want to support a custom read/write function op. This leads to a proliferation of the default_open() implementation across the entire tree. Now that the common implementation has been consolidated into libfs we can replace all the users of this function with simple_open(). This replacement was done with the following semantic patch: @ open @ identifier open_f != simple_open; identifier i, f; @@ -int open_f(struct inode *i, struct file *f) -{ ( -if (i->i_private) -f->private_data = i->i_private; | -f->private_data = i->i_private; ) -return 0; -} @ has_open depends on open @ identifier fops; identifier open.open_f; @@ struct file_operations fops = { ... -.open = open_f, +.open = simple_open, ... }; [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: Stephen Boyd Cc: Greg Kroah-Hartman Cc: Al Viro Cc: Julia Lawall Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c index 0c56a5a..c56df9e 100644 --- a/arch/arm/mach-msm/smd_debug.c +++ b/arch/arm/mach-msm/smd_debug.c @@ -203,15 +203,9 @@ static ssize_t debug_read(struct file *file, char __user *buf, return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize); } -static int debug_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static const struct file_operations debug_ops = { .read = debug_read, - .open = debug_open, + .open = simple_open, .llseek = default_llseek, }; diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c index 90fcf62..1d5d31e 100644 --- a/arch/x86/kernel/kdebugfs.c +++ b/arch/x86/kernel/kdebugfs.c @@ -68,16 +68,9 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf, return count; } -static int setup_data_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - - return 0; -} - static const struct file_operations fops_setup_data = { .read = setup_data_read, - .open = setup_data_open, + .open = simple_open, .llseek = default_llseek, }; diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c index b258cab..7586544 100644 --- a/drivers/acpi/ec_sys.c +++ b/drivers/acpi/ec_sys.c @@ -27,12 +27,6 @@ MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may " static struct dentry *acpi_ec_debugfs_dir; -static int acpi_ec_open_io(struct inode *i, struct file *f) -{ - f->private_data = i->i_private; - return 0; -} - static ssize_t acpi_ec_read_io(struct file *f, char __user *buf, size_t count, loff_t *off) { @@ -95,7 +89,7 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf, static const struct file_operations acpi_ec_io_ops = { .owner = THIS_MODULE, - .open = acpi_ec_open_io, + .open = simple_open, .read = acpi_ec_read_io, .write = acpi_ec_write_io, .llseek = default_llseek, diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 58517a5..251eb70 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -27,12 +27,6 @@ static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size) return strlen(buf); } -static int regmap_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t regmap_name_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -57,7 +51,7 @@ static ssize_t regmap_name_read_file(struct file *file, } static const struct file_operations regmap_name_fops = { - .open = regmap_open_file, + .open = simple_open, .read = regmap_name_read_file, .llseek = default_llseek, }; @@ -174,7 +168,7 @@ static ssize_t regmap_map_write_file(struct file *file, #endif static const struct file_operations regmap_map_fops = { - .open = regmap_open_file, + .open = simple_open, .read = regmap_map_read_file, .write = regmap_map_write_file, .llseek = default_llseek, @@ -243,7 +237,7 @@ out: } static const struct file_operations regmap_access_fops = { - .open = regmap_open_file, + .open = simple_open, .read = regmap_access_read_file, .llseek = default_llseek, }; diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index 6c20bbb..428dbb7 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -45,12 +45,6 @@ struct btmrvl_debugfs_data { struct dentry *txdnldready; }; -static int btmrvl_open_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t btmrvl_hscfgcmd_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { @@ -93,7 +87,7 @@ static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_hscfgcmd_fops = { .read = btmrvl_hscfgcmd_read, .write = btmrvl_hscfgcmd_write, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -134,7 +128,7 @@ static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_psmode_fops = { .read = btmrvl_psmode_read, .write = btmrvl_psmode_write, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -180,7 +174,7 @@ static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_pscmd_fops = { .read = btmrvl_pscmd_read, .write = btmrvl_pscmd_write, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -221,7 +215,7 @@ static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_gpiogap_fops = { .read = btmrvl_gpiogap_read, .write = btmrvl_gpiogap_write, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -265,7 +259,7 @@ static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_hscmd_fops = { .read = btmrvl_hscmd_read, .write = btmrvl_hscmd_write, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -305,7 +299,7 @@ static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf, static const struct file_operations btmrvl_hsmode_fops = { .read = btmrvl_hsmode_read, .write = btmrvl_hsmode_write, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -323,7 +317,7 @@ static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_curpsmode_fops = { .read = btmrvl_curpsmode_read, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -341,7 +335,7 @@ static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf, static const struct file_operations btmrvl_psstate_fops = { .read = btmrvl_psstate_read, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -359,7 +353,7 @@ static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_hsstate_fops = { .read = btmrvl_hsstate_read, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -378,7 +372,7 @@ static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf, static const struct file_operations btmrvl_txdnldready_fops = { .read = btmrvl_txdnldready_read, - .open = btmrvl_open_generic, + .open = simple_open, .llseek = default_llseek, }; diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index b58b561..ddf86b6 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1038,12 +1038,6 @@ static struct attribute_group port_attribute_group = { .attrs = port_sysfs_entries, }; -static int debugfs_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count, loff_t *offp) { @@ -1087,7 +1081,7 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, static const struct file_operations port_debugfs_ops = { .owner = THIS_MODULE, - .open = debugfs_open, + .open = simple_open, .read = debugfs_read, }; diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index d65a718..a63badc 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -104,13 +104,6 @@ static void coh901318_list_print(struct coh901318_chan *cohc, static struct coh901318_base *debugfs_dma_base; static struct dentry *dma_dentry; -static int coh901318_debugfs_open(struct inode *inode, struct file *file) -{ - - file->private_data = inode->i_private; - return 0; -} - static int coh901318_debugfs_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos) { @@ -158,7 +151,7 @@ static int coh901318_debugfs_read(struct file *file, char __user *buf, static const struct file_operations coh901318_debugfs_status_operations = { .owner = THIS_MODULE, - .open = coh901318_debugfs_open, + .open = simple_open, .read = coh901318_debugfs_read, .llseek = default_llseek, }; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index fdb7cce..b505b70 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1502,14 +1502,6 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) return 0; } -static int -i915_debugfs_common_open(struct inode *inode, - struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - static ssize_t i915_wedged_read(struct file *filp, char __user *ubuf, @@ -1560,7 +1552,7 @@ i915_wedged_write(struct file *filp, static const struct file_operations i915_wedged_fops = { .owner = THIS_MODULE, - .open = i915_debugfs_common_open, + .open = simple_open, .read = i915_wedged_read, .write = i915_wedged_write, .llseek = default_llseek, @@ -1622,7 +1614,7 @@ i915_max_freq_write(struct file *filp, static const struct file_operations i915_max_freq_fops = { .owner = THIS_MODULE, - .open = i915_debugfs_common_open, + .open = simple_open, .read = i915_max_freq_read, .write = i915_max_freq_write, .llseek = default_llseek, @@ -1693,7 +1685,7 @@ i915_cache_sharing_write(struct file *filp, static const struct file_operations i915_cache_sharing_fops = { .owner = THIS_MODULE, - .open = i915_debugfs_common_open, + .open = simple_open, .read = i915_cache_sharing_read, .write = i915_cache_sharing_write, .llseek = default_llseek, diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 12f9777..45c3433 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c @@ -1525,12 +1525,6 @@ static const struct file_operations picolcd_debug_reset_fops = { /* * The "eeprom" file */ -static int picolcd_debug_eeprom_open(struct inode *i, struct file *f) -{ - f->private_data = i->i_private; - return 0; -} - static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u, size_t s, loff_t *off) { @@ -1618,7 +1612,7 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, */ static const struct file_operations picolcd_debug_eeprom_fops = { .owner = THIS_MODULE, - .open = picolcd_debug_eeprom_open, + .open = simple_open, .read = picolcd_debug_eeprom_read, .write = picolcd_debug_eeprom_write, .llseek = generic_file_llseek, @@ -1627,12 +1621,6 @@ static const struct file_operations picolcd_debug_eeprom_fops = { /* * The "flash" file */ -static int picolcd_debug_flash_open(struct inode *i, struct file *f) -{ - f->private_data = i->i_private; - return 0; -} - /* record a flash address to buf (bounds check to be done by caller) */ static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off) { @@ -1817,7 +1805,7 @@ static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, */ static const struct file_operations picolcd_debug_flash_fops = { .owner = THIS_MODULE, - .open = picolcd_debug_flash_open, + .open = simple_open, .read = picolcd_debug_flash_read, .write = picolcd_debug_flash_write, .llseek = generic_file_llseek, diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c index 17dabc1..eec3291 100644 --- a/drivers/hid/hid-wiimote-debug.c +++ b/drivers/hid/hid-wiimote-debug.c @@ -23,12 +23,6 @@ struct wiimote_debug { struct dentry *drm; }; -static int wiidebug_eeprom_open(struct inode *i, struct file *f) -{ - f->private_data = i->i_private; - return 0; -} - static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s, loff_t *off) { @@ -83,7 +77,7 @@ static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s, static const struct file_operations wiidebug_eeprom_fops = { .owner = THIS_MODULE, - .open = wiidebug_eeprom_open, + .open = simple_open, .read = wiidebug_eeprom_read, .llseek = generic_file_llseek, }; diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c index c976285..fa080eb 100644 --- a/drivers/idle/i7300_idle.c +++ b/drivers/idle/i7300_idle.c @@ -516,12 +516,6 @@ static struct notifier_block i7300_idle_nb = { MODULE_DEVICE_TABLE(pci, pci_tbl); -int stats_open_generic(struct inode *inode, struct file *fp) -{ - fp->private_data = inode->i_private; - return 0; -} - static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count, loff_t *off) { @@ -534,7 +528,7 @@ static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count, } static const struct file_operations idle_fops = { - .open = stats_open_generic, + .open = simple_open, .read = stats_read_ul, .llseek = default_llseek, }; diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 103dbd9..f55fc5d 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -323,15 +323,9 @@ err_out: return count; } -static int debug_open_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - #define DEBUG_FOPS(name) \ static const struct file_operations debug_##name##_fops = { \ - .open = debug_open_generic, \ + .open = simple_open, \ .read = debug_read_##name, \ .write = debug_write_##name, \ .llseek = generic_file_llseek, \ @@ -339,7 +333,7 @@ static int debug_open_generic(struct inode *inode, struct file *file) #define DEBUG_FOPS_RO(name) \ static const struct file_operations debug_##name##_fops = { \ - .open = debug_open_generic, \ + .open = simple_open, \ .read = debug_read_##name, \ .llseek = generic_file_llseek, \ }; diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 3aa36eb..44a3fdb 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -262,13 +262,6 @@ static ssize_t aat2870_dump_reg(struct aat2870_data *aat2870, char *buf) return count; } -static int aat2870_reg_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - - return 0; -} - static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -330,7 +323,7 @@ static ssize_t aat2870_reg_write_file(struct file *file, } static const struct file_operations aat2870_reg_fops = { - .open = aat2870_reg_open_file, + .open = simple_open, .read = aat2870_reg_read_file, .write = aat2870_reg_write_file, }; diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 60107ee..1efad20 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -483,12 +483,6 @@ struct ab3100_get_set_reg_priv { bool mode; }; -static int ab3100_get_set_reg_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t ab3100_get_set_reg(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) @@ -583,7 +577,7 @@ static ssize_t ab3100_get_set_reg(struct file *file, } static const struct file_operations ab3100_get_set_reg_fops = { - .open = ab3100_get_set_reg_open_file, + .open = simple_open, .write = ab3100_get_set_reg, .llseek = noop_llseek, }; diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 1c034b8..6673e57 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -500,12 +500,6 @@ static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf, return 1; } -static int remote_settings_file_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static int remote_settings_file_close(struct inode *inode, struct file *file) { return 0; @@ -600,7 +594,7 @@ static const struct file_operations r_heartbeat_fops = { }; static const struct file_operations remote_settings_fops = { - .open = remote_settings_file_open, + .open = simple_open, .release = remote_settings_file_close, .read = remote_settings_file_read, .write = remote_settings_file_write, diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index e2cdebf..61af9bb 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -386,19 +386,11 @@ out: return count; } -static int default_open(struct inode *inode, struct file *file) -{ - if (inode->i_private) - file->private_data = inode->i_private; - - return 0; -} - /* File operations for all UBI debugfs files */ static const struct file_operations dfs_fops = { .read = dfs_file_read, .write = dfs_file_write, - .open = default_open, + .open = simple_open, .llseek = no_llseek, .owner = THIS_MODULE, }; diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 96391c3..b71ce9b 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -127,12 +127,6 @@ static inline void dev_debugfs_rem(struct cfspi *cfspi) debugfs_remove(cfspi->dbgfs_dir); } -static int dbgfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t dbgfs_state(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -243,13 +237,13 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf, } static const struct file_operations dbgfs_state_fops = { - .open = dbgfs_open, + .open = simple_open, .read = dbgfs_state, .owner = THIS_MODULE }; static const struct file_operations dbgfs_frame_fops = { - .open = dbgfs_open, + .open = simple_open, .read = dbgfs_frame, .owner = THIS_MODULE }; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 05ff076a..b126b98 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2000,13 +2000,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = { /* * debugfs support */ - -static int mem_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -2050,7 +2043,7 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count, static const struct file_operations mem_debugfs_fops = { .owner = THIS_MODULE, - .open = mem_open, + .open = simple_open, .read = mem_read, .llseek = default_llseek, }; diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c index 129ba36..4b66ab1 100644 --- a/drivers/net/wimax/i2400m/debugfs.c +++ b/drivers/net/wimax/i2400m/debugfs.c @@ -53,17 +53,6 @@ struct dentry *debugfs_create_netdev_queue_stopped( &fops_netdev_queue_stopped); } - -/* - * inode->i_private has the @data argument to debugfs_create_file() - */ -static -int i2400m_stats_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - /* * We don't allow partial reads of this file, as then the reader would * get weirdly confused data as it is updated. @@ -117,7 +106,7 @@ ssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer, static const struct file_operations i2400m_rx_stats_fops = { .owner = THIS_MODULE, - .open = i2400m_stats_open, + .open = simple_open, .read = i2400m_rx_stats_read, .write = i2400m_rx_stats_write, .llseek = default_llseek, @@ -170,7 +159,7 @@ ssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer, static const struct file_operations i2400m_tx_stats_fops = { .owner = THIS_MODULE, - .open = i2400m_stats_open, + .open = simple_open, .read = i2400m_tx_stats_read, .write = i2400m_tx_stats_write, .llseek = default_llseek, diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 8c5ce8b..e5e8f45 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -71,13 +71,6 @@ static unsigned int ath5k_debug; module_param_named(debug, ath5k_debug, uint, 0); -static int ath5k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - - /* debugfs: registers */ struct reg { @@ -265,7 +258,7 @@ static ssize_t write_file_beacon(struct file *file, static const struct file_operations fops_beacon = { .read = read_file_beacon, .write = write_file_beacon, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -285,7 +278,7 @@ static ssize_t write_file_reset(struct file *file, static const struct file_operations fops_reset = { .write = write_file_reset, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = noop_llseek, }; @@ -365,7 +358,7 @@ static ssize_t write_file_debug(struct file *file, static const struct file_operations fops_debug = { .read = read_file_debug, .write = write_file_debug, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -477,7 +470,7 @@ static ssize_t write_file_antenna(struct file *file, static const struct file_operations fops_antenna = { .read = read_file_antenna, .write = write_file_antenna, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -532,7 +525,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, static const struct file_operations fops_misc = { .read = read_file_misc, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, }; @@ -647,7 +640,7 @@ static ssize_t write_file_frameerrors(struct file *file, static const struct file_operations fops_frameerrors = { .read = read_file_frameerrors, .write = write_file_frameerrors, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -810,7 +803,7 @@ static ssize_t write_file_ani(struct file *file, static const struct file_operations fops_ani = { .read = read_file_ani, .write = write_file_ani, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -881,7 +874,7 @@ static ssize_t write_file_queue(struct file *file, static const struct file_operations fops_queue = { .read = read_file_queue, .write = write_file_queue, - .open = ath5k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 552adb3..d01403a 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -217,12 +217,6 @@ void dump_cred_dist_stats(struct htc_target *target) target->credit_info->cur_free_credits); } -static int ath6kl_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) { switch (war) { @@ -263,7 +257,7 @@ static ssize_t read_file_war_stats(struct file *file, char __user *user_buf, static const struct file_operations fops_war_stats = { .read = read_file_war_stats, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -488,7 +482,7 @@ static ssize_t ath6kl_fwlog_mask_write(struct file *file, } static const struct file_operations fops_fwlog_mask = { - .open = ath6kl_debugfs_open, + .open = simple_open, .read = ath6kl_fwlog_mask_read, .write = ath6kl_fwlog_mask_write, .owner = THIS_MODULE, @@ -634,7 +628,7 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, static const struct file_operations fops_tgt_stats = { .read = read_file_tgt_stats, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -699,7 +693,7 @@ static ssize_t read_file_credit_dist_stats(struct file *file, static const struct file_operations fops_credit_dist_stats = { .read = read_file_credit_dist_stats, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -802,7 +796,7 @@ static ssize_t ath6kl_endpoint_stats_write(struct file *file, } static const struct file_operations fops_endpoint_stats = { - .open = ath6kl_debugfs_open, + .open = simple_open, .read = ath6kl_endpoint_stats_read, .write = ath6kl_endpoint_stats_write, .owner = THIS_MODULE, @@ -875,7 +869,7 @@ static ssize_t ath6kl_regread_write(struct file *file, static const struct file_operations fops_diag_reg_read = { .read = ath6kl_regread_read, .write = ath6kl_regread_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -999,7 +993,7 @@ static ssize_t ath6kl_lrssi_roam_read(struct file *file, static const struct file_operations fops_lrssi_roam_threshold = { .read = ath6kl_lrssi_roam_read, .write = ath6kl_lrssi_roam_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1061,7 +1055,7 @@ static ssize_t ath6kl_regwrite_write(struct file *file, static const struct file_operations fops_diag_reg_write = { .read = ath6kl_regwrite_read, .write = ath6kl_regwrite_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1166,7 +1160,7 @@ static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf, static const struct file_operations fops_roam_table = { .read = ath6kl_roam_table_read, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1204,7 +1198,7 @@ static ssize_t ath6kl_force_roam_write(struct file *file, static const struct file_operations fops_force_roam = { .write = ath6kl_force_roam_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1244,7 +1238,7 @@ static ssize_t ath6kl_roam_mode_write(struct file *file, static const struct file_operations fops_roam_mode = { .write = ath6kl_roam_mode_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1286,7 +1280,7 @@ static ssize_t ath6kl_keepalive_write(struct file *file, } static const struct file_operations fops_keepalive = { - .open = ath6kl_debugfs_open, + .open = simple_open, .read = ath6kl_keepalive_read, .write = ath6kl_keepalive_write, .owner = THIS_MODULE, @@ -1331,7 +1325,7 @@ static ssize_t ath6kl_disconnect_timeout_write(struct file *file, } static const struct file_operations fops_disconnect_timeout = { - .open = ath6kl_debugfs_open, + .open = simple_open, .read = ath6kl_disconnect_timeout_read, .write = ath6kl_disconnect_timeout_write, .owner = THIS_MODULE, @@ -1512,7 +1506,7 @@ static ssize_t ath6kl_create_qos_write(struct file *file, static const struct file_operations fops_create_qos = { .write = ath6kl_create_qos_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1560,7 +1554,7 @@ static ssize_t ath6kl_delete_qos_write(struct file *file, static const struct file_operations fops_delete_qos = { .write = ath6kl_delete_qos_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1593,7 +1587,7 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file, static const struct file_operations fops_bgscan_int = { .write = ath6kl_bgscan_int_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1651,7 +1645,7 @@ static ssize_t ath6kl_listen_int_read(struct file *file, static const struct file_operations fops_listen_int = { .read = ath6kl_listen_int_read, .write = ath6kl_listen_int_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1711,7 +1705,7 @@ static ssize_t ath6kl_power_params_write(struct file *file, static const struct file_operations fops_power_params = { .write = ath6kl_power_params_write, - .open = ath6kl_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 35d1c8e..ff47b32 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -26,11 +26,6 @@ #define REG_READ_D(_ah, _reg) \ ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -83,7 +78,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, static const struct file_operations fops_debug = { .read = read_file_debug, .write = write_file_debug, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -129,7 +124,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use static const struct file_operations fops_tx_chainmask = { .read = read_file_tx_chainmask, .write = write_file_tx_chainmask, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -172,7 +167,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use static const struct file_operations fops_rx_chainmask = { .read = read_file_rx_chainmask, .write = write_file_rx_chainmask, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -223,7 +218,7 @@ static ssize_t write_file_disable_ani(struct file *file, static const struct file_operations fops_disable_ani = { .read = read_file_disable_ani, .write = write_file_disable_ani, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -324,7 +319,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, static const struct file_operations fops_dma = { .read = read_file_dma, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -446,7 +441,7 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, static const struct file_operations fops_interrupt = { .read = read_file_interrupt, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -852,28 +847,28 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, static const struct file_operations fops_xmit = { .read = read_file_xmit, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static const struct file_operations fops_stations = { .read = read_file_stations, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static const struct file_operations fops_misc = { .read = read_file_misc, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; static const struct file_operations fops_reset = { .read = read_file_reset, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1016,7 +1011,7 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) static const struct file_operations fops_recv = { .read = read_file_recv, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1055,7 +1050,7 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf, static const struct file_operations fops_regidx = { .read = read_file_regidx, .write = write_file_regidx, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1102,7 +1097,7 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, static const struct file_operations fops_regval = { .read = read_file_regval, .write = write_file_regval, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1191,7 +1186,7 @@ static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf, static const struct file_operations fops_dump_nfcal = { .read = read_file_dump_nfcal, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1219,7 +1214,7 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, static const struct file_operations fops_base_eeprom = { .read = read_file_base_eeprom, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -1247,7 +1242,7 @@ static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, static const struct file_operations fops_modal_eeprom = { .read = read_file_modal_eeprom, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index 106d031..4364c10 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c @@ -60,16 +60,9 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf, return retval; } -static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - - return 0; -} - static const struct file_operations fops_dfs_stats = { .read = read_file_dfs, - .open = ath9k_dfs_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index d3ff33c..3035deb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -16,12 +16,6 @@ #include "htc.h" -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -75,7 +69,7 @@ static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, static const struct file_operations fops_tgt_int_stats = { .read = read_file_tgt_int_stats, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -145,7 +139,7 @@ static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, static const struct file_operations fops_tgt_tx_stats = { .read = read_file_tgt_tx_stats, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -191,7 +185,7 @@ static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, static const struct file_operations fops_tgt_rx_stats = { .read = read_file_tgt_rx_stats, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -243,7 +237,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, static const struct file_operations fops_xmit = { .read = read_file_xmit, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -364,7 +358,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, static const struct file_operations fops_recv = { .read = read_file_recv, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -399,7 +393,7 @@ static ssize_t read_file_slot(struct file *file, char __user *user_buf, static const struct file_operations fops_slot = { .read = read_file_slot, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -446,7 +440,7 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, static const struct file_operations fops_queue = { .read = read_file_queue, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -487,7 +481,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, static const struct file_operations fops_debug = { .read = read_file_debug, .write = write_file_debug, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -636,7 +630,7 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, static const struct file_operations fops_base_eeprom = { .read = read_file_base_eeprom, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -917,7 +911,7 @@ static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, static const struct file_operations fops_modal_eeprom = { .read = read_file_modal_eeprom, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4f84849..08bb455 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1480,12 +1480,6 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, #ifdef CONFIG_ATH9K_DEBUGFS -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1553,7 +1547,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, static const struct file_operations fops_rcstat = { .read = read_file_rcstat, - .open = ath9k_debugfs_open, + .open = simple_open, .owner = THIS_MODULE }; diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 3c16422..93fe600 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c @@ -48,11 +48,6 @@ #define ADD(buf, off, max, fmt, args...) \ off += snprintf(&buf[off], max - off, fmt, ##args); -static int carl9170_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} struct carl9170_debugfs_fops { unsigned int read_bufsize; @@ -178,7 +173,7 @@ static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\ .attr = _attr, \ .req_dev_state = _dstate, \ .fops = { \ - .open = carl9170_debugfs_open, \ + .open = simple_open, \ .read = carl9170_debugfs_read, \ .write = carl9170_debugfs_write, \ .owner = THIS_MODULE \ diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index e751fde..e807bd9 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -500,12 +500,6 @@ out: #undef fappend -static int b43_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -624,7 +618,7 @@ out_unlock: .read = _read, \ .write = _write, \ .fops = { \ - .open = b43_debugfs_open, \ + .open = simple_open, \ .read = b43_debugfs_read, \ .write = b43_debugfs_write, \ .llseek = generic_file_llseek, \ diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c index 5e28ad0..1965edb 100644 --- a/drivers/net/wireless/b43legacy/debugfs.c +++ b/drivers/net/wireless/b43legacy/debugfs.c @@ -197,12 +197,6 @@ static int restart_write_file(struct b43legacy_wldev *dev, const char *buf, size #undef fappend -static int b43legacy_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -331,7 +325,7 @@ out_unlock: .read = _read, \ .write = _write, \ .fops = { \ - .open = b43legacy_debugfs_open, \ + .open = simple_open, \ .read = b43legacy_debugfs_read, \ .write = b43legacy_debugfs_write, \ .llseek = generic_file_llseek, \ diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index 70bee1a..4b10157 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c @@ -821,12 +821,6 @@ out: } #ifdef CONFIG_MAC80211_DEBUGFS -static int -il3945_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} static ssize_t il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf, @@ -862,7 +856,7 @@ il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf, static const struct file_operations rs_sta_dbgfs_stats_table_ops = { .read = il3945_sta_dbgfs_stats_table_read, - .open = il3945_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index d7e2856..11ab124 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c @@ -2518,12 +2518,6 @@ il4965_rs_free_sta(void *il_r, struct ieee80211_sta *sta, void *il_sta) } #ifdef CONFIG_MAC80211_DEBUGFS -static int -il4965_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} static void il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta, u32 * rate_n_flags, int idx) @@ -2695,7 +2689,7 @@ il4965_rs_sta_dbgfs_scale_table_read(struct file *file, char __user *user_buf, static const struct file_operations rs_sta_dbgfs_scale_table_ops = { .write = il4965_rs_sta_dbgfs_scale_table_write, .read = il4965_rs_sta_dbgfs_scale_table_read, - .open = il4965_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -2740,7 +2734,7 @@ il4965_rs_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf, static const struct file_operations rs_sta_dbgfs_stats_table_ops = { .read = il4965_rs_sta_dbgfs_stats_table_read, - .open = il4965_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -2768,7 +2762,7 @@ il4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file, static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { .read = il4965_rs_sta_dbgfs_rate_scale_data_read, - .open = il4965_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index 2298491..eff2650 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c @@ -160,18 +160,12 @@ static ssize_t il_dbgfs_##name##_write(struct file *file, \ const char __user *user_buf, \ size_t count, loff_t *ppos); -static int -il_dbgfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} #define DEBUGFS_READ_FILE_OPS(name) \ DEBUGFS_READ_FUNC(name); \ static const struct file_operations il_dbgfs_##name##_ops = { \ .read = il_dbgfs_##name##_read, \ - .open = il_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -179,7 +173,7 @@ static const struct file_operations il_dbgfs_##name##_ops = { \ DEBUGFS_WRITE_FUNC(name); \ static const struct file_operations il_dbgfs_##name##_ops = { \ .write = il_dbgfs_##name##_write, \ - .open = il_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -189,7 +183,7 @@ static const struct file_operations il_dbgfs_##name##_ops = { \ static const struct file_operations il_dbgfs_##name##_ops = { \ .write = il_dbgfs_##name##_write, \ .read = il_dbgfs_##name##_read, \ - .open = il_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 53f8c51..7e590b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -3083,11 +3083,6 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, } #ifdef CONFIG_MAC80211_DEBUGFS -static int open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, u32 *rate_n_flags, int index) { @@ -3226,7 +3221,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, static const struct file_operations rs_sta_dbgfs_scale_table_ops = { .write = rs_sta_dbgfs_scale_table_write, .read = rs_sta_dbgfs_scale_table_read, - .open = open_file_generic, + .open = simple_open, .llseek = default_llseek, }; static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, @@ -3269,7 +3264,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, static const struct file_operations rs_sta_dbgfs_stats_table_ops = { .read = rs_sta_dbgfs_stats_table_read, - .open = open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -3295,7 +3290,7 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { .read = rs_sta_dbgfs_rate_scale_data_read, - .open = open_file_generic, + .open = simple_open, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index b7b1c04..2bbaebd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -84,17 +84,11 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ size_t count, loff_t *ppos); -static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - #define DEBUGFS_READ_FILE_OPS(name) \ DEBUGFS_READ_FUNC(name); \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -102,7 +96,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ DEBUGFS_WRITE_FUNC(name); \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .write = iwl_dbgfs_##name##_write, \ - .open = iwl_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -113,7 +107,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .write = iwl_dbgfs_##name##_write, \ .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index b4f796c..4d7b30d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1898,17 +1898,11 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ size_t count, loff_t *ppos); -static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - #define DEBUGFS_READ_FILE_OPS(name) \ DEBUGFS_READ_FUNC(name); \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -1916,7 +1910,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ DEBUGFS_WRITE_FUNC(name); \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .write = iwl_dbgfs_##name##_write, \ - .open = iwl_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -1926,7 +1920,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .write = iwl_dbgfs_##name##_write, \ .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index 87eef57..b6199d1 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -99,12 +99,6 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules, iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write, "%llu\n"); -static int iwm_generic_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) @@ -401,28 +395,28 @@ out: static const struct file_operations iwm_debugfs_txq_fops = { .owner = THIS_MODULE, - .open = iwm_generic_open, + .open = simple_open, .read = iwm_debugfs_txq_read, .llseek = default_llseek, }; static const struct file_operations iwm_debugfs_tx_credit_fops = { .owner = THIS_MODULE, - .open = iwm_generic_open, + .open = simple_open, .read = iwm_debugfs_tx_credit_read, .llseek = default_llseek, }; static const struct file_operations iwm_debugfs_rx_ticket_fops = { .owner = THIS_MODULE, - .open = iwm_generic_open, + .open = simple_open, .read = iwm_debugfs_rx_ticket_read, .llseek = default_llseek, }; static const struct file_operations iwm_debugfs_fw_err_fops = { .owner = THIS_MODULE, - .open = iwm_generic_open, + .open = simple_open, .read = iwm_debugfs_fw_err_read, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index 764b40d..0042f20 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -264,13 +264,6 @@ static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count) return ret; } -/* debugfs hooks */ -static int iwm_debugfs_sdio_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { @@ -363,7 +356,7 @@ err: static const struct file_operations iwm_debugfs_sdio_fops = { .owner = THIS_MODULE, - .open = iwm_debugfs_sdio_open, + .open = simple_open, .read = iwm_debugfs_sdio_read, .llseek = default_llseek, }; diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index c192671..a06cc28 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -21,12 +21,6 @@ static char *szStates[] = { static void lbs_debug_init(struct lbs_private *priv); #endif -static int open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t write_file_dummy(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -696,7 +690,7 @@ out_unlock: #define FOPS(fread, fwrite) { \ .owner = THIS_MODULE, \ - .open = open_file_generic, \ + .open = simple_open, \ .read = (fread), \ .write = (fwrite), \ .llseek = generic_file_llseek, \ @@ -962,7 +956,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, static const struct file_operations lbs_debug_fops = { .owner = THIS_MODULE, - .open = open_file_generic, + .open = simple_open, .write = lbs_debugfs_write, .read = lbs_debugfs_read, .llseek = default_llseek, diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index d26a78b..1a84507 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -140,18 +140,6 @@ static struct mwifiex_debug_data items[] = { static int num_of_items = ARRAY_SIZE(items); /* - * Generic proc file open handler. - * - * This function is called every time a file is accessed for read or write. - */ -static int -mwifiex_open_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -/* * Proc info file read handler. * * This function is called when the 'info' file is opened for reading. @@ -676,19 +664,19 @@ done: static const struct file_operations mwifiex_dfs_##name##_fops = { \ .read = mwifiex_##name##_read, \ .write = mwifiex_##name##_write, \ - .open = mwifiex_open_generic, \ + .open = simple_open, \ }; #define MWIFIEX_DFS_FILE_READ_OPS(name) \ static const struct file_operations mwifiex_dfs_##name##_fops = { \ .read = mwifiex_##name##_read, \ - .open = mwifiex_open_generic, \ + .open = simple_open, \ }; #define MWIFIEX_DFS_FILE_WRITE_OPS(name) \ static const struct file_operations mwifiex_dfs_##name##_fops = { \ .write = mwifiex_##name##_write, \ - .open = mwifiex_open_generic, \ + .open = simple_open, \ }; diff --git a/drivers/net/wireless/wl1251/debugfs.c b/drivers/net/wireless/wl1251/debugfs.c index 6c27400..448da1f 100644 --- a/drivers/net/wireless/wl1251/debugfs.c +++ b/drivers/net/wireless/wl1251/debugfs.c @@ -47,7 +47,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ \ static const struct file_operations name## _ops = { \ .read = name## _read, \ - .open = wl1251_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -84,7 +84,7 @@ static ssize_t sub## _ ##name## _read(struct file *file, \ \ static const struct file_operations sub## _ ##name## _ops = { \ .read = sub## _ ##name## _read, \ - .open = wl1251_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -117,12 +117,6 @@ out: mutex_unlock(&wl->mutex); } -static int wl1251_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); @@ -235,7 +229,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, static const struct file_operations tx_queue_len_ops = { .read = tx_queue_len_read, - .open = wl1251_open_file_generic, + .open = simple_open, .llseek = generic_file_llseek, }; @@ -257,7 +251,7 @@ static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf, static const struct file_operations tx_queue_status_ops = { .read = tx_queue_status_read, - .open = wl1251_open_file_generic, + .open = simple_open, .llseek = generic_file_llseek, }; diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index e1cf727..564d495 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -63,7 +63,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ \ static const struct file_operations name## _ops = { \ .read = name## _read, \ - .open = wl1271_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -96,7 +96,7 @@ static ssize_t sub## _ ##name## _read(struct file *file, \ \ static const struct file_operations sub## _ ##name## _ops = { \ .read = sub## _ ##name## _read, \ - .open = wl1271_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -126,12 +126,6 @@ out: mutex_unlock(&wl->mutex); } -static int wl1271_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u"); DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u"); @@ -243,7 +237,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, static const struct file_operations tx_queue_len_ops = { .read = tx_queue_len_read, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -289,7 +283,7 @@ static ssize_t gpio_power_write(struct file *file, static const struct file_operations gpio_power_ops = { .read = gpio_power_read, .write = gpio_power_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -308,7 +302,7 @@ static ssize_t start_recovery_write(struct file *file, static const struct file_operations start_recovery_ops = { .write = start_recovery_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -372,7 +366,7 @@ out: static const struct file_operations dynamic_ps_timeout_ops = { .read = dynamic_ps_timeout_read, .write = dynamic_ps_timeout_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -441,7 +435,7 @@ out: static const struct file_operations forced_ps_ops = { .read = forced_ps_read, .write = forced_ps_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -483,7 +477,7 @@ static ssize_t split_scan_timeout_write(struct file *file, static const struct file_operations split_scan_timeout_ops = { .read = split_scan_timeout_read, .write = split_scan_timeout_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -566,7 +560,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, static const struct file_operations driver_state_ops = { .read = driver_state_read, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -675,7 +669,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, static const struct file_operations vifs_state_ops = { .read = vifs_state_read, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -733,7 +727,7 @@ static ssize_t dtim_interval_write(struct file *file, static const struct file_operations dtim_interval_ops = { .read = dtim_interval_read, .write = dtim_interval_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -791,7 +785,7 @@ static ssize_t suspend_dtim_interval_write(struct file *file, static const struct file_operations suspend_dtim_interval_ops = { .read = suspend_dtim_interval_read, .write = suspend_dtim_interval_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -849,7 +843,7 @@ static ssize_t beacon_interval_write(struct file *file, static const struct file_operations beacon_interval_ops = { .read = beacon_interval_read, .write = beacon_interval_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -904,7 +898,7 @@ static ssize_t rx_streaming_interval_read(struct file *file, static const struct file_operations rx_streaming_interval_ops = { .read = rx_streaming_interval_read, .write = rx_streaming_interval_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -959,7 +953,7 @@ static ssize_t rx_streaming_always_read(struct file *file, static const struct file_operations rx_streaming_always_ops = { .read = rx_streaming_always_read, .write = rx_streaming_always_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; @@ -1003,7 +997,7 @@ out: static const struct file_operations beacon_filtering_ops = { .write = beacon_filtering_write, - .open = wl1271_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index ee8fd03..849357c 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -117,25 +117,17 @@ static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_ } -static int default_open(struct inode *inode, struct file *filp) -{ - if (inode->i_private) - filp->private_data = inode->i_private; - return 0; -} - - static const struct file_operations ulong_fops = { .read = ulong_read_file, .write = ulong_write_file, - .open = default_open, + .open = simple_open, .llseek = default_llseek, }; static const struct file_operations ulong_ro_fops = { .read = ulong_read_file, - .open = default_open, + .open = simple_open, .llseek = default_llseek, }; @@ -187,7 +179,7 @@ static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t coun static const struct file_operations atomic_ro_fops = { .read = atomic_read_file, - .open = default_open, + .open = simple_open, .llseek = default_llseek, }; diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 70277a5..85d31a6 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -50,16 +50,9 @@ static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf, return simple_read_from_buffer(userbuf, count, ppos, trace->va, len); } -static int rproc_open_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - - return 0; -} - static const struct file_operations trace_rproc_ops = { .read = rproc_trace_read, - .open = rproc_open_generic, + .open = simple_open, .llseek = generic_file_llseek, }; @@ -94,7 +87,7 @@ static ssize_t rproc_state_read(struct file *filp, char __user *userbuf, static const struct file_operations rproc_state_ops = { .read = rproc_state_read, - .open = rproc_open_generic, + .open = simple_open, .llseek = generic_file_llseek, }; @@ -114,7 +107,7 @@ static ssize_t rproc_name_read(struct file *filp, char __user *userbuf, static const struct file_operations rproc_name_ops = { .read = rproc_name_read, - .open = rproc_open_generic, + .open = simple_open, .llseek = generic_file_llseek, }; diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 22e17be..34f7cf7 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -997,13 +997,6 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf, return nbytes; } -static int -lpfc_debugfs_dif_err_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t lpfc_debugfs_dif_err_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) @@ -3521,7 +3514,7 @@ static const struct file_operations lpfc_debugfs_op_dumpDif = { #undef lpfc_debugfs_op_dif_err static const struct file_operations lpfc_debugfs_op_dif_err = { .owner = THIS_MODULE, - .open = lpfc_debugfs_dif_err_open, + .open = simple_open, .llseek = lpfc_debugfs_lseek, .read = lpfc_debugfs_dif_err_read, .write = lpfc_debugfs_dif_err_write, diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 082458d..d1a495f 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -63,12 +63,6 @@ struct chip_data { }; #ifdef CONFIG_DEBUG_FS -static int spi_show_regs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - #define SPI_REGS_BUFSIZE 1024 static ssize_t spi_show_regs(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -128,7 +122,7 @@ static ssize_t spi_show_regs(struct file *file, char __user *user_buf, static const struct file_operations mrst_spi_regs_ops = { .owner = THIS_MODULE, - .open = spi_show_regs_open, + .open = simple_open, .read = spi_show_regs, .llseek = default_llseek, }; diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index a9234ba8..c4b50af 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -127,11 +127,6 @@ static inline void serial_out(struct uart_hsu_port *up, int offset, int value) #define HSU_REGS_BUFSIZE 1024 -static int hsu_show_regs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} static ssize_t port_show_regs(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -231,14 +226,14 @@ static ssize_t dma_show_regs(struct file *file, char __user *user_buf, static const struct file_operations port_regs_ops = { .owner = THIS_MODULE, - .open = hsu_show_regs_open, + .open = simple_open, .read = port_show_regs, .llseek = default_llseek, }; static const struct file_operations dma_regs_ops = { .owner = THIS_MODULE, - .open = hsu_show_regs_open, + .open = simple_open, .read = dma_show_regs, .llseek = default_llseek, }; diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 332f2eb..46ec722 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -304,11 +304,7 @@ static const int trigger_level_1[4] = { 1, 1, 1, 1 }; #ifdef CONFIG_DEBUG_FS #define PCH_REGS_BUFSIZE 1024 -static int pch_show_regs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} + static ssize_t port_show_regs(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -362,7 +358,7 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf, static const struct file_operations port_regs_ops = { .owner = THIS_MODULE, - .open = pch_show_regs_open, + .open = simple_open, .read = port_show_regs, .llseek = default_llseek, }; diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index cefa0c8..d2b9af5 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -428,18 +428,10 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) return retval; } -static int default_open (struct inode *inode, struct file *file) -{ - if (inode->i_private) - file->private_data = inode->i_private; - - return 0; -} - static const struct file_operations default_file_operations = { .read = default_read_file, .write = default_write_file, - .open = default_open, + .open = simple_open, .llseek = default_file_lseek, }; diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index fd9109d..680e1a3 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -352,7 +352,6 @@ static int debug_async_open(struct inode *, struct file *); static int debug_periodic_open(struct inode *, struct file *); static int debug_registers_open(struct inode *, struct file *); static int debug_async_open(struct inode *, struct file *); -static int debug_lpm_open(struct inode *, struct file *); static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); static ssize_t debug_lpm_write(struct file *file, const char __user *buffer, @@ -385,7 +384,7 @@ static const struct file_operations debug_registers_fops = { }; static const struct file_operations debug_lpm_fops = { .owner = THIS_MODULE, - .open = debug_lpm_open, + .open = simple_open, .read = debug_lpm_read, .write = debug_lpm_write, .release = debug_lpm_close, @@ -970,12 +969,6 @@ static int debug_registers_open(struct inode *inode, struct file *file) return file->private_data ? 0 : -ENOMEM; } -static int debug_lpm_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static int debug_lpm_close(struct inode *inode, struct file *file) { return 0; diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c index 2eecec0..6ec45be 100644 --- a/drivers/uwb/uwb-debug.c +++ b/drivers/uwb/uwb-debug.c @@ -159,13 +159,6 @@ static int cmd_ie_rm(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_rm) return uwb_rc_ie_rm(rc, ie_to_rm->data[0]); } -static int command_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - - return 0; -} - static ssize_t command_write(struct file *file, const char __user *buf, size_t len, loff_t *off) { @@ -206,7 +199,7 @@ static ssize_t command_write(struct file *file, const char __user *buf, } static const struct file_operations command_fops = { - .open = command_open, + .open = simple_open, .write = command_write, .read = NULL, .llseek = no_llseek, diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 21e9360..5dfafdd 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -33,18 +33,10 @@ static ssize_t default_write_file(struct file *file, const char __user *buf, return count; } -static int default_open(struct inode *inode, struct file *file) -{ - if (inode->i_private) - file->private_data = inode->i_private; - - return 0; -} - const struct file_operations debugfs_file_operations = { .read = default_read_file, .write = default_write_file, - .open = default_open, + .open = simple_open, .llseek = noop_llseek, }; @@ -447,7 +439,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf, static const struct file_operations fops_bool = { .read = read_file_bool, .write = write_file_bool, - .open = default_open, + .open = simple_open, .llseek = default_llseek, }; @@ -492,7 +484,7 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf, static const struct file_operations fops_blob = { .read = read_file_blob, - .open = default_open, + .open = simple_open, .llseek = default_llseek, }; diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 3dca2b3..1c9b080 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c @@ -609,13 +609,6 @@ static const struct file_operations format3_fops = { /* * dump lkb's on the ls_waiters list */ - -static int waiters_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t waiters_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -644,7 +637,7 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf, static const struct file_operations waiters_fops = { .owner = THIS_MODULE, - .open = waiters_open, + .open = simple_open, .read = waiters_read, .llseek = default_llseek, }; diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index f37c32b..8ae5a03 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -52,12 +52,6 @@ struct pstore_private { char data[]; }; -static int pstore_file_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t pstore_file_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -67,7 +61,7 @@ static ssize_t pstore_file_read(struct file *file, char __user *userbuf, } static const struct file_operations pstore_file_operations = { - .open = pstore_file_open, + .open = simple_open, .read = pstore_file_read, .llseek = default_llseek, }; diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index cdea7b5..c0bd030 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -311,13 +311,6 @@ int blk_trace_remove(struct request_queue *q) } EXPORT_SYMBOL_GPL(blk_trace_remove); -static int blk_dropped_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - - return 0; -} - static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { @@ -331,18 +324,11 @@ static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, static const struct file_operations blk_dropped_fops = { .owner = THIS_MODULE, - .open = blk_dropped_open, + .open = simple_open, .read = blk_dropped_read, .llseek = default_llseek, }; -static int blk_msg_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - - return 0; -} - static ssize_t blk_msg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) { @@ -371,7 +357,7 @@ static ssize_t blk_msg_write(struct file *filp, const char __user *buffer, static const struct file_operations blk_msg_fops = { .owner = THIS_MODULE, - .open = blk_msg_open, + .open = simple_open, .write = blk_msg_write, .llseek = noop_llseek, }; diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index cc5b7a6..778e591 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -15,12 +15,6 @@ #include "rate.h" #include "debugfs.h" -int mac80211_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - #define DEBUGFS_FORMAT_BUFFER_SIZE 100 int mac80211_format_buffer(char __user *userbuf, size_t count, @@ -50,7 +44,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ #define DEBUGFS_READONLY_FILE_OPS(name) \ static const struct file_operations name## _ops = { \ .read = name## _read, \ - .open = mac80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -93,7 +87,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, static const struct file_operations reset_ops = { .write = reset_write, - .open = mac80211_open_file_generic, + .open = simple_open, .llseek = noop_llseek, }; @@ -254,7 +248,7 @@ static ssize_t stats_ ##name## _read(struct file *file, \ \ static const struct file_operations stats_ ##name## _ops = { \ .read = stats_ ##name## _read, \ - .open = mac80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h index 7c87529..9be4e6d 100644 --- a/net/mac80211/debugfs.h +++ b/net/mac80211/debugfs.h @@ -3,7 +3,6 @@ #ifdef CONFIG_MAC80211_DEBUGFS extern void debugfs_hw_add(struct ieee80211_local *local); -extern int mac80211_open_file_generic(struct inode *inode, struct file *file); extern int mac80211_format_buffer(char __user *userbuf, size_t count, loff_t *ppos, char *fmt, ...); #else diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 59edcd9..7932767 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -30,7 +30,7 @@ static ssize_t key_##name##_read(struct file *file, \ #define KEY_OPS(name) \ static const struct file_operations key_ ##name## _ops = { \ .read = key_##name##_read, \ - .open = mac80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ } @@ -45,7 +45,7 @@ static const struct file_operations key_ ##name## _ops = { \ #define KEY_CONF_OPS(name) \ static const struct file_operations key_ ##name## _ops = { \ .read = key_conf_##name##_read, \ - .open = mac80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index a32eeda..30f99c3 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -135,7 +135,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ static const struct file_operations name##_ops = { \ .read = ieee80211_if_read_##name, \ .write = (_write), \ - .open = mac80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ } diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6d45804..832b2da 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -33,7 +33,7 @@ static ssize_t sta_ ##name## _read(struct file *file, \ #define STA_OPS(name) \ static const struct file_operations sta_ ##name## _ops = { \ .read = sta_##name##_read, \ - .open = mac80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ } @@ -41,7 +41,7 @@ static const struct file_operations sta_ ##name## _ops = { \ static const struct file_operations sta_ ##name## _ops = { \ .read = sta_##name##_read, \ .write = sta_##name##_write, \ - .open = mac80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ } diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index b4f7600..3313c11 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -145,7 +145,7 @@ static ssize_t rcname_read(struct file *file, char __user *userbuf, static const struct file_operations rcname_ops = { .read = rcname_read, - .open = mac80211_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; #endif diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 39765bc..920cabe 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c @@ -13,12 +13,6 @@ #include "core.h" #include "debugfs.h" -static int cfg80211_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ static ssize_t name## _read(struct file *file, char __user *userbuf, \ size_t count, loff_t *ppos) \ @@ -33,7 +27,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ \ static const struct file_operations name## _ops = { \ .read = name## _read, \ - .open = cfg80211_open_file_generic, \ + .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -102,7 +96,7 @@ static ssize_t ht40allow_map_read(struct file *file, static const struct file_operations ht40allow_map_ops = { .read = ht40allow_map_read, - .open = cfg80211_open_file_generic, + .open = simple_open, .llseek = default_llseek, }; diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/imx/imx-audmux.c index 601df80..1765a19 100644 --- a/sound/soc/imx/imx-audmux.c +++ b/sound/soc/imx/imx-audmux.c @@ -40,12 +40,6 @@ static void __iomem *audmux_base; #ifdef CONFIG_DEBUG_FS static struct dentry *audmux_debugfs_root; -static int audmux_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - /* There is an annoying discontinuity in the SSI numbering with regard * to the Linux number of the devices */ static const char *audmux_port_string(int port) @@ -142,7 +136,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, } static const struct file_operations audmux_debugfs_fops = { - .open = audmux_open_file, + .open = simple_open, .read = audmux_read_file, .llseek = default_llseek, }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a4deebc..e19c24a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -201,12 +201,6 @@ static ssize_t pmdown_time_set(struct device *dev, static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set); #ifdef CONFIG_DEBUG_FS -static int codec_reg_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -264,7 +258,7 @@ static ssize_t codec_reg_write_file(struct file *file, } static const struct file_operations codec_reg_fops = { - .open = codec_reg_open_file, + .open = simple_open, .read = codec_reg_read_file, .write = codec_reg_write_file, .llseek = default_llseek, diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6241490..5cbd2d76 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1544,12 +1544,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) } #ifdef CONFIG_DEBUG_FS -static int dapm_widget_power_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t dapm_widget_power_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1613,17 +1607,11 @@ static ssize_t dapm_widget_power_read_file(struct file *file, } static const struct file_operations dapm_widget_power_fops = { - .open = dapm_widget_power_open_file, + .open = simple_open, .read = dapm_widget_power_read_file, .llseek = default_llseek, }; -static int dapm_bias_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1654,7 +1642,7 @@ static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf, } static const struct file_operations dapm_bias_fops = { - .open = dapm_bias_open_file, + .open = simple_open, .read = dapm_bias_read_file, .llseek = default_llseek, }; -- cgit v0.10.2 From 2561b069da3e8fe2ab939f82abe43754d39b6ea0 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 5 Apr 2012 14:25:12 -0700 Subject: alpha: use set_current_blocked() and block_sigmask() As described in e6fa16ab9c1e ("signal: sigprocmask() should do retarget_shared_pending()") the modification of current->blocked is incorrect as we need to check for shared signals we're about to block. Also, use the new helper function introduced in commit 5e6292c0f28f ("signal: add block_sigmask() for adding sigmask to current->blocked") which centralises the code for updating current->blocked after successfully delivering a signal and reduces the amount of duplicate code across architectures. In the past some architectures got this code wrong, so using this helper function should stop that from happening again. Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Cc: Al Viro Acked-by: Oleg Nesterov Signed-off-by: Matt Fleming Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 6f7feb5..35f2ef4 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -120,12 +120,13 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, */ SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) { - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); + sigset_t blocked; + current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + + mask &= _BLOCKABLE; + siginitset(&blocked, mask); + set_current_blocked(&blocked); current->state = TASK_INTERRUPTIBLE; schedule(); @@ -238,10 +239,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, goto give_sigsegv; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(sc, regs, sw)) goto give_sigsegv; @@ -276,10 +274,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, goto give_sigsegv; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) goto give_sigsegv; @@ -501,14 +496,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, else ret = setup_frame(sig, ka, oldset, regs, sw); - if (ret == 0) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } + if (ret == 0) + block_sigmask(ka, sig); return ret; } -- cgit v0.10.2 From 6fc26488e44a3248e24997cda2fa6a4d4b062c5b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 5 Apr 2012 14:25:13 -0700 Subject: MAINTAINERS: fix REMOTEPROC F: typo remoteproc.txt should have been .h Signed-off-by: Joe Perches Cc: Ohad Ben-Cohen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 3d11fa5..a8a0c60 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5639,7 +5639,7 @@ M: Ohad Ben-Cohen S: Maintained F: drivers/remoteproc/ F: Documentation/remoteproc.txt -F: include/linux/remoteproc.txt +F: include/linux/remoteproc.h RFKILL M: Johannes Berg -- cgit v0.10.2 From 389325b449caf3c73544f25bd4d6742b7f97e5dd Mon Sep 17 00:00:00 2001 From: Christopher Li Date: Thu, 5 Apr 2012 14:25:14 -0700 Subject: MAINTAINERS: add entry for sparse checker Signed-off-by: Christopher Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index a8a0c60..0104116 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6283,6 +6283,15 @@ F: drivers/tty/serial/sunsu.c F: drivers/tty/serial/sunzilog.c F: drivers/tty/serial/sunzilog.h +SPARSE CHECKER +M: "Christopher Li" +L: linux-sparse@vger.kernel.org +W: https://sparse.wiki.kernel.org/ +T: git git://git.kernel.org/pub/scm/devel/sparse/sparse.git +T: git git://git.kernel.org/pub/scm/devel/sparse/chrisl/sparse.git +S: Maintained +F: include/linux/compiler.h + SPEAR PLATFORM SUPPORT M: Viresh Kumar L: spear-devel@list.st.com -- cgit v0.10.2 From 6e61ee3b7a1e05a8c5b76095a1ea6c3711c922cb Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 5 Apr 2012 14:25:14 -0700 Subject: C6X: use set_current_blocked() and block_sigmask() As described in e6fa16ab9c1e ("signal: sigprocmask() should do retarget_shared_pending()") the modification of current->blocked is incorrect as we need to check whether the signal we're about to block is pending in the shared queue. Also, use the new helper function introduced in commit 5e6292c0f28f ("signal: add block_sigmask() for adding sigmask to current->blocked") which centralises the code for updating current->blocked after successfully delivering a signal and reduces the amount of duplicate code across architectures. In the past some architectures got this code wrong, so using this helper function should stop that from happening again. Acked-by: Mark Salter Cc: Aurelien Jacquiot Acked-by: Oleg Nesterov Signed-off-by: Matt Fleming Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c index 304f675..3b5a050 100644 --- a/arch/c6x/kernel/signal.c +++ b/arch/c6x/kernel/signal.c @@ -85,10 +85,7 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; @@ -279,15 +276,8 @@ static int handle_signal(int sig, /* Set up the stack frame */ ret = setup_rt_frame(sig, ka, info, oldset, regs); - if (ret == 0) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } + if (ret == 0) + block_sigmask(ka, sig); return ret; } -- cgit v0.10.2 From 6ede3d832aaa038e7465e677569f7acc96b4dcdf Mon Sep 17 00:00:00 2001 From: Ashish Jangam Date: Thu, 5 Apr 2012 14:25:15 -0700 Subject: backlight: add driver for DA9052/53 PMIC v1 DA9052/53 PMIC has capability to supply power for upto 3 banks of 6 white serial LEDS. It can also control intensity of independent banks and to drive these banks boost converter will provide up to 24V and forward current of max 50mA. This patch allows to control intensity of the individual WLEDs bank through DA9052/53 PMIC. This patch is functionally tested on Samsung SMDKV6410. Signed-off-by: David Dajun Chen Signed-off-by: Ashish Jangam Cc: Richard Purdie Cc: Samuel Ortiz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 7ed9991..af16884 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -245,6 +245,12 @@ config BACKLIGHT_DA903X If you have a LCD backlight connected to the WLED output of DA9030 or DA9034 WLED output, say Y here to enable this driver. +config BACKLIGHT_DA9052 + tristate "Dialog DA9052/DA9053 WLED" + depends on PMIC_DA9052 + help + Enable the Backlight Driver for DA9052-BC and DA9053-AA/Bx PMICs. + config BACKLIGHT_MAX8925 tristate "Backlight driver for MAX8925" depends on MFD_MAX8925 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 8071eb6..36855ae 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o +obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c new file mode 100644 index 0000000..b628d68 --- /dev/null +++ b/drivers/video/backlight/da9052_bl.c @@ -0,0 +1,187 @@ +/* + * Backlight Driver for Dialog DA9052 PMICs + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: David Dajun Chen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define DA9052_MAX_BRIGHTNESS 0xFF + +enum { + DA9052_WLEDS_OFF, + DA9052_WLEDS_ON, +}; + +enum { + DA9052_TYPE_WLED1, + DA9052_TYPE_WLED2, + DA9052_TYPE_WLED3, +}; + +static unsigned char wled_bank[] = { + DA9052_LED1_CONF_REG, + DA9052_LED2_CONF_REG, + DA9052_LED3_CONF_REG, +}; + +struct da9052_bl { + struct da9052 *da9052; + uint brightness; + uint state; + uint led_reg; +}; + +static int da9052_adjust_wled_brightness(struct da9052_bl *wleds) +{ + unsigned char boost_en; + unsigned char i_sink; + int ret; + + boost_en = 0x3F; + i_sink = 0xFF; + if (wleds->state == DA9052_WLEDS_OFF) { + boost_en = 0x00; + i_sink = 0x00; + } + + ret = da9052_reg_write(wleds->da9052, DA9052_BOOST_REG, boost_en); + if (ret < 0) + return ret; + + ret = da9052_reg_write(wleds->da9052, DA9052_LED_CONT_REG, i_sink); + if (ret < 0) + return ret; + + ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], 0x0); + if (ret < 0) + return ret; + + msleep(10); + + if (wleds->brightness) { + ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], + wleds->brightness); + if (ret < 0) + return ret; + } + + return 0; +} + +static int da9052_backlight_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + struct da9052_bl *wleds = bl_get_data(bl); + + wleds->brightness = brightness; + wleds->state = DA9052_WLEDS_ON; + + return da9052_adjust_wled_brightness(wleds); +} + +static int da9052_backlight_get_brightness(struct backlight_device *bl) +{ + struct da9052_bl *wleds = bl_get_data(bl); + + return wleds->brightness; +} + +static const struct backlight_ops da9052_backlight_ops = { + .update_status = da9052_backlight_update_status, + .get_brightness = da9052_backlight_get_brightness, +}; + +static int da9052_backlight_probe(struct platform_device *pdev) +{ + struct backlight_device *bl; + struct backlight_properties props; + struct da9052_bl *wleds; + + wleds = devm_kzalloc(&pdev->dev, sizeof(struct da9052_bl), GFP_KERNEL); + if (!wleds) + return -ENOMEM; + + wleds->da9052 = dev_get_drvdata(pdev->dev.parent); + wleds->brightness = 0; + wleds->led_reg = platform_get_device_id(pdev)->driver_data; + wleds->state = DA9052_WLEDS_OFF; + + props.type = BACKLIGHT_RAW; + props.max_brightness = DA9052_MAX_BRIGHTNESS; + + bl = backlight_device_register(pdev->name, wleds->da9052->dev, wleds, + &da9052_backlight_ops, &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "Failed to register backlight\n"); + devm_kfree(&pdev->dev, wleds); + return PTR_ERR(bl); + } + + bl->props.max_brightness = DA9052_MAX_BRIGHTNESS; + bl->props.brightness = 0; + platform_set_drvdata(pdev, bl); + + return da9052_adjust_wled_brightness(wleds); +} + +static int da9052_backlight_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct da9052_bl *wleds = bl_get_data(bl); + + wleds->brightness = 0; + wleds->state = DA9052_WLEDS_OFF; + da9052_adjust_wled_brightness(wleds); + backlight_device_unregister(bl); + devm_kfree(&pdev->dev, wleds); + + return 0; +} + +static struct platform_device_id da9052_wled_ids[] = { + { + .name = "da9052-wled1", + .driver_data = DA9052_TYPE_WLED1, + }, + { + .name = "da9052-wled2", + .driver_data = DA9052_TYPE_WLED2, + }, + { + .name = "da9052-wled3", + .driver_data = DA9052_TYPE_WLED3, + }, +}; + +static struct platform_driver da9052_wled_driver = { + .probe = da9052_backlight_probe, + .remove = da9052_backlight_remove, + .id_table = da9052_wled_ids, + .driver = { + .name = "da9052-wled", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(da9052_wled_driver); + +MODULE_AUTHOR("David Dajun Chen "); +MODULE_DESCRIPTION("Backlight driver for DA9052 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9052-backlight"); -- cgit v0.10.2 From dac23b0d0513916498d40412818bd2c581b365f7 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 5 Apr 2012 14:25:16 -0700 Subject: memcg swap: use mem_cgroup_uncharge_swap fix Although mem_cgroup_uncharge_swap has an empty placeholder for !CONFIG_CGROUP_MEM_RES_CTLR_SWAP the definition is placed in the CONFIG_SWAP ifdef block so we are missing the same definition for !CONFIG_SWAP which implies !CONFIG_CGROUP_MEM_RES_CTLR_SWAP. This has not been an issue before, because mem_cgroup_uncharge_swap was not called from !CONFIG_SWAP context. But Hugh Dickins has a cleanup patch to call __mem_cgroup_commit_charge_swapin which is defined also for !CONFIG_SWAP. Let's move both the empty definition and declaration outside of the CONFIG_SWAP block to avoid the following compilation error: mm/memcontrol.c: In function '__mem_cgroup_commit_charge_swapin': mm/memcontrol.c:2837: error: implicit declaration of function 'mem_cgroup_uncharge_swap' if CONFIG_SWAP is disabled. Reported-by: David Rientjes Signed-off-by: Michal Hocko Cc: Hugh Dickins Cc: KAMEZAWA Hiroyuki Cc: Daisuke Nishimura Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/swap.h b/include/linux/swap.h index 8dc0ea7..b1fd5c7 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -305,6 +305,13 @@ static inline int mem_cgroup_swappiness(struct mem_cgroup *mem) return vm_swappiness; } #endif +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP +extern void mem_cgroup_uncharge_swap(swp_entry_t ent); +#else +static inline void mem_cgroup_uncharge_swap(swp_entry_t ent) +{ +} +#endif #ifdef CONFIG_SWAP /* linux/mm/page_io.c */ extern int swap_readpage(struct page *); @@ -375,13 +382,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) { } #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP -extern void mem_cgroup_uncharge_swap(swp_entry_t ent); -#else -static inline void mem_cgroup_uncharge_swap(swp_entry_t ent) -{ -} -#endif #else /* CONFIG_SWAP */ -- cgit v0.10.2 From 35f9c09fe9c72eb8ca2b8e89a593e1c151f28fc2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 5 Apr 2012 03:05:35 +0000 Subject: tcp: tcp_sendpages() should call tcp_push() once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2f533844242 (tcp: allow splice() to build full TSO packets) added a regression for splice() calls using SPLICE_F_MORE. We need to call tcp_flush() at the end of the last page processed in tcp_sendpages(), or else transmits can be deferred and future sends stall. Add a new internal flag, MSG_SENDPAGE_NOTLAST, acting like MSG_MORE, but with different semantic. For all sendpage() providers, its a transparent change. Only sock_sendpage() and tcp_sendpages() can differentiate the two different flags provided by pipe_to_sendpage() Reported-by: Tom Herbert Cc: Nandita Dukkipati Cc: Neal Cardwell Cc: Tom Herbert Cc: Yuchung Cheng Cc: H.K. Jerry Chu Cc: Maciej Żenczykowski Cc: Mahesh Bandewar Cc: Ilpo Järvinen Signed-off-by: Eric Dumazet com> Signed-off-by: David S. Miller diff --git a/fs/splice.c b/fs/splice.c index 5f883de..f847684 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -30,6 +30,7 @@ #include #include #include +#include /* * Attempt to steal a page from a pipe buffer. This should perhaps go into @@ -690,7 +691,9 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe, if (!likely(file->f_op && file->f_op->sendpage)) return -EINVAL; - more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; + more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0; + if (sd->len < sd->total_len) + more |= MSG_SENDPAGE_NOTLAST; return file->f_op->sendpage(file, buf->page, buf->offset, sd->len, &pos, more); } diff --git a/include/linux/socket.h b/include/linux/socket.h index da2d3e2..b84bbd4 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -265,7 +265,7 @@ struct ucred { #define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */ #define MSG_MORE 0x8000 /* Sender will send more */ #define MSG_WAITFORONE 0x10000 /* recvmmsg(): block until 1+ packets avail */ - +#define MSG_SENDPAGE_NOTLAST 0x20000 /* sendpage() internal : not the last page */ #define MSG_EOF MSG_FIN #define MSG_CMSG_CLOEXEC 0x40000000 /* Set close_on_exit for file diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2ff6f45..5d54ed3 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -860,7 +860,7 @@ wait_for_memory: } out: - if (copied && !(flags & MSG_MORE)) + if (copied && !(flags & MSG_SENDPAGE_NOTLAST)) tcp_push(sk, flags, mss_now, tp->nonagle); return copied; diff --git a/net/socket.c b/net/socket.c index 484cc69..851edcd 100644 --- a/net/socket.c +++ b/net/socket.c @@ -811,9 +811,9 @@ static ssize_t sock_sendpage(struct file *file, struct page *page, sock = file->private_data; - flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; - if (more) - flags |= MSG_MORE; + flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; + /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ + flags |= more; return kernel_sendpage(sock, page, offset, size, flags); } -- cgit v0.10.2 From bcf1b70ac6eb0ed8286c66e6bf37cb747cbaa04c Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 5 Apr 2012 12:07:45 +0000 Subject: phonet: Check input from user before allocating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A phonet packet is limited to USHRT_MAX bytes, this is never checked during tx which means that the user can specify any size he wishes, and the kernel will attempt to allocate that size. In the good case, it'll lead to the following warning, but it may also cause the kernel to kick in the OOM and kill a random task on the server. [ 8921.744094] WARNING: at mm/page_alloc.c:2255 __alloc_pages_slowpath+0x65/0x730() [ 8921.749770] Pid: 5081, comm: trinity Tainted: G W 3.4.0-rc1-next-20120402-sasha #46 [ 8921.756672] Call Trace: [ 8921.758185] [] warn_slowpath_common+0x87/0xb0 [ 8921.762868] [] warn_slowpath_null+0x15/0x20 [ 8921.765399] [] __alloc_pages_slowpath+0x65/0x730 [ 8921.769226] [] ? zone_watermark_ok+0x1a/0x20 [ 8921.771686] [] ? get_page_from_freelist+0x625/0x660 [ 8921.773919] [] __alloc_pages_nodemask+0x1f8/0x240 [ 8921.776248] [] kmalloc_large_node+0x70/0xc0 [ 8921.778294] [] __kmalloc_node_track_caller+0x34/0x1c0 [ 8921.780847] [] ? sock_alloc_send_pskb+0xbc/0x260 [ 8921.783179] [] __alloc_skb+0x75/0x170 [ 8921.784971] [] sock_alloc_send_pskb+0xbc/0x260 [ 8921.787111] [] ? release_sock+0x7e/0x90 [ 8921.788973] [] sock_alloc_send_skb+0x10/0x20 [ 8921.791052] [] pep_sendmsg+0x60/0x380 [ 8921.792931] [] ? pn_socket_bind+0x156/0x180 [ 8921.794917] [] ? pn_socket_autobind+0x3f/0x90 [ 8921.797053] [] pn_socket_sendmsg+0x4f/0x70 [ 8921.798992] [] sock_aio_write+0x187/0x1b0 [ 8921.801395] [] ? sub_preempt_count+0xae/0xf0 [ 8921.803501] [] ? __lock_acquire+0x42c/0x4b0 [ 8921.805505] [] ? __sock_recv_ts_and_drops+0x140/0x140 [ 8921.807860] [] do_sync_readv_writev+0xbc/0x110 [ 8921.809986] [] ? might_fault+0x97/0xa0 [ 8921.811998] [] ? security_file_permission+0x1e/0x90 [ 8921.814595] [] do_readv_writev+0xe2/0x1e0 [ 8921.816702] [] ? do_setitimer+0x1ac/0x200 [ 8921.818819] [] ? get_parent_ip+0x11/0x50 [ 8921.820863] [] ? sub_preempt_count+0xae/0xf0 [ 8921.823318] [] vfs_writev+0x46/0x60 [ 8921.825219] [] sys_writev+0x4f/0xb0 [ 8921.827127] [] system_call_fastpath+0x16/0x1b [ 8921.829384] ---[ end trace dffe390f30db9eb7 ]--- Signed-off-by: Sasha Levin Acked-by: Rémi Denis-Courmont Signed-off-by: David S. Miller diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 9f60008..9726fe6 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -1130,6 +1130,9 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, int flags = msg->msg_flags; int err, done; + if (len > USHRT_MAX) + return -EMSGSIZE; + if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL| MSG_CMSG_COMPAT)) || !(msg->msg_flags & MSG_EOR)) -- cgit v0.10.2 From 5a4309746cd74734daa964acb02690c22b3c8911 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Thu, 5 Apr 2012 03:47:43 +0000 Subject: bonding: properly unset current_arp_slave on slave link up When a slave comes up, we're unsetting the current_arp_slave without removing active flags from it, which can lead to situations where we have more than one slave with active flags in active-backup mode. To avoid this situation we must remove the active flags from a slave before removing it as a current_arp_slave. Signed-off-by: Veaceslav Falico Signed-off-by: Jay Vosburgh Signed-off-by: Andy Gospodarek Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index fc8a8d5..62d2409 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3010,7 +3010,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) trans_start + delta_in_ticks)) || bond->curr_active_slave != slave) { slave->link = BOND_LINK_UP; - bond->current_arp_slave = NULL; + if (bond->current_arp_slave) { + bond_set_slave_inactive_flags( + bond->current_arp_slave); + bond->current_arp_slave = NULL; + } pr_info("%s: link status definitely up for interface %s.\n", bond->dev->name, slave->dev->name); -- cgit v0.10.2 From 44c14c1d4cf9b6ef4993c4a69f479d1f13cb8b21 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 2 Apr 2012 12:59:47 +0000 Subject: MAINTAINERS: update for Marvell Ethernet drivers Marvell has agreed to do maintenance on the sky2 driver. * Add the developer to the maintainers file * Remove the old reference to the long gone (sk98lin) driver * Rearrange to fit current topic organization Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index 962232d..c411dd1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4309,6 +4309,13 @@ W: http://www.kernel.org/doc/man-pages L: linux-man@vger.kernel.org S: Maintained +MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) +M: Mirko Lindner +M: Stephen Hemminger +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/ethernet/marvell/sk* + MARVELL LIBERTAS WIRELESS DRIVER M: Dan Williams L: libertas-dev@lists.infradead.org @@ -4339,12 +4346,6 @@ M: Nicolas Pitre S: Odd Fixes F: drivers/mmc/host/mvsdio.* -MARVELL YUKON / SYSKONNECT DRIVER -M: Mirko Lindner -M: Ralph Roesler -W: http://www.syskonnect.com -S: Supported - MATROX FRAMEBUFFER DRIVER L: linux-fbdev@vger.kernel.org S: Orphan @@ -6116,12 +6117,6 @@ W: http://www.winischhofer.at/linuxsisusbvga.shtml S: Maintained F: drivers/usb/misc/sisusbvga/ -SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS -M: Stephen Hemminger -L: netdev@vger.kernel.org -S: Maintained -F: drivers/net/ethernet/marvell/sk* - SLAB ALLOCATOR M: Christoph Lameter M: Pekka Enberg -- cgit v0.10.2 From 3119936a289db88cf749143fa5ef6b4a4712e3c0 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 16 Feb 2012 22:23:58 +0900 Subject: mmc: sdhci-s3c: Remove usage of clk_type member in platform data SDHCI controllers on Exynos4 do not include the sdclk divider as per the sdhci controller specification. This case can be represented using the sdhci quirk SDHCI_QUIRK_NONSTANDARD_CLOCK instead of using an additional enum type definition 'clk_types'. Hence, usage of clk_type member in platform data is removed and the sdhci quirk is used. In addition to that, since this qurik is SoC specific, driver data is introduced to represent controllers on SoC's that require this quirk. Cc: Ben Dooks Cc: Jeongbae Seo Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index b19e7d4..5fce143 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -53,6 +53,18 @@ struct sdhci_s3c { struct clk *clk_bus[MAX_BUS_CLK]; }; +/** + * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data + * @sdhci_quirks: sdhci host specific quirks. + * + * Specifies platform specific configuration of sdhci controller. + * Note: A structure for driver specific platform data is used for future + * expansion of its usage. + */ +struct sdhci_s3c_drv_data { + unsigned int sdhci_quirks; +}; + static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) { return sdhci_priv(host); @@ -132,10 +144,10 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, return UINT_MAX; /* - * Clock divider's step is different as 1 from that of host controller - * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL. + * If controller uses a non-standard clock division, find the best clock + * speed possible with selected clock source and skip the division. */ - if (ourhost->pdata->clk_type) { + if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { rate = clk_round_rate(clksrc, wanted); return wanted - rate; } @@ -272,6 +284,8 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) { struct sdhci_s3c *ourhost = to_s3c(host); + unsigned long timeout; + u16 clk = 0; /* don't bother if the clock is going off */ if (clock == 0) @@ -282,6 +296,25 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); host->clock = clock; + + clk = SDHCI_CLOCK_INT_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + /* Wait max 20 ms */ + timeout = 20; + while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) + & SDHCI_CLOCK_INT_STABLE)) { + if (timeout == 0) { + printk(KERN_ERR "%s: Internal clock never " + "stabilised.\n", mmc_hostname(host->mmc)); + return; + } + timeout--; + mdelay(1); + } + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); } /** @@ -382,9 +415,17 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) } } +static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( + struct platform_device *pdev) +{ + return (struct sdhci_s3c_drv_data *) + platform_get_device_id(pdev)->driver_data; +} + static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; + struct sdhci_s3c_drv_data *drv_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; @@ -414,6 +455,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) return PTR_ERR(host); } + drv_data = sdhci_s3c_get_driver_data(pdev); sc = sdhci_priv(host); sc->host = host; @@ -491,6 +533,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; + if (drv_data) + host->quirks |= drv_data->sdhci_quirks; #ifndef CONFIG_MMC_SDHCI_S3C_DMA @@ -531,7 +575,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) * If controller does not have internal clock divider, * we can use overriding functions instead of default. */ - if (pdata->clk_type) { + if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; @@ -647,9 +691,31 @@ static const struct dev_pm_ops sdhci_s3c_pmops = { #define SDHCI_S3C_PMOPS NULL #endif +#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) +static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { + .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK, +}; +#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data) +#else +#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)NULL) +#endif + +static struct platform_device_id sdhci_s3c_driver_ids[] = { + { + .name = "s3c-sdhci", + .driver_data = (kernel_ulong_t)NULL, + }, { + .name = "exynos4-sdhci", + .driver_data = EXYNOS4_SDHCI_DRV_DATA, + }, + { } +}; +MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); + static struct platform_driver sdhci_s3c_driver = { .probe = sdhci_s3c_probe, .remove = __devexit_p(sdhci_s3c_remove), + .id_table = sdhci_s3c_driver_ids, .driver = { .owner = THIS_MODULE, .name = "s3c-sdhci", -- cgit v0.10.2 From 0d22c77089c86416324d0d87e7ef8cfa931e53cd Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Sat, 31 Mar 2012 23:29:45 -0400 Subject: mmc: sdhci-s3c: derive transfer width host cap from max_width in platdata max_width member in platform data can be used to derive the mmc bus transfer width that can be supported by the controller. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 5fce143..dab1a77 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -562,6 +562,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->mmc->caps = MMC_CAP_NONREMOVABLE; + switch (pdata->max_width) { + case 8: + host->mmc->caps |= MMC_CAP_8_BIT_DATA; + case 4: + host->mmc->caps |= MMC_CAP_4_BIT_DATA; + break; + } + if (pdata->pm_caps) host->mmc->pm_caps |= pdata->pm_caps; -- cgit v0.10.2 From 1d4dc338bb7cbbadcb5a527b1b0e897b5cde1701 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 16 Feb 2012 22:23:59 +0900 Subject: mmc: sdhci-s3c: Keep a copy of platform data and use it The platform data is copied into driver's private data and the copy is used for all access to the platform data. This simpifies the addition of device tree support for the sdhci-s3c driver. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index dab1a77..e81a033 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -424,7 +424,7 @@ static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { - struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; + struct s3c_sdhci_platdata *pdata; struct sdhci_s3c_drv_data *drv_data; struct device *dev = &pdev->dev; struct sdhci_host *host; @@ -432,7 +432,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) struct resource *res; int ret, irq, ptr, clks; - if (!pdata) { + if (!pdev->dev.platform_data) { dev_err(dev, "no device data specified\n"); return -ENOENT; } @@ -455,6 +455,13 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) return PTR_ERR(host); } + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + goto err_io_clk; + } + memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); + drv_data = sdhci_s3c_get_driver_data(pdev); sc = sdhci_priv(host); -- cgit v0.10.2 From 9bda6da7ff7d35ef757e235aae559e679d3a9493 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 8 Mar 2012 23:24:53 -0500 Subject: mmc: sdhci-s3c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. By using devm_ioremap, it also removes a potential memory leak, because there was no call to iounmap in the probe function. The call to platform_get_resource was moved just to make it closer to the place where its result it used. Signed-off-by: Julia Lawall Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index e81a033..c3144cb 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -443,12 +443,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) return irq; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "no memory specified\n"); - return -ENOENT; - } - host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); @@ -513,15 +507,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) goto err_no_busclks; } - sc->ioarea = request_mem_region(res->start, resource_size(res), - mmc_hostname(host->mmc)); - if (!sc->ioarea) { - dev_err(dev, "failed to reserve register area\n"); - ret = -ENXIO; - goto err_req_regs; - } - - host->ioaddr = ioremap_nocache(res->start, resource_size(res)); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + host->ioaddr = devm_request_and_ioremap(&pdev->dev, res); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; @@ -606,7 +593,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); - goto err_add_host; + goto err_req_regs; } /* The following two methods of card detection might call @@ -620,10 +607,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) return 0; - err_add_host: - release_resource(sc->ioarea); - kfree(sc->ioarea); - err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { @@ -669,10 +652,6 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) clk_disable(sc->clk_io); clk_put(sc->clk_io); - iounmap(host->ioaddr); - release_resource(sc->ioarea); - kfree(sc->ioarea); - sdhci_free_host(host); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From d5e9c02cab60920d5ac16a8244bb6085dc27564f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 3 Mar 2012 00:46:41 +0000 Subject: mmc: sdhci-s3c: Use CONFIG_PM_SLEEP to ifdef system suspend This matches current best practice as one can have runtime PM enabled without system sleep and CONFIG_PM is defined for both. Signed-off-by: Mark Brown Acked-by: Jaehoon Chung Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index c3144cb..2ea3e6b 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include @@ -658,8 +661,7 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM - +#ifdef CONFIG_PM_SLEEP static int sdhci_s3c_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); @@ -673,10 +675,11 @@ static int sdhci_s3c_resume(struct device *dev) return sdhci_resume_host(host); } +#endif +#ifdef CONFIG_PM static const struct dev_pm_ops sdhci_s3c_pmops = { - .suspend = sdhci_s3c_suspend, - .resume = sdhci_s3c_resume, + SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume) }; #define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops) -- cgit v0.10.2 From 9f4e8151dbbc4ca4d5dd7792666a50c137102204 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 31 Mar 2012 23:31:55 -0400 Subject: mmc: sdhci-s3c: Enable runtime power management Since most of the work is already done by the core we just need to add runtime suspend methods and tell the PM core that runtime PM is enabled for this device. Signed-off-by: Mark Brown Acked-by: Jaehoon Chung Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 2ea3e6b..55a164f 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -593,9 +594,16 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) if (pdata->host_caps2) host->mmc->caps2 |= pdata->host_caps2; + pm_runtime_enable(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 50); + pm_runtime_use_autosuspend(&pdev->dev); + pm_suspend_ignore_children(&pdev->dev, 1); + ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); + pm_runtime_forbid(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); goto err_req_regs; } @@ -646,6 +654,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) sdhci_remove_host(host, 1); + pm_runtime_disable(&pdev->dev); + for (ptr = 0; ptr < 3; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); @@ -677,9 +687,27 @@ static int sdhci_s3c_resume(struct device *dev) } #endif +#ifdef CONFIG_PM_RUNTIME +static int sdhci_s3c_runtime_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + + return sdhci_runtime_suspend_host(host); +} + +static int sdhci_s3c_runtime_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + + return sdhci_runtime_resume_host(host); +} +#endif + #ifdef CONFIG_PM static const struct dev_pm_ops sdhci_s3c_pmops = { SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume) + SET_RUNTIME_PM_OPS(sdhci_s3c_runtime_suspend, sdhci_s3c_runtime_resume, + NULL) }; #define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops) -- cgit v0.10.2 From 66292ad92c6d3f2f1c137a1c826b331ca8595dfd Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 28 Mar 2012 12:28:33 +0200 Subject: mmc: atmel-mci: correct data timeout computation The HSMCI operates at a rate of up to Master Clock divided by two. Moreover previous calculation can cause overflows and so wrong timeouts. Signed-off-by: Ludovic Desroches Acked-by: Nicolas Ferre Cc: Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 9819dc0..34080f5 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -482,7 +482,14 @@ err: static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, unsigned int ns) { - return (ns * (host->bus_hz / 1000000) + 999) / 1000; + /* + * It is easier here to use us instead of ns for the timeout, + * it prevents from overflows during calculation. + */ + unsigned int us = DIV_ROUND_UP(ns, 1000); + + /* Maximum clock frequency is host->bus_hz/2 */ + return us * (DIV_ROUND_UP(host->bus_hz, 2000000)); } static void atmci_set_timeout(struct atmel_mci *host, -- cgit v0.10.2 From 33ab4bbbdf6c60a8c196b5a28215a93aa2a4ed2e Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 21 Mar 2012 16:41:22 +0100 Subject: mmc: atmel-mci: r/w proof capability only available since v2xx Signed-off-by: Ludovic Desroches Acked-by: Nicolas Ferre Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 34080f5..c56edc4 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2023,6 +2023,8 @@ static void __init atmci_get_cap(struct atmel_mci *host) /* keep only major version number */ switch (version & 0xf00) { case 0x100: + host->caps.has_pdc = 1; + break; case 0x200: host->caps.has_pdc = 1; host->caps.has_rwproof = 1; -- cgit v0.10.2 From faf8180b20882b52145b96d6d4ed082d41908f90 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 21 Mar 2012 16:41:23 +0100 Subject: mmc: atmel-mci: add support for odd clock dividers Add an odd clock divider capability available from v5xx. It also involves changing the clock divider calculation, and changing the switch-case statement to use top-down fallthrough. Signed-off-by: Ludovic Desroches Acked-by: Nicolas Ferre Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index 000b3ad..787aba1 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h @@ -31,6 +31,7 @@ # define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */ # define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */ # define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */ +# define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */ #define ATMCI_DTOR 0x0008 /* Data Timeout */ # define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */ # define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */ diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index c56edc4..e94476b 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -77,6 +77,7 @@ struct atmel_mci_caps { bool has_cstor_reg; bool has_highspeed; bool has_rwproof; + bool has_odd_clk_div; }; struct atmel_mci_dma { @@ -1134,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } /* Calculate clock divider */ - clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; - if (clkdiv > 255) { - dev_warn(&mmc->class_dev, - "clock %u too slow; using %lu\n", - clock_min, host->bus_hz / (2 * 256)); - clkdiv = 255; + if (host->caps.has_odd_clk_div) { + clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2; + if (clkdiv > 511) { + dev_warn(&mmc->class_dev, + "clock %u too slow; using %lu\n", + clock_min, host->bus_hz / (511 + 2)); + clkdiv = 511; + } + host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1) + | ATMCI_MR_CLKODD(clkdiv & 1); + } else { + clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; + if (clkdiv > 255) { + dev_warn(&mmc->class_dev, + "clock %u too slow; using %lu\n", + clock_min, host->bus_hz / (2 * 256)); + clkdiv = 255; + } + host->mode_reg = ATMCI_MR_CLKDIV(clkdiv); } - host->mode_reg = ATMCI_MR_CLKDIV(clkdiv); - /* * WRPROOF and RDPROOF prevent overruns/underruns by * stopping the clock when the FIFO is full/empty. @@ -2014,37 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host) "version: 0x%x\n", version); host->caps.has_dma = 0; - host->caps.has_pdc = 0; + host->caps.has_pdc = 1; host->caps.has_cfg_reg = 0; host->caps.has_cstor_reg = 0; host->caps.has_highspeed = 0; host->caps.has_rwproof = 0; + host->caps.has_odd_clk_div = 0; /* keep only major version number */ switch (version & 0xf00) { - case 0x100: - host->caps.has_pdc = 1; - break; - case 0x200: - host->caps.has_pdc = 1; - host->caps.has_rwproof = 1; - break; - case 0x300: - case 0x400: case 0x500: + host->caps.has_odd_clk_div = 1; + case 0x400: + case 0x300: #ifdef CONFIG_AT_HDMAC host->caps.has_dma = 1; #else - host->caps.has_dma = 0; dev_info(&host->pdev->dev, "has dma capability but dma engine is not selected, then use pio\n"); #endif + host->caps.has_pdc = 0; host->caps.has_cfg_reg = 1; host->caps.has_cstor_reg = 1; host->caps.has_highspeed = 1; + case 0x200: host->caps.has_rwproof = 1; + case 0x100: break; default: + host->caps.has_pdc = 0; dev_warn(&host->pdev->dev, "Unmanaged mci version, set minimum capabilities\n"); break; -- cgit v0.10.2 From 5865f2876baa5c68fd0d50029dd220ce19f3d2af Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 22 Mar 2012 11:47:26 +0100 Subject: mmc: block: Remove use of mmc_blk_set_blksize According to the specifications for SD and (e)MMC default blocksize (named BLOCKLEN in Spec.) must always be 512 bytes. Since we hardcoded to always use 512 bytes, we do not explicitly have to set it. Future improvements should potentially make it possible to use a greater blocksize than 512 bytes, but until then let's skip this. Signed-off-by: Ulf Hansson Reviewed-by: Subhash Jadavani Signed-off-by: Chris Ball diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index eed213a..b180965 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1623,24 +1623,6 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) return ret; } -static int -mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) -{ - int err; - - mmc_claim_host(card->host); - err = mmc_set_blocklen(card, 512); - mmc_release_host(card->host); - - if (err) { - pr_err("%s: unable to set block size to 512: %d\n", - md->disk->disk_name, err); - return -EINVAL; - } - - return 0; -} - static void mmc_blk_remove_req(struct mmc_blk_data *md) { struct mmc_card *card; @@ -1768,7 +1750,6 @@ static const struct mmc_fixup blk_fixups[] = static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; - int err; char cap_str[10]; /* @@ -1781,10 +1762,6 @@ static int mmc_blk_probe(struct mmc_card *card) if (IS_ERR(md)) return PTR_ERR(md); - err = mmc_blk_set_blksize(md, card); - if (err) - goto out; - string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, cap_str, sizeof(cap_str)); pr_info("%s: %s %s %s %s\n", @@ -1809,7 +1786,7 @@ static int mmc_blk_probe(struct mmc_card *card) out: mmc_blk_remove_parts(card, md); mmc_blk_remove_req(md); - return err; + return 0; } static void mmc_blk_remove(struct mmc_card *card) @@ -1845,8 +1822,6 @@ static int mmc_blk_resume(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { - mmc_blk_set_blksize(md, card); - /* * Resume involves the card going into idle state, * so current partition is always the main one. -- cgit v0.10.2 From f93882570496aa02ba8a47bfaf81cce43046b978 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 28 Mar 2012 18:01:09 +0900 Subject: mmc: sh_mmcif: double clock speed Correct an off-by one error when calculating the clock divisor in cases where the host clock is a power of two of the target clock. Previously the divisor was one greater than the correct value in these cases leading to the clock being set at half the desired speed. Thanks to Guennadi Liakhovetski for working with me on the logic for this change. Tested-by: Cao Minh Hiep Acked-by: Guennadi Liakhovetski Signed-off-by: Simon Horman Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index aafaf0b..d79c643 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -454,7 +454,8 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); else sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & - ((fls(host->clk / clk) - 1) << 16)); + ((fls(DIV_ROUND_UP(host->clk, + clk) - 1) - 1) << 16)); sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); } -- cgit v0.10.2 From 930f152cc9998388031af577843baae572ac8ab6 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 28 Mar 2012 18:01:10 +0900 Subject: mmc: sh_mmcif: mmc->f_max should be half of the bus clock mmc->f_max should be half of the bus clock. And now that mmc->f_max is not equal to the bus clock the latter should be used directly to calculate mmc->f_min. Cc: Magnus Damm Tested-by: Cao Minh Hiep Acked-by: Guennadi Liakhovetski Signed-off-by: Simon Horman Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index d79c643..4bb999e 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1298,14 +1298,14 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) spin_lock_init(&host->lock); mmc->ops = &sh_mmcif_ops; - mmc->f_max = host->clk; + mmc->f_max = host->clk / 2; /* close to 400KHz */ - if (mmc->f_max < 51200000) - mmc->f_min = mmc->f_max / 128; - else if (mmc->f_max < 102400000) - mmc->f_min = mmc->f_max / 256; + if (host->clk < 51200000) + mmc->f_min = host->clk / 128; + else if (host->clk < 102400000) + mmc->f_min = host->clk / 256; else - mmc->f_min = mmc->f_max / 512; + mmc->f_min = host->clk / 512; if (pd->ocr) mmc->ocr_avail = pd->ocr; mmc->caps = MMC_CAP_MMC_HIGHSPEED; -- cgit v0.10.2 From eb91b9118db8c05a5a1257b594b021d32b491254 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 28 Mar 2012 18:01:11 +0900 Subject: mmc: sh_mmcif: Simplify calculation of mmc->f_min There is no need to tune mmc->f_min to a value near 400kHz as the MMC core begins testing frequencies at 400kHz regardless of the value of mmc->f_min. As suggested by Guennadi Liakhovetski. Cc: Magnus Damm Acked-by: Guennadi Liakhovetski Tested-by: Cao Minh Hiep Signed-off-by: Simon Horman Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 4bb999e..724b35e 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1299,13 +1299,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) mmc->ops = &sh_mmcif_ops; mmc->f_max = host->clk / 2; - /* close to 400KHz */ - if (host->clk < 51200000) - mmc->f_min = host->clk / 128; - else if (host->clk < 102400000) - mmc->f_min = host->clk / 256; - else - mmc->f_min = host->clk / 512; + mmc->f_min = host->clk / 512; if (pd->ocr) mmc->ocr_avail = pd->ocr; mmc->caps = MMC_CAP_MMC_HIGHSPEED; -- cgit v0.10.2 From 210b7d28598e402548b0164ca2f543e15aab8c6e Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 29 Mar 2012 19:05:04 +0200 Subject: mmc: sdhci-pci: add quirks for broken MSI on O2Micro controllers MSI on my O2Micro OZ600 SD card reader is broken. This patch adds a quirk to disable MSI on these controllers. Signed-off-by: Manuel Lauss Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index fbbebe2..9303f7f 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -561,6 +561,7 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) static const struct sdhci_pci_fixes sdhci_o2 = { .probe = o2_probe, + .quirks2 = SDHCI_QUIRK2_BROKEN_MSI, }; static const struct sdhci_pci_fixes sdhci_jmicron = { @@ -1418,7 +1419,8 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, slots = chip->num_slots; /* Quirk may have changed this */ - pci_enable_msi(pdev); + if (!(chip->quirks2 & SDHCI_QUIRK2_BROKEN_MSI)) + pci_enable_msi(pdev); for (i = 0; i < slots; i++) { slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index e9051e1..9752fe4 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -91,6 +91,8 @@ struct sdhci_host { unsigned int quirks2; /* More deviations from spec. */ #define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1<<0) +/* broken MSI Interrupts */ +#define SDHCI_QUIRK2_BROKEN_MSI (1<<1) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- cgit v0.10.2 From 6500c8ed957ac7b1ff37045ba6a2ad39ab2a8dbc Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Fri, 30 Mar 2012 12:10:18 +0530 Subject: mmc: bus: print bus speed mode of UHS-I card When UHS-I card is detected also print the bus speed mode in which UHS-I card will be running. Signed-off-by: Subhash Jadavani Reviewed-by: Namjae Jeon Acked-by: Aaron Lu Signed-off-by: Chris Ball diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 5d011a3..3f60606 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -267,6 +267,15 @@ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; + const char *uhs_bus_speed_mode = ""; + static const char *const uhs_speeds[] = { + [UHS_SDR12_BUS_SPEED] = "SDR12 ", + [UHS_SDR25_BUS_SPEED] = "SDR25 ", + [UHS_SDR50_BUS_SPEED] = "SDR50 ", + [UHS_SDR104_BUS_SPEED] = "SDR104 ", + [UHS_DDR50_BUS_SPEED] = "DDR50 ", + }; + dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); @@ -296,6 +305,10 @@ int mmc_add_card(struct mmc_card *card) break; } + if (mmc_sd_card_uhs(card) && + (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) + uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; + if (mmc_host_is_spi(card->host)) { pr_info("%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), @@ -303,13 +316,13 @@ int mmc_add_card(struct mmc_card *card) mmc_card_ddr_mode(card) ? "DDR " : "", type); } else { - pr_info("%s: new %s%s%s%s card at address %04x\n", + pr_info("%s: new %s%s%s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_card_uhs(card) ? "ultra high speed " : (mmc_card_highspeed(card) ? "high speed " : ""), (mmc_card_hs200(card) ? "HS200 " : ""), mmc_card_ddr_mode(card) ? "DDR " : "", - type, card->rca); + uhs_bus_speed_mode, type, card->rca); } #ifdef CONFIG_DEBUG_FS -- cgit v0.10.2 From e841a7c69b708eeaf784fd517978006e8319b03a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 1 Apr 2012 00:34:58 -0400 Subject: mmc: sdio: Use empty system suspend/resume callbacks at the bus level Neil Brown reports that commit 35cd133c PM: Run the driver callback directly if the subsystem one is not there breaks suspend for his libertas wifi, because SDIO has a protocol where the suspend method can return -ENOSYS and this means "There is no point in suspending, just turn me off". Moreover, the suspend methods provided by SDIO drivers are not supposed to be called by the PM core or bus-level suspend routines (which aren't presend for SDIO). Instead, when the SDIO core gets to suspend the device's ancestor, it calls the device driver's suspend function, catches the ENOSYS, and turns the device off. The commit above breaks the SDIO core's assumption that the device drivers' callbacks won't be executed if it doesn't provide any bus-level callbacks. If fact, however, this assumption has never been really satisfied, because device class or device type suspend might very well use the driver's callback even without that commit. The simplest way to address this problem is to make the SDIO core tell the PM core to ignore driver callbacks, for example by providing no-operation suspend/resume callbacks at the bus level for it, which is implemented by this change. Reported-and-tested-by: Neil Brown Signed-off-by: Rafael J. Wysocki [stable: please apply to 3.3-stable only] Cc: Signed-off-by: Chris Ball diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 40989e6..236842e 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device *dev) return ret; } -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM + +static int pm_no_operation(struct device *dev) +{ + return 0; +} static const struct dev_pm_ops sdio_bus_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation) SET_RUNTIME_PM_OPS( pm_generic_runtime_suspend, pm_generic_runtime_resume, @@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_pm_ops = { #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) -#else /* !CONFIG_PM_RUNTIME */ +#else /* !CONFIG_PM */ #define SDIO_PM_OPS_PTR NULL -#endif /* !CONFIG_PM_RUNTIME */ +#endif /* !CONFIG_PM */ static struct bus_type sdio_bus_type = { .name = "sdio", -- cgit v0.10.2 From d59d77ed1e0cdd254f99260013b27d64dc1dffac Mon Sep 17 00:00:00 2001 From: Balaji T K Date: Fri, 24 Feb 2012 21:14:33 +0530 Subject: mmc: omap_hsmmc: use runtime put sync in probe error patch pm_runtime_put_sync instead of autosuspend pm runtime API because iounmap(host->base) follows immediately. Reported-by: Rajendra Nayak Signed-off-by: Balaji T K Signed-off-by: Venkatraman S Cc: Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 47adb16..f15b04b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2018,8 +2018,7 @@ err_reg: err_irq_cd_init: free_irq(host->irq, host); err_irq: - pm_runtime_mark_last_busy(host->dev); - pm_runtime_put_autosuspend(host->dev); + pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); clk_put(host->fclk); if (host->got_dbclk) { -- cgit v0.10.2 From 92a3aebf06bdef849cc53aba99f963a9ae397e9d Mon Sep 17 00:00:00 2001 From: Balaji T K Date: Fri, 24 Feb 2012 21:14:34 +0530 Subject: mmc: omap_hsmmc: context save after enabling runtime pm Call context save api after enabling runtime pm to make sure that register access in context save api happens with clk enabled. Signed-off-by: Balaji T K Signed-off-by: Venkatraman S Cc: Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f15b04b..4ee1570 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1875,8 +1875,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) goto err1; } - omap_hsmmc_context_save(host); - if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) { dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n"); mmc->caps2 |= MMC_CAP2_NO_MULTI_READ; @@ -1887,6 +1885,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY); pm_runtime_use_autosuspend(host->dev); + omap_hsmmc_context_save(host); + if (cpu_is_omap2430()) { host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); /* -- cgit v0.10.2 From 927ce944aebdcac0fa757d4e6448a6972184db8c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 14 Mar 2012 11:18:27 +0200 Subject: mmc: omap_hsmmc: trivial cleanups A bunch of non-functional cleanups to the omap_hsmmc driver. It basically decreases indentation level, drop unneded dereferences and drop unneded accesses to the platform_device structure. Signed-off-by: Felipe Balbi Signed-off-by: Venkatraman S Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4ee1570..920964a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2041,30 +2041,28 @@ static int omap_hsmmc_remove(struct platform_device *pdev) struct omap_hsmmc_host *host = platform_get_drvdata(pdev); struct resource *res; - if (host) { - pm_runtime_get_sync(host->dev); - mmc_remove_host(host->mmc); - if (host->use_reg) - omap_hsmmc_reg_put(host); - if (host->pdata->cleanup) - host->pdata->cleanup(&pdev->dev); - free_irq(host->irq, host); - if (mmc_slot(host).card_detect_irq) - free_irq(mmc_slot(host).card_detect_irq, host); - - pm_runtime_put_sync(host->dev); - pm_runtime_disable(host->dev); - clk_put(host->fclk); - if (host->got_dbclk) { - clk_disable(host->dbclk); - clk_put(host->dbclk); - } + pm_runtime_get_sync(host->dev); + mmc_remove_host(host->mmc); + if (host->use_reg) + omap_hsmmc_reg_put(host); + if (host->pdata->cleanup) + host->pdata->cleanup(&pdev->dev); + free_irq(host->irq, host); + if (mmc_slot(host).card_detect_irq) + free_irq(mmc_slot(host).card_detect_irq, host); - mmc_free_host(host->mmc); - iounmap(host->base); - omap_hsmmc_gpio_free(pdev->dev.platform_data); + pm_runtime_put_sync(host->dev); + pm_runtime_disable(host->dev); + clk_put(host->fclk); + if (host->got_dbclk) { + clk_disable(host->dbclk); + clk_put(host->dbclk); } + mmc_free_host(host->mmc); + iounmap(host->base); + omap_hsmmc_gpio_free(pdev->dev.platform_data); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) release_mem_region(res->start, resource_size(res)); @@ -2077,49 +2075,45 @@ static int omap_hsmmc_remove(struct platform_device *pdev) static int omap_hsmmc_suspend(struct device *dev) { int ret = 0; - struct platform_device *pdev = to_platform_device(dev); - struct omap_hsmmc_host *host = platform_get_drvdata(pdev); + struct omap_hsmmc_host *host = dev_get_drvdata(dev); - if (host && host->suspended) + if (!host) return 0; - if (host) { - pm_runtime_get_sync(host->dev); - host->suspended = 1; - if (host->pdata->suspend) { - ret = host->pdata->suspend(&pdev->dev, - host->slot_id); - if (ret) { - dev_dbg(mmc_dev(host->mmc), - "Unable to handle MMC board" - " level suspend\n"); - host->suspended = 0; - return ret; - } - } - ret = mmc_suspend_host(host->mmc); + if (host && host->suspended) + return 0; + pm_runtime_get_sync(host->dev); + host->suspended = 1; + if (host->pdata->suspend) { + ret = host->pdata->suspend(dev, host->slot_id); if (ret) { + dev_dbg(dev, "Unable to handle MMC board" + " level suspend\n"); host->suspended = 0; - if (host->pdata->resume) { - ret = host->pdata->resume(&pdev->dev, - host->slot_id); - if (ret) - dev_dbg(mmc_dev(host->mmc), - "Unmask interrupt failed\n"); - } - goto err; + return ret; } + } + ret = mmc_suspend_host(host->mmc); - if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { - omap_hsmmc_disable_irq(host); - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); + if (ret) { + host->suspended = 0; + if (host->pdata->resume) { + ret = host->pdata->resume(dev, host->slot_id); + if (ret) + dev_dbg(dev, "Unmask interrupt failed\n"); } - if (host->got_dbclk) - clk_disable(host->dbclk); + goto err; + } + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { + omap_hsmmc_disable_irq(host); + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); } + + if (host->got_dbclk) + clk_disable(host->dbclk); err: pm_runtime_put_sync(host->dev); return ret; @@ -2129,38 +2123,37 @@ err: static int omap_hsmmc_resume(struct device *dev) { int ret = 0; - struct platform_device *pdev = to_platform_device(dev); - struct omap_hsmmc_host *host = platform_get_drvdata(pdev); + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + + if (!host) + return 0; if (host && !host->suspended) return 0; - if (host) { - pm_runtime_get_sync(host->dev); + pm_runtime_get_sync(host->dev); - if (host->got_dbclk) - clk_enable(host->dbclk); + if (host->got_dbclk) + clk_enable(host->dbclk); - if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) - omap_hsmmc_conf_bus_power(host); + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) + omap_hsmmc_conf_bus_power(host); - if (host->pdata->resume) { - ret = host->pdata->resume(&pdev->dev, host->slot_id); - if (ret) - dev_dbg(mmc_dev(host->mmc), - "Unmask interrupt failed\n"); - } + if (host->pdata->resume) { + ret = host->pdata->resume(dev, host->slot_id); + if (ret) + dev_dbg(dev, "Unmask interrupt failed\n"); + } - omap_hsmmc_protect_card(host); + omap_hsmmc_protect_card(host); - /* Notify the core to resume the host */ - ret = mmc_resume_host(host->mmc); - if (ret == 0) - host->suspended = 0; + /* Notify the core to resume the host */ + ret = mmc_resume_host(host->mmc); + if (ret == 0) + host->suspended = 0; - pm_runtime_mark_last_busy(host->dev); - pm_runtime_put_autosuspend(host->dev); - } + pm_runtime_mark_last_busy(host->dev); + pm_runtime_put_autosuspend(host->dev); return ret; @@ -2177,7 +2170,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) host = platform_get_drvdata(to_platform_device(dev)); omap_hsmmc_context_save(host); - dev_dbg(mmc_dev(host->mmc), "disabled\n"); + dev_dbg(dev, "disabled\n"); return 0; } @@ -2188,7 +2181,7 @@ static int omap_hsmmc_runtime_resume(struct device *dev) host = platform_get_drvdata(to_platform_device(dev)); omap_hsmmc_context_restore(host); - dev_dbg(mmc_dev(host->mmc), "enabled\n"); + dev_dbg(dev, "enabled\n"); return 0; } -- cgit v0.10.2 From efa25fd3a33275861aa74ff03a512423873a8805 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 14 Mar 2012 11:18:28 +0200 Subject: mmc: omap_hsmmc: make it behave well as a module If we put probe() on __init section, that will never work for multiple module insertions/removals. In order to make it work properly, move probe to __devinit section and use platform_driver_register() instead of platform_driver_probe(). Signed-off-by: Felipe Balbi Signed-off-by: Venkatraman S Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 920964a..2aa963d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1785,7 +1785,7 @@ static inline struct omap_mmc_platform_data } #endif -static int __init omap_hsmmc_probe(struct platform_device *pdev) +static int __devinit omap_hsmmc_probe(struct platform_device *pdev) { struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; struct mmc_host *mmc; @@ -2036,7 +2036,7 @@ err: return ret; } -static int omap_hsmmc_remove(struct platform_device *pdev) +static int __devexit omap_hsmmc_remove(struct platform_device *pdev) { struct omap_hsmmc_host *host = platform_get_drvdata(pdev); struct resource *res; @@ -2194,7 +2194,8 @@ static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { }; static struct platform_driver omap_hsmmc_driver = { - .remove = omap_hsmmc_remove, + .probe = omap_hsmmc_probe, + .remove = __devexit_p(omap_hsmmc_remove), .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -2206,7 +2207,7 @@ static struct platform_driver omap_hsmmc_driver = { static int __init omap_hsmmc_init(void) { /* Register the MMC driver */ - return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe); + return platform_driver_register(&omap_hsmmc_driver); } static void __exit omap_hsmmc_cleanup(void) -- cgit v0.10.2 From b796450b4590dbaee2d31c85b04791cafacff9b4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 14 Mar 2012 11:18:32 +0200 Subject: mmc: omap_hsmmc: convert to module_platform_driver This will delete some boilerplate code, no functional changes. Signed-off-by: Felipe Balbi Signed-off-by: Venkatraman S Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2aa963d..b4c59ea 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2204,21 +2204,7 @@ static struct platform_driver omap_hsmmc_driver = { }, }; -static int __init omap_hsmmc_init(void) -{ - /* Register the MMC driver */ - return platform_driver_register(&omap_hsmmc_driver); -} - -static void __exit omap_hsmmc_cleanup(void) -{ - /* Unregister MMC driver */ - platform_driver_unregister(&omap_hsmmc_driver); -} - -module_init(omap_hsmmc_init); -module_exit(omap_hsmmc_cleanup); - +module_platform_driver(omap_hsmmc_driver); MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit v0.10.2 From fc307df88f0d77505c19756d95be66c981c421ea Mon Sep 17 00:00:00 2001 From: Balaji T K Date: Mon, 2 Apr 2012 12:26:47 +0530 Subject: mmc: omap_hsmmc: fix module re-insertion OMAP4 and OMAP3 HSMMC IP registers differ by 0x100 offset. Adding the offset to platform_device resource structure increments the start address for every insmod operation. MMC command fails on re-insertion as module due to incorrect register base. Fix this by updating the ioremap base address only. Signed-off-by: Balaji T K Signed-off-by: Venkatraman S Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b4c59ea..5c2b1c1 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1818,8 +1818,6 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) if (res == NULL || irq < 0) return -ENXIO; - res->start += pdata->reg_offset; - res->end += pdata->reg_offset; res = request_mem_region(res->start, resource_size(res), pdev->name); if (res == NULL) return -EBUSY; @@ -1843,7 +1841,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) host->dma_ch = -1; host->irq = irq; host->slot_id = 0; - host->mapbase = res->start; + host->mapbase = res->start + pdata->reg_offset; host->base = ioremap(host->mapbase, SZ_4K); host->power_mode = MMC_POWER_OFF; host->next_data.cookie = 1; -- cgit v0.10.2 From 93fc5a47f25c41125b30c0bf4f243bf3204a1a0a Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Tue, 3 Apr 2012 12:25:58 +0530 Subject: mmc: core: fix power class selection mmc_select_powerclass() function returns error if eMMC VDD level supported by host is between 2.7v to 3.2v. According to eMMC specification, valid voltage for high voltage cards is 2.7v to 3.6v. This patch ensures that 2.7v to 3.6v VDD range is treated as valid range. Also, failure to set the power class shouldn't be treated as fatal error because even if setting the power class fails, card can still work in default power class. If mmc_select_powerclass() returns error, just print the warning message and go ahead with rest of the card initialization. Signed-off-by: Subhash Jadavani Acked-by: Girish K S Reviewed-by: Namjae Jeon Signed-off-by: Chris Ball diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 02914d6..54df5ad 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -695,6 +695,11 @@ static int mmc_select_powerclass(struct mmc_card *card, else if (host->ios.clock <= 200000000) index = EXT_CSD_PWR_CL_200_195; break; + case MMC_VDD_27_28: + case MMC_VDD_28_29: + case MMC_VDD_29_30: + case MMC_VDD_30_31: + case MMC_VDD_31_32: case MMC_VDD_32_33: case MMC_VDD_33_34: case MMC_VDD_34_35: @@ -1111,11 +1116,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); - if (err) { - pr_err("%s: power class selection to bus width %d failed\n", - mmc_hostname(card->host), 1 << bus_width); - goto err; - } + if (err) + pr_warning("%s: power class selection to bus width %d" + " failed\n", mmc_hostname(card->host), + 1 << bus_width); } /* @@ -1147,10 +1151,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_select_powerclass(card, ext_csd_bits[idx][0], ext_csd); if (err) - pr_err("%s: power class selection to " - "bus width %d failed\n", - mmc_hostname(card->host), - 1 << bus_width); + pr_warning("%s: power class selection to " + "bus width %d failed\n", + mmc_hostname(card->host), + 1 << bus_width); err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, @@ -1178,10 +1182,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_select_powerclass(card, ext_csd_bits[idx][1], ext_csd); if (err) - pr_err("%s: power class selection to " - "bus width %d ddr %d failed\n", - mmc_hostname(card->host), - 1 << bus_width, ddr); + pr_warning("%s: power class selection to " + "bus width %d ddr %d failed\n", + mmc_hostname(card->host), + 1 << bus_width, ddr); err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, -- cgit v0.10.2 From 84e41d2d56fbacfd888ab1382e94e752da176582 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Tue, 3 Apr 2012 16:47:55 -0400 Subject: Revert "mmc: sdhci-pci: add quirks for broken MSI on O2Micro controllers" This reverts commit c16e981b2fd9455af670a69a84f4c8cf07e12658, because it's no longer useful once MSI support is reverted. Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 9303f7f..fbbebe2 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -561,7 +561,6 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) static const struct sdhci_pci_fixes sdhci_o2 = { .probe = o2_probe, - .quirks2 = SDHCI_QUIRK2_BROKEN_MSI, }; static const struct sdhci_pci_fixes sdhci_jmicron = { @@ -1419,8 +1418,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, slots = chip->num_slots; /* Quirk may have changed this */ - if (!(chip->quirks2 & SDHCI_QUIRK2_BROKEN_MSI)) - pci_enable_msi(pdev); + pci_enable_msi(pdev); for (i = 0; i < slots; i++) { slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 9752fe4..e9051e1 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -91,8 +91,6 @@ struct sdhci_host { unsigned int quirks2; /* More deviations from spec. */ #define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1<<0) -/* broken MSI Interrupts */ -#define SDHCI_QUIRK2_BROKEN_MSI (1<<1) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- cgit v0.10.2 From 79263f33b0f3abe26d74a66824b457b94bdbef9f Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Tue, 3 Apr 2012 16:48:32 -0400 Subject: Revert "mmc: sdhci-pci: Add MSI support" This reverts commit e6039832bed9a9b967796d7021f17f25b625b616. There are reports of MSI breaking SDHCI on multiple chipsets (JMicron and O2Micro, at least), so this should be reverted until we come up with a whitelist or something. Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index fbbebe2..69ef0be 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -1418,8 +1418,6 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, slots = chip->num_slots; /* Quirk may have changed this */ - pci_enable_msi(pdev); - for (i = 0; i < slots; i++) { slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); if (IS_ERR(slot)) { @@ -1438,8 +1436,6 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, return 0; free: - pci_disable_msi(pdev); - pci_set_drvdata(pdev, NULL); kfree(chip); @@ -1462,8 +1458,6 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev) for (i = 0; i < chip->num_slots; i++) sdhci_pci_remove_slot(chip->slots[i]); - pci_disable_msi(pdev); - pci_set_drvdata(pdev, NULL); kfree(chip); } -- cgit v0.10.2 From 4188bba0e9e7ba58d231b528df495666f2742b74 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Fri, 16 Mar 2012 15:54:17 -0400 Subject: mmc: Prevent 1.8V switch for SD hosts that don't support UHS modes. The driver should not try to switch to 1.8V when the SD 3.0 host controller does not have any UHS capabilities bits set (SDR50, DDR50 or SDR104). See page 72 of "SD Specifications Part A2 SD Host Controller Simplified Specification Version 3.00" under "1.8V Signaling Enable". Instead of setting SDR12 and SDR25 in the host capabilities data structure for all V3.0 host controllers, only set them if SDR104, SDR50 or DDR50 is set in the host capabilities register. This will prevent the switch to 1.8V later. Signed-off-by: Al Cooper Acked-by: Arindam Nath Acked-by: Philip Rakity Acked-by: Girish K S Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 8262cad..9aa77f3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2782,8 +2782,9 @@ int sdhci_add_host(struct sdhci_host *host) mmc_card_is_removable(mmc)) mmc->caps |= MMC_CAP_NEEDS_POLL; - /* UHS-I mode(s) supported by the host controller. */ - if (host->version >= SDHCI_SPEC_300) + /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ + if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50)) mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; /* SDR104 supports also implies SDR50 support */ -- cgit v0.10.2 From 8c2fc8e413ecc2c96b696e28d4eb1bc6cee8dc84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf=20H=C3=B8gemark?= Date: Wed, 4 Apr 2012 12:27:09 -0400 Subject: mmc: sdhci-dove: Fix compile error by including module.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes a compile error in drivers/mmc/host/sdhci-dove.c by including the linux/module.h file. Signed-off-by: Alf Høgemark Cc: Signed-off-by: Chris Ball diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 46fd1fd..177f697 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -20,6 +20,7 @@ */ #include +#include #include #include "sdhci-pltfm.h" -- cgit v0.10.2 From 3bdc9ba892d6a294d16e9e6e0c4041926aa3d58c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 12 Mar 2012 04:58:00 -0600 Subject: mmc: use really long write timeout to deal with crappy cards Several people have noticed that crappy SD cards take much longer to complete multiple block writes than the 300ms that Linux specifies. Try to work around this by using a three second write timeout instead. This is a generalized version of a patch from Chase Maupin , whose patch description said: * With certain SD cards timeouts like the following have been seen due to an improper calculation of the dto value: mmcblk0: error -110 transferring data, sector 4126233, nr 8, card status 0xc00 * By removing the dto calculation and setting the timeout value to the maximum specified by the SD card specification part A2 section 2.2.15 these timeouts can be avoided. * This change has been used by beagleboard users as well as the Texas Instruments SDK without a negative impact. * There are multiple discussion threads about this but the most relevant ones are: * http://talk.maemo.org/showthread.php?p=1000707#post1000707 * http://www.mail-archive.com/linux-omap@vger.kernel.org/msg42213.html * Original proposal for this fix was done by Sukumar Ghoral of Texas Instruments * Tested using a Texas Instruments AM335x EVM Signed-off-by: Paul Walmsley Tested-by: Tony Lindgren Signed-off-by: Chris Ball diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 14f262e..7474c47 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -527,10 +527,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) if (data->flags & MMC_DATA_WRITE) /* - * The limit is really 250 ms, but that is - * insufficient for some crappy cards. + * The MMC spec "It is strongly recommended + * for hosts to implement more than 500ms + * timeout value even if the card indicates + * the 250ms maximum busy length." Even the + * previous value of 300ms is known to be + * insufficient for some cards. */ - limit_us = 300000; + limit_us = 3000000; else limit_us = 100000; -- cgit v0.10.2 From 95fc2d8f96d37995f2bd1ec49f46ee9816ddf5b7 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 28 Mar 2012 11:43:02 +0800 Subject: blackfin: fix L1 data A overflow link issue This patch fix below compile error: "bfin-uclinux-ld: L1 data A overflow!" It is due to the recent lib/gen_crc32table.c change: 46c5801eaf86e83cb3a4142ad35188db5011fff0 crc32: bolt on crc32c it added 8KiB more data to __cacheline_aligned which cause blackfin L1 data cache overflow. Signed-off-by: Mike Frysinger Signed-off-by: Bob Liu diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index c1269a1..373a690 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -823,7 +823,7 @@ config CACHELINE_ALIGNED_L1 bool "Locate cacheline_aligned data to L1 Data Memory" default y if !BF54x default n if BF54x - depends on !SMP && !BF531 + depends on !SMP && !BF531 && !CRC32 help If enabled, cacheline_aligned data is linked into L1 data memory. (less latency) -- cgit v0.10.2 From e8c5c6da6c8aafceb9b7ca98c601db55640826b3 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Tue, 27 Mar 2012 11:27:15 +0800 Subject: blackfin: gpio: fix compile error if !CONFIG_GPIOLIB Add __gpio_get_value()/__gpio_set_value() to fix compile error if CONFIG_GPIOLIB = n. Signed-off-by: Bob Liu diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 5a25856..12d3571 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -244,16 +244,26 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) return -EINVAL; } -static inline int gpio_get_value(unsigned gpio) +static inline int __gpio_get_value(unsigned gpio) { return bfin_gpio_get_value(gpio); } -static inline void gpio_set_value(unsigned gpio, int value) +static inline void __gpio_set_value(unsigned gpio, int value) { return bfin_gpio_set_value(gpio, value); } +static inline int gpio_get_value(unsigned gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + return __gpio_set_value(gpio, value); +} + static inline int gpio_to_irq(unsigned gpio) { if (likely(gpio < MAX_BLACKFIN_GPIOS)) -- cgit v0.10.2 From 35fe2e73bf097409abb9b81e041db83ea08b1c93 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Thu, 5 Apr 2012 10:40:35 +0800 Subject: blackfin: update defconfig for bf527-ezkit To fix compile error: drivers/usb/musb/blackfin.h:51:3: error: #error "Please use PIO mode in MUSB driver on bf52x chip v0.0 and v0.1" make[4]: *** [drivers/usb/musb/blackfin.o] Error 1 Signed-off-by: Bob Liu diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index 9ccc18a..90b1753 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -147,6 +147,7 @@ CONFIG_USB_OTG_BLACKLIST_HUB=y CONFIG_USB_MON=y CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_BLACKFIN=y +CONFIG_MUSB_PIO_ONLY=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_RTC_CLASS=y -- cgit v0.10.2 From b4f79e5cb2182f27d151da6e223186f287a615d6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Apr 2012 14:38:49 +0000 Subject: ethtool: Remove exception to the requirement of holding RTNL lock Commit e52ac3398c3d772d372b9b62ab408fd5eec96840 ('net: Use device model to get driver name in skb_gso_segment()') removed the only in-tree caller of ethtool ops that doesn't hold the RTNL lock. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index e1d9e0e..f5647b5 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -896,8 +896,7 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings) * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must - * hold the RTNL, except that for @get_drvinfo the caller may or may - * not hold the RTNL. + * hold the RTNL lock. * * See the structures used by these operations for further documentation. * -- cgit v0.10.2 From 93b6a3adbd159174772702744b142d60e3891dfa Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Apr 2012 14:39:10 +0000 Subject: doc, net: Remove obsolete reference to dev->poll Commit bea3348eef27e6044b6161fd04c3152215f96411 ('[NET]: Make NAPI polling independent of struct net_device objects.') removed the automatic disabling of NAPI polling by dev_close(), and drivers must now do this themselves. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 8935834..336fe8e 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -54,8 +54,7 @@ dev->open: dev->stop: Synchronization: rtnl_lock() semaphore. Context: process - Note1: netif_running() is guaranteed false - Note2: dev->poll() is guaranteed to be stopped + Note: netif_running() is guaranteed false dev->do_ioctl: Synchronization: rtnl_lock() semaphore. -- cgit v0.10.2 From 04fd3d3515612b71f96b851db7888bfe58ef2142 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Apr 2012 14:39:30 +0000 Subject: doc, net: Update documentation of synchronisation for TX multiqueue Commits e308a5d806c852f56590ffdd3834d0df0cbed8d7 ('netdev: Add netdev->addr_list_lock protection.') and e8a0464cc950972824e2e128028ae3db666ec1ed ('netdev: Allocate multiple queues for TX.') introduced more fine-grained locks. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 336fe8e..b107733 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -65,7 +65,7 @@ dev->get_stats: Context: nominally process, but don't sleep inside an rwlock dev->hard_start_xmit: - Synchronization: netif_tx_lock spinlock. + Synchronization: __netif_tx_lock spinlock. When the driver sets NETIF_F_LLTX in dev->features this will be called without holding netif_tx_lock. In this case the driver @@ -87,12 +87,12 @@ dev->hard_start_xmit: Only valid when NETIF_F_LLTX is set. dev->tx_timeout: - Synchronization: netif_tx_lock spinlock. + Synchronization: netif_tx_lock spinlock; all TX queues frozen. Context: BHs disabled Notes: netif_queue_stopped() is guaranteed true dev->set_rx_mode: - Synchronization: netif_tx_lock spinlock. + Synchronization: netif_addr_lock spinlock. Context: BHs disabled struct napi_struct synchronization rules -- cgit v0.10.2 From b3cf65457fc0c8d183bdb9bc4358e5706aa63cc5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Apr 2012 14:39:47 +0000 Subject: doc, net: Update netdev operation names Commits d314774cf2cd5dfeb39a00d37deee65d4c627927 ('netdev: network device operations infrastructure') and 008298231abbeb91bc7be9e8b078607b816d1a4a ('netdev: add more functions to netdevice ops') moved and renamed net device operation pointers. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/Documentation/networking/driver.txt b/Documentation/networking/driver.txt index 03283da..83ce060 100644 --- a/Documentation/networking/driver.txt +++ b/Documentation/networking/driver.txt @@ -2,7 +2,7 @@ Document about softnet driver issues Transmit path guidelines: -1) The hard_start_xmit method must never return '1' under any +1) The ndo_start_xmit method must never return '1' under any normal circumstances. It is considered a hard error unless there is no way your device can tell ahead of time when it's transmit function will become busy. @@ -61,10 +61,10 @@ Transmit path guidelines: 2) Do not forget to update netdev->trans_start to jiffies after each new tx packet is given to the hardware. -3) A hard_start_xmit method must not modify the shared parts of a +3) An ndo_start_xmit method must not modify the shared parts of a cloned SKB. -4) Do not forget that once you return 0 from your hard_start_xmit +4) Do not forget that once you return 0 from your ndo_start_xmit method, it is your driver's responsibility to free up the SKB and in some finite amount of time. @@ -74,7 +74,7 @@ Transmit path guidelines: This error can deadlock sockets waiting for send buffer room to be freed up. - If you return 1 from the hard_start_xmit method, you must not keep + If you return 1 from the ndo_start_xmit method, you must not keep any reference to that SKB and you must not attempt to free it up. Probing guidelines: @@ -85,10 +85,10 @@ Probing guidelines: Close/stop guidelines: -1) After the dev->stop routine has been called, the hardware must +1) After the ndo_stop routine has been called, the hardware must not receive or transmit any data. All in flight packets must be aborted. If necessary, poll or wait for completion of any reset commands. -2) The dev->stop routine will be called by unregister_netdevice +2) The ndo_stop routine will be called by unregister_netdevice if device is still UP. diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index b107733..c7ecc70 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -47,24 +47,24 @@ packets is preferred. struct net_device synchronization rules ======================================= -dev->open: +ndo_open: Synchronization: rtnl_lock() semaphore. Context: process -dev->stop: +ndo_stop: Synchronization: rtnl_lock() semaphore. Context: process Note: netif_running() is guaranteed false -dev->do_ioctl: +ndo_do_ioctl: Synchronization: rtnl_lock() semaphore. Context: process -dev->get_stats: +ndo_get_stats: Synchronization: dev_base_lock rwlock. Context: nominally process, but don't sleep inside an rwlock -dev->hard_start_xmit: +ndo_start_xmit: Synchronization: __netif_tx_lock spinlock. When the driver sets NETIF_F_LLTX in dev->features this will be @@ -86,12 +86,12 @@ dev->hard_start_xmit: o NETDEV_TX_LOCKED Locking failed, please retry quickly. Only valid when NETIF_F_LLTX is set. -dev->tx_timeout: +ndo_tx_timeout: Synchronization: netif_tx_lock spinlock; all TX queues frozen. Context: BHs disabled Notes: netif_queue_stopped() is guaranteed true -dev->set_rx_mode: +ndo_set_rx_mode: Synchronization: netif_addr_lock spinlock. Context: BHs disabled @@ -99,7 +99,7 @@ struct napi_struct synchronization rules ======================================== napi->poll: Synchronization: NAPI_STATE_SCHED bit in napi->state. Device - driver's dev->close method will invoke napi_disable() on + driver's ndo_stop method will invoke napi_disable() on all NAPI instances which will do a sleeping poll on the NAPI_STATE_SCHED napi->state bit, waiting for all pending NAPI activity to cease. -- cgit v0.10.2 From de7aca16fd6c32719b6a7d4480b8f4685f69f7ff Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Apr 2012 14:40:06 +0000 Subject: doc, net: Remove instruction to set net_device::trans_start Commit 08baf561083bc27a953aa087dd8a664bb2b88e8e ('net: txq_trans_update() helper') made it unnecessary for most drivers to set net_device::trans_start (or netdev_queue::trans_start). Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/Documentation/networking/driver.txt b/Documentation/networking/driver.txt index 83ce060..2128e41 100644 --- a/Documentation/networking/driver.txt +++ b/Documentation/networking/driver.txt @@ -58,13 +58,10 @@ Transmit path guidelines: TX_BUFFS_AVAIL(dp) > 0) netif_wake_queue(dp->dev); -2) Do not forget to update netdev->trans_start to jiffies after - each new tx packet is given to the hardware. - -3) An ndo_start_xmit method must not modify the shared parts of a +2) An ndo_start_xmit method must not modify the shared parts of a cloned SKB. -4) Do not forget that once you return 0 from your ndo_start_xmit +3) Do not forget that once you return 0 from your ndo_start_xmit method, it is your driver's responsibility to free up the SKB and in some finite amount of time. -- cgit v0.10.2 From e34fac1c2e9ec531c2d63a5e3aa9a6d0ef36a1d3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Apr 2012 14:40:25 +0000 Subject: doc, net: Update ndo_start_xmit return type and values Commit dc1f8bf68b311b1537cb65893430b6796118498a ('netdev: change transmit to limited range type') changed the required return type and 9a1654ba0b50402a6bd03c7b0fe9b0200a5ea7b1 ('net: Optimize hard_start_xmit() return checking') changed the valid numerical return values. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/Documentation/networking/driver.txt b/Documentation/networking/driver.txt index 2128e41..da59e28 100644 --- a/Documentation/networking/driver.txt +++ b/Documentation/networking/driver.txt @@ -2,16 +2,16 @@ Document about softnet driver issues Transmit path guidelines: -1) The ndo_start_xmit method must never return '1' under any - normal circumstances. It is considered a hard error unless +1) The ndo_start_xmit method must not return NETDEV_TX_BUSY under + any normal circumstances. It is considered a hard error unless there is no way your device can tell ahead of time when it's transmit function will become busy. Instead it must maintain the queue properly. For example, for a driver implementing scatter-gather this means: - static int drv_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) + static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb, + struct net_device *dev) { struct drv *dp = netdev_priv(dev); @@ -23,7 +23,7 @@ Transmit path guidelines: unlock_tx(dp); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } ... queue packet to card ... @@ -35,6 +35,7 @@ Transmit path guidelines: ... unlock_tx(dp); ... + return NETDEV_TX_OK; } And then at the end of your TX reclamation event handling: @@ -61,9 +62,9 @@ Transmit path guidelines: 2) An ndo_start_xmit method must not modify the shared parts of a cloned SKB. -3) Do not forget that once you return 0 from your ndo_start_xmit - method, it is your driver's responsibility to free up the SKB - and in some finite amount of time. +3) Do not forget that once you return NETDEV_TX_OK from your + ndo_start_xmit method, it is your driver's responsibility to free + up the SKB and in some finite amount of time. For example, this means that it is not allowed for your TX mitigation scheme to let TX packets "hang out" in the TX @@ -71,8 +72,9 @@ Transmit path guidelines: This error can deadlock sockets waiting for send buffer room to be freed up. - If you return 1 from the ndo_start_xmit method, you must not keep - any reference to that SKB and you must not attempt to free it up. + If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you + must not keep any reference to that SKB and you must not attempt + to free it up. Probing guidelines: -- cgit v0.10.2 From 4a7e7c2ad540e54c75489a70137bf0ec15d3a127 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 5 Apr 2012 22:17:46 +0000 Subject: netlink: fix races after skb queueing As soon as an skb is queued into socket receive_queue, another thread can consume it, so we are not allowed to reference skb anymore, or risk use after free. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 32bb753..faa48f7 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -829,12 +829,19 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, return 0; } -int netlink_sendskb(struct sock *sk, struct sk_buff *skb) +static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb) { int len = skb->len; skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, len); + return len; +} + +int netlink_sendskb(struct sock *sk, struct sk_buff *skb) +{ + int len = __netlink_sendskb(sk, skb); + sock_put(sk); return len; } @@ -957,8 +964,7 @@ static int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb) if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf && !test_bit(0, &nlk->state)) { skb_set_owner_r(skb, sk); - skb_queue_tail(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); + __netlink_sendskb(sk, skb); return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1); } return -1; @@ -1698,10 +1704,8 @@ static int netlink_dump(struct sock *sk) if (sk_filter(sk, skb)) kfree_skb(skb); - else { - skb_queue_tail(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); - } + else + __netlink_sendskb(sk, skb); return 0; } @@ -1715,10 +1719,8 @@ static int netlink_dump(struct sock *sk) if (sk_filter(sk, skb)) kfree_skb(skb); - else { - skb_queue_tail(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); - } + else + __netlink_sendskb(sk, skb); if (cb->done) cb->done(cb); -- cgit v0.10.2 From 110c43304db6f06490961529536c362d9ac5732f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 6 Apr 2012 10:49:10 +0200 Subject: net: fix a race in sock_queue_err_skb() As soon as an skb is queued into socket error queue, another thread can consume it, so we are not allowed to reference skb anymore, or risk use after free. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f223cdc..baf8d28 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3161,6 +3161,8 @@ static void sock_rmem_free(struct sk_buff *skb) */ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) { + int len = skb->len; + if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= (unsigned)sk->sk_rcvbuf) return -ENOMEM; @@ -3175,7 +3177,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) skb_queue_tail(&sk->sk_error_queue, skb); if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_data_ready(sk, skb->len); + sk->sk_data_ready(sk, len); return 0; } EXPORT_SYMBOL(sock_queue_err_skb); -- cgit v0.10.2 From e95ae5a4939c52ccab02a49238d5d15d492b2598 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 27 Mar 2012 19:31:08 +0200 Subject: xen: only check xen_platform_pci_unplug if hvm commit b9136d207f08 xen: initialize platform-pci even if xen_emul_unplug=never breaks blkfront/netfront by not loading them because of xen_platform_pci_unplug=0 and it is never set for PV guest. Signed-off-by: Andrew Jones Signed-off-by: Igor Mammedov Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 4276ab0..19b6005 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1452,7 +1452,7 @@ static int __init xlblk_init(void) if (!xen_domain()) return -ENODEV; - if (!xen_platform_pci_unplug) + if (xen_hvm_domain() && !xen_platform_pci_unplug) return -ENODEV; if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) { diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 8cc0914..ccba19c 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1957,7 +1957,7 @@ static int __init netif_init(void) if (xen_initial_domain()) return 0; - if (!xen_platform_pci_unplug) + if (xen_hvm_domain() && !xen_platform_pci_unplug) return -ENODEV; printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n"); -- cgit v0.10.2 From 2531d64b6fe2724dc432b67d8dc66bd45621da0b Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 20 Mar 2012 15:04:18 -0400 Subject: xen/x86: Workaround 'x86/ioapic: Add register level checks to detect bogus io-apic entries' The above mentioned patch checks the IOAPIC and if it contains -1, then it unmaps said IOAPIC. But under Xen we get this: BUG: unable to handle kernel NULL pointer dereference at 0000000000000040 IP: [] xen_irq_init+0x1f/0xb0 PGD 0 Oops: 0002 [#1] SMP CPU 0 Modules linked in: Pid: 1, comm: swapper/0 Not tainted 3.2.10-3.fc16.x86_64 #1 Dell Inc. Inspiron 1525 /0U990C RIP: e030:[] [] xen_irq_init+0x1f/0xb0 RSP: e02b: ffff8800d42cbb70 EFLAGS: 00010202 RAX: 0000000000000000 RBX: 00000000ffffffef RCX: 0000000000000001 RDX: 0000000000000040 RSI: 00000000ffffffef RDI: 0000000000000001 RBP: ffff8800d42cbb80 R08: ffff8800d6400000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 00000000ffffffef R13: 0000000000000001 R14: 0000000000000001 R15: 0000000000000010 FS: 0000000000000000(0000) GS:ffff8800df5fe000(0000) knlGS:0000000000000000 CS: e033 DS: 0000 ES: 0000 CR0:000000008005003b CR2: 0000000000000040 CR3: 0000000001a05000 CR4: 0000000000002660 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper/0 (pid: 1, threadinfo ffff8800d42ca000, task ffff8800d42d0000) Stack: 00000000ffffffef 0000000000000010 ffff8800d42cbbe0 ffffffff8134f157 ffffffff8100a9b2 ffffffff8182ffd1 00000000000000a0 00000000829e7384 0000000000000002 0000000000000010 00000000ffffffff 0000000000000000 Call Trace: [] xen_bind_pirq_gsi_to_irq+0x87/0x230 [] ? check_events+0x12+0x20 [] xen_register_pirq+0x82/0xe0 [] xen_register_gsi.part.2+0x4a/0xd0 [] acpi_register_gsi_xen+0x20/0x30 [] acpi_register_gsi+0xf/0x20 [] acpi_pci_irq_enable+0x12e/0x202 [] pcibios_enable_device+0x39/0x40 [] do_pci_enable_device+0x4b/0x70 [] __pci_enable_device_flags+0xa8/0xf0 [] pci_enable_device+0x13/0x20 The reason we are dying is b/c the call acpi_get_override_irq() is used, which returns the polarity and trigger for the IRQs. That function calls mp_find_ioapics to get the 'struct ioapic' structure - which along with the mp_irq[x] is used to figure out the default values and the polarity/trigger overrides. Since the mp_find_ioapics now returns -1 [b/c the IOAPIC is filled with 0xffffffff], the acpi_get_override_irq() stops trying to lookup in the mp_irq[x] the proper INT_SRV_OVR and we can't install the SCI interrupt. The proper fix for this is going in v3.5 and adds an x86_io_apic_ops struct so that platforms can override it. But for v3.4 lets carry this work-around. This patch does that by providing a slightly different variant of the fake IOAPIC entries. Signed-off-by: Konrad Rzeszutek Wilk diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 1a309ee..91dc287 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1859,6 +1859,7 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, #endif /* CONFIG_X86_64 */ static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; +static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss; static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) { @@ -1899,7 +1900,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) * We just don't map the IO APIC - all access is via * hypercalls. Keep the address in the pte for reference. */ - pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL); + pte = pfn_pte(PFN_DOWN(__pa(fake_ioapic_mapping)), PAGE_KERNEL); break; #endif @@ -2064,6 +2065,7 @@ void __init xen_init_mmu_ops(void) pv_mmu_ops = xen_mmu_ops; memset(dummy_mapping, 0xff, PAGE_SIZE); + memset(fake_ioapic_mapping, 0xfd, PAGE_SIZE); } /* Protected by xen_reservation_lock. */ -- cgit v0.10.2 From e8c9e788f493d3236809e955c9fc12625a461e09 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Thu, 22 Mar 2012 18:29:24 +0530 Subject: xen/smp: Remove unnecessary call to smp_processor_id() There is an extra and unnecessary call to smp_processor_id() in cpu_bringup(). Remove it. Signed-off-by: Srivatsa S. Bhat Signed-off-by: Konrad Rzeszutek Wilk diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 240def4..e845555 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -59,7 +59,7 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) static void __cpuinit cpu_bringup(void) { - int cpu = smp_processor_id(); + int cpu; cpu_init(); touch_softlockup_watchdog(); -- cgit v0.10.2 From 0ee46eca0476faf0e93c1387b1597b861b79711f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 2 Apr 2012 15:32:22 +0100 Subject: xen/pciback: fix XEN_PCI_OP_enable_msix result Prior to 2.6.19 and as of 2.6.31, pci_enable_msix() can return a positive value to indicate the number of vectors (less than the amount requested) that can be set up for a given device. Returning this as an operation value (secondary result) is fine, but (primary) operation results are expected to be negative (error) or zero (success) according to the protocol. With the frontend fixed to match the XenoLinux behavior, the backend can now validly return zero (success) here, passing the upper limit on the number of vectors in op->value. Signed-off-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 63616d7..97f5d26 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -234,7 +234,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, if (dev_data) dev_data->ack_intr = 0; - return result; + return result > 0 ? 0 : result; } static -- cgit v0.10.2 From f09d8432e39797abf39531f41ac8a46a3fbf442a Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 2 Apr 2012 15:22:39 +0100 Subject: xen/pcifront: avoid pci_frontend_enable_msix() falsely returning success The original XenoLinux code has always had things this way, and for compatibility reasons (in particular with a subsequent pciback adjustment) upstream Linux should behave the same way (allowing for two distinct error indications to be returned by the backend). Signed-off-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 7cf3d2f..c18fab2 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -290,6 +290,7 @@ static int pci_frontend_enable_msix(struct pci_dev *dev, } else { printk(KERN_DEBUG "enable msix get value %x\n", op.value); + err = op.value; } } else { dev_err(&dev->dev, "enable msix get err %x\n", err); -- cgit v0.10.2 From ee01e663373343c63e0e3d364d09f6155378dbcc Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Sat, 31 Mar 2012 21:37:02 -0600 Subject: cpuidle: Fix panic in CPU off-lining with no idle driver Fix a NULL pointer dereference panic in cpuidle_play_dead() during CPU off-lining when no cpuidle driver is registered. A cpuidle driver may be registered at boot-time based on CPU type. This patch allows an off-lined CPU to enter HLT-based idle in this condition. Signed-off-by: Toshi Kani Cc: Boris Ostrovsky Reviewed-by: Srivatsa S. Bhat Tested-by: Srivatsa S. Bhat Signed-off-by: Len Brown diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 3e146b2..a71376a 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -74,7 +74,7 @@ static cpuidle_enter_t cpuidle_enter_ops; /** * cpuidle_play_dead - cpu off-lining * - * Only returns in case of an error + * Returns in case of an error or no driver */ int cpuidle_play_dead(void) { @@ -83,6 +83,9 @@ int cpuidle_play_dead(void) int i, dead_state = -1; int power_usage = -1; + if (!drv) + return -ENODEV; + /* Find lowest-power state that supports long-term idle */ for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { struct cpuidle_state *s = &drv->states[i]; -- cgit v0.10.2 From f68e556e23d1a4176b563bcb25d8baf2c5313f91 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 6 Apr 2012 13:54:56 -0700 Subject: Make the "word-at-a-time" helper functions more commonly usable I have a new optimized x86 "strncpy_from_user()" that will use these same helper functions for all the same reasons the name lookup code uses them. This is preparation for that. This moves them into an architecture-specific header file. It's architecture-specific for two reasons: - some of the functions are likely to want architecture-specific implementations. Even if the current code happens to be "generic" in the sense that it should work on any little-endian machine, it's likely that the "multiply by a big constant and shift" implementation is less than optimal for an architecture that has a guaranteed fast bit count instruction, for example. - I expect that if architectures like sparc want to start playing around with this, we'll need to abstract out a few more details (in particular the actual unaligned accesses). So we're likely to have more architecture-specific stuff if non-x86 architectures start using this. (and if it turns out that non-x86 architectures don't start using this, then having it in an architecture-specific header is still the right thing to do, of course) Signed-off-by: Linus Torvalds diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h new file mode 100644 index 0000000..6fe6767 --- /dev/null +++ b/arch/x86/include/asm/word-at-a-time.h @@ -0,0 +1,46 @@ +#ifndef _ASM_WORD_AT_A_TIME_H +#define _ASM_WORD_AT_A_TIME_H + +/* + * This is largely generic for little-endian machines, but the + * optimal byte mask counting is probably going to be something + * that is architecture-specific. If you have a reliably fast + * bit count instruction, that might be better than the multiply + * and shift, for example. + */ + +#ifdef CONFIG_64BIT + +/* + * Jan Achrenius on G+: microoptimized version of + * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" + * that works for the bytemasks without having to + * mask them first. + */ +static inline long count_masked_bytes(unsigned long mask) +{ + return mask*0x0001020304050608ul >> 56; +} + +#else /* 32-bit case */ + +/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ +static inline long count_masked_bytes(long mask) +{ + /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ + long a = (0x0ff0001+mask) >> 23; + /* Fix the 1 for 00 case */ + return a & mask; +} + +#endif + +#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) + +/* Return the high bit set in the first byte that is a zero */ +static inline unsigned long has_zero(unsigned long a) +{ + return ((a - REPEAT_BYTE(0x01)) & ~a) & REPEAT_BYTE(0x80); +} + +#endif /* _ASM_WORD_AT_A_TIME_H */ diff --git a/fs/namei.c b/fs/namei.c index 1898198..0062dd1 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1407,18 +1407,9 @@ static inline int can_lookup(struct inode *inode) */ #ifdef CONFIG_DCACHE_WORD_ACCESS -#ifdef CONFIG_64BIT +#include -/* - * Jan Achrenius on G+: microoptimized version of - * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" - * that works for the bytemasks without having to - * mask them first. - */ -static inline long count_masked_bytes(unsigned long mask) -{ - return mask*0x0001020304050608ul >> 56; -} +#ifdef CONFIG_64BIT static inline unsigned int fold_hash(unsigned long hash) { @@ -1428,15 +1419,6 @@ static inline unsigned int fold_hash(unsigned long hash) #else /* 32-bit case */ -/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ -static inline long count_masked_bytes(long mask) -{ - /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ - long a = (0x0ff0001+mask) >> 23; - /* Fix the 1 for 00 case */ - return a & mask; -} - #define fold_hash(x) (x) #endif @@ -1464,17 +1446,6 @@ done: } EXPORT_SYMBOL(full_name_hash); -#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) -#define ONEBYTES REPEAT_BYTE(0x01) -#define SLASHBYTES REPEAT_BYTE('/') -#define HIGHBITS REPEAT_BYTE(0x80) - -/* Return the high bit set in the first byte that is a zero */ -static inline unsigned long has_zero(unsigned long a) -{ - return ((a - ONEBYTES) & ~a) & HIGHBITS; -} - /* * Calculate the length and hash of the path component, and * return the length of the component; @@ -1490,7 +1461,7 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp) len += sizeof(unsigned long); a = *(unsigned long *)(name+len); /* Do we have any NUL or '/' bytes in this word? */ - mask = has_zero(a) | has_zero(a ^ SLASHBYTES); + mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/')); } while (!mask); /* The mask *below* the first high bit set */ -- cgit v0.10.2 From aaef292acf3a78d9c0bb6fb72226077d286b45d7 Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Fri, 30 Mar 2012 22:40:12 +0400 Subject: MAINTAINERS: Update git url for ACPI Signed-off-by: Igor Murzov Signed-off-by: Len Brown diff --git a/MAINTAINERS b/MAINTAINERS index eecf344..c159e2f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -228,7 +228,7 @@ M: Len Brown L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ Q: http://patchwork.kernel.org/project/linux-acpi/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux S: Supported F: drivers/acpi/ F: drivers/pnp/pnpacpi/ -- cgit v0.10.2 From e1c4038282c7586c3544542b37872c434669d3ac Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Tue, 3 Apr 2012 10:24:41 -0700 Subject: tcm_fc: Add abort flag for gracefully handling exchange timeout Add abort flag and use it to terminate processing when an exchange is timed out or is reset. The abort flag is used in place of the transport_generic_free_cmd function call in the reset and timeout cases, because calling that function in that context would free memory that was in use. The aborted flag allows the lifetime to be managed in a more normal way, while truncating the processing. This change eliminates a source of memory corruption which manifested in a variety of ugly ways. (nab: Drop unused struct fc_exch *ep in ft_recv_seq) Signed-off-by: Mark Rustad Acked-by: Kiran Patil Cc: Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index 8306579..c5eb3c3 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h @@ -122,6 +122,7 @@ struct ft_cmd { /* Local sense buffer */ unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER]; u32 was_ddp_setup:1; /* Set only if ddp is setup */ + u32 aborted:1; /* Set if aborted by reset or timeout */ struct scatterlist *sg; /* Set only if DDP is setup */ u32 sg_cnt; /* No. of item in scatterlist */ }; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 62dec97..a375f25 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -121,6 +121,8 @@ int ft_queue_status(struct se_cmd *se_cmd) struct fc_exch *ep; size_t len; + if (cmd->aborted) + return 0; ft_dump_cmd(cmd, __func__); ep = fc_seq_exch(cmd->seq); lport = ep->lp; @@ -187,6 +189,8 @@ int ft_write_pending(struct se_cmd *se_cmd) ft_dump_cmd(cmd, __func__); + if (cmd->aborted) + return 0; ep = fc_seq_exch(cmd->seq); lport = ep->lp; fp = fc_frame_alloc(lport, sizeof(*txrdy)); @@ -252,10 +256,10 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg) struct ft_cmd *cmd = arg; struct fc_frame_header *fh; - if (IS_ERR(fp)) { + if (unlikely(IS_ERR(fp))) { /* XXX need to find cmd if queued */ cmd->seq = NULL; - transport_generic_free_cmd(&cmd->se_cmd, 0); + cmd->aborted = true; return; } @@ -399,6 +403,8 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd) struct se_tmr_req *tmr = se_cmd->se_tmr_req; enum fcp_resp_rsp_codes code; + if (cmd->aborted) + return 0; switch (tmr->response) { case TMR_FUNCTION_COMPLETE: code = FCP_TMF_CMPL; diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index 2b693ee..dc7c0db 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -81,6 +81,8 @@ int ft_queue_data_in(struct se_cmd *se_cmd) void *from; void *to = NULL; + if (cmd->aborted) + return 0; ep = fc_seq_exch(cmd->seq); lport = ep->lp; cmd->seq = lport->tt.seq_start_next(cmd->seq); -- cgit v0.10.2 From 06383f10c49f507220594a455c6491ca6f8c94ab Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Tue, 3 Apr 2012 10:24:52 -0700 Subject: tcm_fc: Do not free tpg structure during wq allocation failure Avoid freeing a registered tpg structure if an alloc_workqueue call fails. This fixes a bug where the failure was leaking memory associated with se_portal_group setup during the original core_tpg_register() call. Signed-off-by: Mark Rustad Acked-by: Kiran Patil Cc: Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index f357039..2948dc9 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c @@ -300,6 +300,7 @@ static struct se_portal_group *ft_add_tpg( { struct ft_lport_acl *lacl; struct ft_tpg *tpg; + struct workqueue_struct *wq; unsigned long index; int ret; @@ -321,18 +322,20 @@ static struct se_portal_group *ft_add_tpg( tpg->lport_acl = lacl; INIT_LIST_HEAD(&tpg->lun_list); - ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg, - tpg, TRANSPORT_TPG_TYPE_NORMAL); - if (ret < 0) { + wq = alloc_workqueue("tcm_fc", 0, 1); + if (!wq) { kfree(tpg); return NULL; } - tpg->workqueue = alloc_workqueue("tcm_fc", 0, 1); - if (!tpg->workqueue) { + ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg, + tpg, TRANSPORT_TPG_TYPE_NORMAL); + if (ret < 0) { + destroy_workqueue(wq); kfree(tpg); return NULL; } + tpg->workqueue = wq; mutex_lock(&ft_lport_lock); list_add_tail(&tpg->list, &lacl->tpg_list); -- cgit v0.10.2 From 0034102808e0dbbf3a2394b82b1bb40b5778de9e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 7 Apr 2012 18:30:41 -0700 Subject: Linux 3.4-rc2 diff --git a/Makefile b/Makefile index 5e637c2..0df3d00 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- cgit v0.10.2