From ea2c00095c022846dd8dfd211de05154d3e4e1b8 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 17 May 2011 15:25:37 -0700 Subject: Connector: Set the CN_NETLINK_USERS correctly The CN_NETLINK_USERS must be set to the highest valid index +1. Thanks to Evgeniy for pointing this out. Signed-off-by: K. Y. Srinivasan Acked-by: Evgeniy Polyakov Cc: stable [.39] Signed-off-by: Greg Kroah-Hartman --- include/linux/connector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/connector.h b/include/linux/connector.h index 7c60d0942adb..f696bccd48cb 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -44,7 +44,7 @@ #define CN_VAL_DRBD 0x1 #define CN_KVP_IDX 0x9 /* HyperV KVP */ -#define CN_NETLINK_USERS 9 +#define CN_NETLINK_USERS 10 /* Highest index + 1 */ /* * Maximum connector's message size. -- cgit v1.2.3 From 8de111e27688798623b9e9062235bb0cac29f599 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 27 May 2011 16:56:50 -0300 Subject: [media] lirc_dev: store cdev in irctl, up maxdevs Store the cdev pointer in struct irctl, allocated dynamically as needed, rather than having a static array. At the same time, recycle some of the saved memory to nudge the maximum number of lirc devices supported up a ways -- its not that uncommon these days, now that we have the rc-core lirc bridge driver, to see a system with at least 4 raw IR receivers. (consider a mythtv backend with several video capture devices and the possible need for IR transmit hardware). Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/lirc_dev.c | 37 +++++++++++++++++++++++++++---------- include/media/lirc_dev.h | 2 +- 2 files changed, 28 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index fd237ab120bb..27997a9ceb0d 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -55,6 +55,8 @@ struct irctl { struct lirc_buffer *buf; unsigned int chunk_size; + struct cdev *cdev; + struct task_struct *task; long jiffies_to_wait; }; @@ -62,7 +64,6 @@ struct irctl { static DEFINE_MUTEX(lirc_dev_lock); static struct irctl *irctls[MAX_IRCTL_DEVICES]; -static struct cdev cdevs[MAX_IRCTL_DEVICES]; /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; @@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = { static int lirc_cdev_add(struct irctl *ir) { - int retval; + int retval = -ENOMEM; struct lirc_driver *d = &ir->d; - struct cdev *cdev = &cdevs[d->minor]; + struct cdev *cdev; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + goto err_out; if (d->fops) { cdev_init(cdev, d->fops); @@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir) } retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor); if (retval) - return retval; + goto err_out; retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); - if (retval) + if (retval) { kobject_put(&cdev->kobj); + goto err_out; + } + + ir->cdev = cdev; + + return 0; +err_out: + kfree(cdev); return retval; } @@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d) if (MAX_IRCTL_DEVICES <= d->minor) { dev_err(d->dev, "lirc_dev: lirc_register_driver: " "\"minor\" must be between 0 and %d (%d)!\n", - MAX_IRCTL_DEVICES-1, d->minor); + MAX_IRCTL_DEVICES - 1, d->minor); err = -EBADRQC; goto out; } @@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor) if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " - "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); + "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES - 1); return -EBADRQC; } @@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor) return -ENOENT; } - cdev = &cdevs[minor]; + cdev = ir->cdev; mutex_lock(&lirc_dev_lock); @@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor) } else { lirc_irctl_cleanup(ir); cdev_del(cdev); + kfree(cdev); kfree(ir); irctls[minor] = NULL; } @@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) goto error; } - cdev = &cdevs[iminor(inode)]; + cdev = ir->cdev; if (try_module_get(cdev->owner)) { ir->open++; retval = ir->d.set_use_inc(ir->d.data); @@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open); int lirc_dev_fop_close(struct inode *inode, struct file *file) { struct irctl *ir = irctls[iminor(inode)]; - struct cdev *cdev = &cdevs[iminor(inode)]; + struct cdev *cdev; if (!ir) { printk(KERN_ERR "%s: called with invalid irctl\n", __func__); return -EINVAL; } + cdev = ir->cdev; + dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); WARN_ON(mutex_lock_killable(&lirc_dev_lock)); @@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) lirc_irctl_cleanup(ir); cdev_del(cdev); irctls[ir->d.minor] = NULL; + kfree(cdev); kfree(ir); } diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 630e702c9511..168dd0b1bae2 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -9,7 +9,7 @@ #ifndef _LINUX_LIRC_DEV_H #define _LINUX_LIRC_DEV_H -#define MAX_IRCTL_DEVICES 4 +#define MAX_IRCTL_DEVICES 8 #define BUFLEN 16 #define mod(n, div) ((n) % (div)) -- cgit v1.2.3 From c30701130cf7bff4f97a148b1bc96f878c046a40 Mon Sep 17 00:00:00 2001 From: "HeungJun, Kim" Date: Tue, 7 Jun 2011 02:00:58 -0300 Subject: [media] m5mols: Use proper email address format Signed-off-by: HeungJun, Kim Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols.h | 4 ++-- drivers/media/video/m5mols/m5mols_capture.c | 4 ++-- drivers/media/video/m5mols/m5mols_controls.c | 4 ++-- drivers/media/video/m5mols/m5mols_core.c | 4 ++-- drivers/media/video/m5mols/m5mols_reg.h | 4 ++-- include/media/m5mols.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index 9ae170935871..89d09a8914f8 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h @@ -2,10 +2,10 @@ * Header for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * 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 diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c index 751f4593da9b..d9471928369d 100644 --- a/drivers/media/video/m5mols/m5mols_capture.c +++ b/drivers/media/video/m5mols/m5mols_capture.c @@ -2,10 +2,10 @@ * The Capture code for Fujitsu M-5MOLS ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * 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 diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c index d392c83fbf05..d135d20d09cf 100644 --- a/drivers/media/video/m5mols/m5mols_controls.c +++ b/drivers/media/video/m5mols/m5mols_controls.c @@ -2,10 +2,10 @@ * Controls for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * 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 diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 9815f2c75e83..43c68f51c5ce 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -2,10 +2,10 @@ * Driver for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * 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 diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h index 5f5bdcf608b6..c755bd6edfe9 100644 --- a/drivers/media/video/m5mols/m5mols_reg.h +++ b/drivers/media/video/m5mols/m5mols_reg.h @@ -2,10 +2,10 @@ * Register map for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * 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 diff --git a/include/media/m5mols.h b/include/media/m5mols.h index 2d7e7ca2313d..aac2c0e06d5e 100644 --- a/include/media/m5mols.h +++ b/include/media/m5mols.h @@ -2,10 +2,10 @@ * Driver header for M-5MOLS 8M Pixel camera sensor with ISP * * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim, riverful.kim@samsung.com + * Author: HeungJun Kim * * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com + * Author: Dongsoo Nathaniel Kim * * 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 -- cgit v1.2.3 From c16d51a32bbb61ac8fd96f78b5ce2fccfe0fb4c3 Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Mon, 13 Jun 2011 10:11:33 +0200 Subject: amba pl011: workaround for uart registers lockup This workaround aims to break the deadlock situation which raises during continuous transfer of data for long duration over uart with hardware flow control. It is observed that CTS interrupt cannot be cleared in uart interrupt register (ICR). Hence further transfer over uart gets blocked. It is seen that during such deadlock condition ICR don't get cleared even on multiple write. This leads pass_counter to decrease and finally reach zero. This can be taken as trigger point to run this UART_BT_WA. Workaround backups the register configuration, does soft reset of UART using BIT-0 of PRCC_K_SOFTRST_SET/CLEAR registers and restores the registers. This patch also provides support for uart init and exit function calls if present. Signed-off-by: Shreshtha Kumar Sahu Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 123 +++++++++++++++++++++++++++++++++++++++- include/linux/amba/serial.h | 3 + 2 files changed, 125 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 8dc0541feecc..f5f6831b0a64 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,30 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 << 16) + +#define UART_WA_SAVE_NR 14 + +static void pl011_lockup_wa(unsigned long data); +static const u32 uart_wa_reg[UART_WA_SAVE_NR] = { + ST_UART011_DMAWM, + ST_UART011_TIMEOUT, + ST_UART011_LCRH_RX, + UART011_IBRD, + UART011_FBRD, + ST_UART011_LCRH_TX, + UART011_IFLS, + ST_UART011_XFCR, + ST_UART011_XON1, + ST_UART011_XON2, + ST_UART011_XOFF1, + ST_UART011_XOFF2, + UART011_CR, + UART011_IMSC +}; + +static u32 uart_wa_regdata[UART_WA_SAVE_NR]; +static DECLARE_TASKLET(pl011_lockup_tlet, pl011_lockup_wa, 0); + /* There is by now at least one vendor with differing details, so handle it */ struct vendor_data { unsigned int ifls; @@ -72,6 +97,7 @@ struct vendor_data { unsigned int lcrh_tx; unsigned int lcrh_rx; bool oversampling; + bool interrupt_may_hang; /* vendor-specific */ bool dma_threshold; }; @@ -90,9 +116,12 @@ static struct vendor_data vendor_st = { .lcrh_tx = ST_UART011_LCRH_TX, .lcrh_rx = ST_UART011_LCRH_RX, .oversampling = true, + .interrupt_may_hang = true, .dma_threshold = true, }; +static struct uart_amba_port *amba_ports[UART_NR]; + /* Deals with DMA transactions */ struct pl011_sgbuf { @@ -132,6 +161,7 @@ struct uart_amba_port { unsigned int lcrh_rx; /* vendor-specific */ bool autorts; char type[12]; + bool interrupt_may_hang; /* vendor-specific */ #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ bool using_tx_dma; @@ -1008,6 +1038,68 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) #endif +/* + * pl011_lockup_wa + * This workaround aims to break the deadlock situation + * when after long transfer over uart in hardware flow + * control, uart interrupt registers cannot be cleared. + * Hence uart transfer gets blocked. + * + * It is seen that during such deadlock condition ICR + * don't get cleared even on multiple write. This leads + * pass_counter to decrease and finally reach zero. This + * can be taken as trigger point to run this UART_BT_WA. + * + */ +static void pl011_lockup_wa(unsigned long data) +{ + struct uart_amba_port *uap = amba_ports[0]; + void __iomem *base = uap->port.membase; + struct circ_buf *xmit = &uap->port.state->xmit; + struct tty_struct *tty = uap->port.state->port.tty; + int buf_empty_retries = 200; + int loop; + + /* Stop HCI layer from submitting data for tx */ + tty->hw_stopped = 1; + while (!uart_circ_empty(xmit)) { + if (buf_empty_retries-- == 0) + break; + udelay(100); + } + + /* Backup registers */ + for (loop = 0; loop < UART_WA_SAVE_NR; loop++) + uart_wa_regdata[loop] = readl(base + uart_wa_reg[loop]); + + /* Disable UART so that FIFO data is flushed out */ + writew(0x00, uap->port.membase + UART011_CR); + + /* Soft reset UART module */ + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->reset) + plat->reset(); + } + + /* Restore registers */ + for (loop = 0; loop < UART_WA_SAVE_NR; loop++) + writew(uart_wa_regdata[loop] , + uap->port.membase + uart_wa_reg[loop]); + + /* Initialise the old status of the modem signals */ + uap->old_status = readw(uap->port.membase + UART01x_FR) & + UART01x_FR_MODEM_ANY; + + if (readl(base + UART011_MIS) & 0x2) + printk(KERN_EMERG "UART_BT_WA: ***FAILED***\n"); + + /* Start Tx/Rx */ + tty->hw_stopped = 0; +} + static void pl011_stop_tx(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1158,8 +1250,11 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (status & UART011_TXIS) pl011_tx_chars(uap); - if (pass_counter-- == 0) + if (pass_counter-- == 0) { + if (uap->interrupt_may_hang) + tasklet_schedule(&pl011_lockup_tlet); break; + } status = readw(uap->port.membase + UART011_MIS); } while (status != 0); @@ -1339,6 +1434,14 @@ static int pl011_startup(struct uart_port *port) writew(uap->im, uap->port.membase + UART011_IMSC); spin_unlock_irq(&uap->port.lock); + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->init) + plat->init(); + } + return 0; clk_dis: @@ -1394,6 +1497,15 @@ static void pl011_shutdown(struct uart_port *port) * Shut down the clock producer */ clk_disable(uap->clk); + + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->exit) + plat->exit(); + } + } static void @@ -1700,6 +1812,14 @@ static int __init pl011_console_setup(struct console *co, char *options) if (!uap) return -ENODEV; + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->init) + plat->init(); + } + uap->port.uartclk = clk_get_rate(uap->clk); if (options) @@ -1774,6 +1894,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; uap->fifosize = vendor->fifosize; + uap->interrupt_may_hang = vendor->interrupt_may_hang; uap->port.dev = &dev->dev; uap->port.mapbase = dev->res.start; uap->port.membase = base; diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index 5479fdc849e9..514ed45c462e 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -201,6 +201,9 @@ struct amba_pl011_data { bool (*dma_filter)(struct dma_chan *chan, void *filter_param); void *dma_rx_param; void *dma_tx_param; + void (*init) (void); + void (*exit) (void); + void (*reset) (void); }; #endif -- cgit v1.2.3 From 39785eb1d3e6c58cc8bf8f6990956a58037ecc75 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 23 Jun 2011 20:20:26 +0000 Subject: fsl-diu-fb: remove check for pixel clock ranges The Freescale DIU framebuffer driver defines two constants, MIN_PIX_CLK and MAX_PIX_CLK, that are supposed to represent the lower and upper limits of the pixel clock. These values, however, are true only for one platform clock rate (533MHz) and only for the MPC8610. So the actual range for the pixel clock is chip-specific, which means the current values are almost always wrong. The chance of an out-of-range pixel clock being used are also remote. Rather than try to detect an out-of-range clock in the DIU driver, we depend on the board-specific pixel clock function (e.g. p1022ds_set_pixel_clock) to clamp the pixel clock to a supported value. Signed-off-by: Timur Tabi Signed-off-by: Paul Mundt --- drivers/video/fsl-diu-fb.c | 16 ---------------- include/linux/fsl-diu-fb.h | 6 ------ 2 files changed, 22 deletions(-) (limited to 'include') diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index bedf5be27f05..0acc7d65aeaa 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -555,8 +555,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, static int fsl_diu_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - unsigned long htotal, vtotal; - pr_debug("check_var xres: %d\n", var->xres); pr_debug("check_var yres: %d\n", var->yres); @@ -635,20 +633,6 @@ static int fsl_diu_check_var(struct fb_var_screeninfo *var, break; } - /* If the pixclock is below the minimum spec'd value then set to - * refresh rate for 60Hz since this is supported by most monitors. - * Refer to Documentation/fb/ for calculations. - */ - if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) { - htotal = var->xres + var->right_margin + var->hsync_len + - var->left_margin; - vtotal = var->yres + var->lower_margin + var->vsync_len + - var->upper_margin; - var->pixclock = (vtotal * htotal * 6UL) / 100UL; - var->pixclock = KHZ2PICOS(var->pixclock); - pr_debug("pixclock set for 60Hz refresh = %u ps\n", - var->pixclock); - } var->height = -1; var->width = -1; diff --git a/include/linux/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h index 781d4671415f..daa9952d2174 100644 --- a/include/linux/fsl-diu-fb.h +++ b/include/linux/fsl-diu-fb.h @@ -24,12 +24,6 @@ * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory() */ #define MEM_ALLOC_THRESHOLD (1024*768*4+32) -/* Minimum value that the pixel clock can be set to in pico seconds - * This is determined by platform clock/3 where the minimum platform - * clock is 533MHz. This gives 5629 pico seconds. - */ -#define MIN_PIX_CLK 5629 -#define MAX_PIX_CLK 96096 #include -- cgit v1.2.3 From a66b98db570a638afd909459e1e6bfa272344bd3 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Thu, 23 Jun 2011 00:00:24 +0300 Subject: mac80211: fix rx->key NULL dereference during mic failure Sometimes when reporting a MIC failure rx->key may be unset. This code path is hit when receiving a packet meant for a multicast address, and decryption is performed in HW. Fortunately, the failing key_idx is not used for anything up to (and including) usermode, so we allow ourselves to drop it on the way up when a key cannot be retrieved. Signed-off-by: Arik Nemtsov Cc: stable@kernel.org Signed-off-by: John W. Linville --- include/net/cfg80211.h | 2 +- net/mac80211/wpa.c | 8 +++++++- net/wireless/nl80211.c | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0589f554788a..396e8fc8910e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2688,7 +2688,7 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, * @dev: network device * @addr: The source MAC address of the frame * @key_type: The key type that the received frame used - * @key_id: Key identifier (0..3) + * @key_id: Key identifier (0..3). Can be -1 if missing. * @tsc: The TSC value of the frame that generated the MIC failure (6 octets) * @gfp: allocation flags * diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 9dc3b5f26e80..d91c1a26630d 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -154,7 +154,13 @@ update_iv: return RX_CONTINUE; mic_fail: - mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, + /* + * In some cases the key can be unset - e.g. a multicast packet, in + * a driver that supports HW encryption. Send up the key idx only if + * the key is set. + */ + mac80211_ev_michael_mic_failure(rx->sdata, + rx->key ? rx->key->conf.keyidx : -1, (void *) skb->data, NULL, GFP_ATOMIC); return RX_DROP_UNUSABLE; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 98fa8eb6cc4b..f07602d7bf68 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6463,7 +6463,8 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, if (addr) NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); + if (key_id != -1) + NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); if (tsc) NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc); -- cgit v1.2.3 From 15b493d11fcce3c5547e3d7fb6d90e11ffe12777 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 28 Jun 2011 09:48:48 +0200 Subject: drbd: fix limit define, we support 1 PiByte now Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- include/linux/drbd_limits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h index 246f576c981d..447c36752385 100644 --- a/include/linux/drbd_limits.h +++ b/include/linux/drbd_limits.h @@ -117,10 +117,10 @@ /* drbdsetup XY resize -d Z * you are free to reduce the device size to nothing, if you want to. * the upper limit with 64bit kernel, enough ram and flexible meta data - * is 16 TB, currently. */ + * is 1 PiB, currently. */ /* DRBD_MAX_SECTORS */ #define DRBD_DISK_SIZE_SECT_MIN 0 -#define DRBD_DISK_SIZE_SECT_MAX (16 * (2LLU << 30)) +#define DRBD_DISK_SIZE_SECT_MAX (1 * (2LLU << 40)) #define DRBD_DISK_SIZE_SECT_DEF 0 /* = disabled = no user size... */ #define DRBD_ON_IO_ERROR_DEF EP_PASS_ON -- cgit v1.2.3 From 4f3c7a18d9e8a287d31f828a259d713fe4859471 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Jun 2011 15:08:04 +0200 Subject: ALSA: sb16 - Fix build errors on MIPS and others with 13bit ioctl size One of ioctl definition in sound/sb16_csp.h contains the data size over 8kB, and this causes build errors on architectures like MIPS, which define _IOC_SIZEBITS=13. For avoiding this build errors but keeping the compatibility, manually expand with _IOC() instead of using _IOW() for the problematic ioctl. Signed-off-by: Takashi Iwai --- include/sound/sb16_csp.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h index 736eac71d053..af1b49e982df 100644 --- a/include/sound/sb16_csp.h +++ b/include/sound/sb16_csp.h @@ -99,7 +99,14 @@ struct snd_sb_csp_info { /* get CSP information */ #define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info) /* load microcode to CSP */ -#define SNDRV_SB_CSP_IOCTL_LOAD_CODE _IOW('H', 0x11, struct snd_sb_csp_microcode) +/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits) + * defined for some architectures like MIPS, and it leads to build errors. + * (x86 and co have 14-bit size, thus it's valid, though.) + * As a workaround for skipping the size-limit check, here we don't use the + * normal _IOW() macro but _IOC() with the manual argument. + */ +#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \ + _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode)) /* unload microcode from CSP */ #define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) /* start CSP */ -- cgit v1.2.3 From 957c665f37007de93ccbe45902a23143724170d0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 24 Jun 2011 15:25:00 -0700 Subject: ipv6: Don't put artificial limit on routing table size. IPV6, unlike IPV4, doesn't have a routing cache. Routing table entries, as well as clones made in response to route lookup requests, all live in the same table. And all of these things are together collected in the destination cache table for ipv6. This means that routing table entries count against the garbage collection limits, even though such entries cannot ever be reclaimed and are added explicitly by the administrator (rather than being created in response to lookups). Therefore it makes no sense to count ipv6 routing table entries against the GC limits. Add a DST_NOCOUNT destination cache entry flag, and skip the counting if it is set. Use this flag bit in ipv6 when adding routing table entries. Signed-off-by: David S. Miller --- include/net/dst.h | 1 + net/core/dst.c | 6 ++++-- net/ipv6/route.c | 13 +++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/net/dst.h b/include/net/dst.h index 7d15d238b6ec..e12ddfb9eb16 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -77,6 +77,7 @@ struct dst_entry { #define DST_NOPOLICY 0x0004 #define DST_NOHASH 0x0008 #define DST_NOCACHE 0x0010 +#define DST_NOCOUNT 0x0020 union { struct dst_entry *next; struct rtable __rcu *rt_next; diff --git a/net/core/dst.c b/net/core/dst.c index 9ccca038444f..6135f3671692 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -190,7 +190,8 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, dst->lastuse = jiffies; dst->flags = flags; dst->next = NULL; - dst_entries_add(ops, 1); + if (!(flags & DST_NOCOUNT)) + dst_entries_add(ops, 1); return dst; } EXPORT_SYMBOL(dst_alloc); @@ -243,7 +244,8 @@ again: neigh_release(neigh); } - dst_entries_add(dst->ops, -1); + if (!(dst->flags & DST_NOCOUNT)) + dst_entries_add(dst->ops, -1); if (dst->ops->destroy) dst->ops->destroy(dst); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2af4da074b0..0ef1f086feb8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -228,9 +228,10 @@ static struct rt6_info ip6_blk_hole_entry_template = { /* allocate dst with ip6_dst_ops */ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, - struct net_device *dev) + struct net_device *dev, + int flags) { - struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, 0); + struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); @@ -1042,7 +1043,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, if (unlikely(idev == NULL)) return NULL; - rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); if (unlikely(rt == NULL)) { in6_dev_put(idev); goto out; @@ -1206,7 +1207,7 @@ int ip6_route_add(struct fib6_config *cfg) goto out; } - rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL); + rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); if (rt == NULL) { err = -ENOMEM; @@ -1726,7 +1727,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) { struct net *net = dev_net(ort->rt6i_dev); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, - ort->dst.dev); + ort->dst.dev, 0); if (rt) { rt->dst.input = ort->dst.input; @@ -2005,7 +2006,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, { struct net *net = dev_net(idev->dev); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, - net->loopback_dev); + net->loopback_dev, 0); struct neighbour *neigh; if (rt == NULL) { -- cgit v1.2.3 From e4c2fb0d5776b58049d2556b456144a4db3fe5a9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 5 Jul 2011 10:56:32 +0200 Subject: sched: Disable (revert) SCHED_LOAD_SCALE increase Alex reported that commit c8b281161df ("sched: Increase SCHED_LOAD_SCALE resolution") caused a power usage regression under light load as it increases the number of load-balance operations and keeps idle cpus from staying idle. Time has run out to find the root cause for this release so disable the feature for v3.0 until we can figure out what causes the problem. Reported-by: "Alex, Shi" Signed-off-by: Peter Zijlstra Cc: Nikhil Rao Cc: Ming Lei Cc: Mike Galbraith Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/n/tip-m4onxn0sxnyn5iz9o88eskc3@git.kernel.org Signed-off-by: Ingo Molnar --- include/linux/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sched.h b/include/linux/sched.h index a837b20ba190..496770a96487 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -808,7 +808,7 @@ enum cpu_idle_type { * when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the * increased costs. */ -#if BITS_PER_LONG > 32 +#if 0 /* BITS_PER_LONG > 32 -- currently broken: it increases power usage under light load */ # define SCHED_LOAD_RESOLUTION 10 # define scale_load(w) ((w) << SCHED_LOAD_RESOLUTION) # define scale_load_down(w) ((w) >> SCHED_LOAD_RESOLUTION) -- cgit v1.2.3 From e206fc5e3de0e38a35b6f92941c913b6d8343fc6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 13 Jun 2011 09:34:56 -0300 Subject: [media] v4l2-subdev.h: remove unused s_mode tuner op s_mode is no longer used, so remove it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 1562c4ff3a65..224502067c43 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -173,16 +173,13 @@ struct v4l2_subdev_core_ops { struct v4l2_event_subscription *sub); }; -/* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio. - - s_radio: v4l device was opened in Radio mode, to be replaced by s_mode. +/* s_radio: v4l device was opened in radio mode. s_type_addr: sets tuner type and its I2C addr. s_config: sets tda9887 specific stuff, like port1, port2 and qss */ struct v4l2_subdev_tuner_ops { - int (*s_mode)(struct v4l2_subdev *sd, enum v4l2_tuner_type); int (*s_radio)(struct v4l2_subdev *sd); int (*s_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); -- cgit v1.2.3 From 338e9e1ad541cbb2a3fa5839376ff6c138d40301 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 13 Jun 2011 09:35:56 -0300 Subject: [media] tuner-core/v4l2-subdev: document that the type field has to be filled in The tuner ops g_frequency, g_tuner and s_tuner require that the tuner type field is filled in. Document this. The tuner-core doc is based on a patch from Mauro Carvalho Chehab . Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 29 +++++++++++++++++++++++++++++ include/media/v4l2-subdev.h | 7 +++++++ 2 files changed, 36 insertions(+) (limited to 'include') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 1843fc293322..6c007aa00236 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1117,6 +1117,16 @@ static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) return 0; } +/** + * tuner_g_frequency - Get the tuned frequency for the tuner + * @sd: pointer to struct v4l2_subdev + * @f: pointer to struct v4l2_frequency + * + * At return, the structure f will be filled with tuner frequency + * if the tuner matches the f->type. + * Note: f->type should be initialized before calling it. + * This is done by either video_ioctl2 or by the bridge driver. + */ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) { struct tuner *t = to_tuner(sd); @@ -1139,6 +1149,16 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) return 0; } +/** + * tuner_g_tuner - Fill in tuner information + * @sd: pointer to struct v4l2_subdev + * @vt: pointer to struct v4l2_tuner + * + * At return, the structure vt will be filled with tuner information + * if the tuner matches vt->type. + * Note: vt->type should be initialized before calling it. + * This is done by either video_ioctl2 or by the bridge driver. + */ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) { struct tuner *t = to_tuner(sd); @@ -1179,6 +1199,15 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } +/** + * tuner_s_tuner - Set the tuner's audio mode + * @sd: pointer to struct v4l2_subdev + * @vt: pointer to struct v4l2_tuner + * + * Sets the audio mode if the tuner matches vt->type. + * Note: vt->type should be initialized before calling it. + * This is done by either video_ioctl2 or by the bridge driver. + */ static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) { struct tuner *t = to_tuner(sd); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 224502067c43..2884e3e69cb1 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -175,6 +175,13 @@ struct v4l2_subdev_core_ops { /* s_radio: v4l device was opened in radio mode. + g_frequency: freq->type must be filled in. Normally done by video_ioctl2 + or the bridge driver. + + g_tuner: + s_tuner: vt->type must be filled in. Normally done by video_ioctl2 or the + bridge driver. + s_type_addr: sets tuner type and its I2C addr. s_config: sets tda9887 specific stuff, like port1, port2 and qss -- cgit v1.2.3 From c902ce1bfb40d8b049bd2319b388b4b68b04bc27 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Jul 2011 12:19:48 +0100 Subject: FS-Cache: Add a helper to bulk uncache pages on an inode Add an FS-Cache helper to bulk uncache pages on an inode. This will only work for the circumstance where the pages in the cache correspond 1:1 with the pages attached to an inode's page cache. This is required for CIFS and NFS: When disabling inode cookie, we were returning the cookie and setting cifsi->fscache to NULL but failed to invalidate any previously mapped pages. This resulted in "Bad page state" errors and manifested in other kind of errors when running fsstress. Fix it by uncaching mapped pages when we disable the inode cookie. This patch should fix the following oops and "Bad page state" errors seen during fsstress testing. ------------[ cut here ]------------ kernel BUG at fs/cachefiles/namei.c:201! invalid opcode: 0000 [#1] SMP Pid: 5, comm: kworker/u:0 Not tainted 2.6.38.7-30.fc15.x86_64 #1 Bochs Bochs RIP: 0010: cachefiles_walk_to_object+0x436/0x745 [cachefiles] RSP: 0018:ffff88002ce6dd00 EFLAGS: 00010282 RAX: ffff88002ef165f0 RBX: ffff88001811f500 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000100 RDI: 0000000000000282 RBP: ffff88002ce6dda0 R08: 0000000000000100 R09: ffffffff81b3a300 R10: 0000ffff00066c0a R11: 0000000000000003 R12: ffff88002ae54840 R13: ffff88002ae54840 R14: ffff880029c29c00 R15: ffff88001811f4b0 FS: 00007f394dd32720(0000) GS:ffff88002ef00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00007fffcb62ddf8 CR3: 000000001825f000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process kworker/u:0 (pid: 5, threadinfo ffff88002ce6c000, task ffff88002ce55cc0) Stack: 0000000000000246 ffff88002ce55cc0 ffff88002ce6dd58 ffff88001815dc00 ffff8800185246c0 ffff88001811f618 ffff880029c29d18 ffff88001811f380 ffff88002ce6dd50 ffffffff814757e4 ffff88002ce6dda0 ffffffff8106ac56 Call Trace: cachefiles_lookup_object+0x78/0xd4 [cachefiles] fscache_lookup_object+0x131/0x16d [fscache] fscache_object_work_func+0x1bc/0x669 [fscache] process_one_work+0x186/0x298 worker_thread+0xda/0x15d kthread+0x84/0x8c kernel_thread_helper+0x4/0x10 RIP cachefiles_walk_to_object+0x436/0x745 [cachefiles] ---[ end trace 1d481c9af1804caa ]--- I tested the uncaching by the following means: (1) Create a big file on my NFS server (104857600 bytes). (2) Read the file into the cache with md5sum on the NFS client. Look in /proc/fs/fscache/stats: Pages : mrk=25601 unc=0 (3) Open the file for read/write ("bash 5<>/warthog/bigfile"). Look in proc again: Pages : mrk=25601 unc=25601 Reported-by: Jeff Layton Signed-off-by: David Howells Reviewed-and-Tested-by: Suresh Jayaraman cc: stable@kernel.org Signed-off-by: Linus Torvalds --- Documentation/filesystems/caching/netfs-api.txt | 16 +++++++++ fs/cifs/fscache.c | 1 + fs/fscache/page.c | 44 +++++++++++++++++++++++++ fs/nfs/fscache.c | 8 ++--- include/linux/fscache.h | 21 ++++++++++++ 5 files changed, 85 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt index a167ab876c35..7cc6bf2871eb 100644 --- a/Documentation/filesystems/caching/netfs-api.txt +++ b/Documentation/filesystems/caching/netfs-api.txt @@ -673,6 +673,22 @@ storage request to complete, or it may attempt to cancel the storage request - in which case the page will not be stored in the cache this time. +BULK INODE PAGE UNCACHE +----------------------- + +A convenience routine is provided to perform an uncache on all the pages +attached to an inode. This assumes that the pages on the inode correspond on a +1:1 basis with the pages in the cache. + + void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie, + struct inode *inode); + +This takes the netfs cookie that the pages were cached with and the inode that +the pages are attached to. This function will wait for pages to finish being +written to the cache and for the cache to finish with the page generally. No +error is returned. + + ========================== INDEX AND DATA FILE UPDATE ========================== diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index 816696621ec9..42e5363b4102 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -92,6 +92,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode) if (cifsi->fscache) { cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); + fscache_uncache_all_inode_pages(cifsi->fscache, inode); fscache_relinquish_cookie(cifsi->fscache, 1); cifsi->fscache = NULL; } diff --git a/fs/fscache/page.c b/fs/fscache/page.c index a2a5d19ece6a..2f343b4d7a7d 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -954,3 +954,47 @@ void fscache_mark_pages_cached(struct fscache_retrieval *op, pagevec_reinit(pagevec); } EXPORT_SYMBOL(fscache_mark_pages_cached); + +/* + * Uncache all the pages in an inode that are marked PG_fscache, assuming them + * to be associated with the given cookie. + */ +void __fscache_uncache_all_inode_pages(struct fscache_cookie *cookie, + struct inode *inode) +{ + struct address_space *mapping = inode->i_mapping; + struct pagevec pvec; + pgoff_t next; + int i; + + _enter("%p,%p", cookie, inode); + + if (!mapping || mapping->nrpages == 0) { + _leave(" [no pages]"); + return; + } + + pagevec_init(&pvec, 0); + next = 0; + while (next <= (loff_t)-1 && + pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE) + ) { + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + pgoff_t page_index = page->index; + + ASSERTCMP(page_index, >=, next); + next = page_index + 1; + + if (PageFsCache(page)) { + __fscache_wait_on_page_write(cookie, page); + __fscache_uncache_page(cookie, page); + } + } + pagevec_release(&pvec); + cond_resched(); + } + + _leave(""); +} +EXPORT_SYMBOL(__fscache_uncache_all_inode_pages); diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index ce153a6b3aec..419119c371bf 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -259,12 +259,10 @@ static void nfs_fscache_disable_inode_cookie(struct inode *inode) dfprintk(FSCACHE, "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode)); - /* Need to invalidate any mapped pages that were read in before - * turning off the cache. + /* Need to uncache any pages attached to this inode that + * fscache knows about before turning off the cache. */ - if (inode->i_mapping && inode->i_mapping->nrpages) - invalidate_inode_pages2(inode->i_mapping); - + fscache_uncache_all_inode_pages(NFS_I(inode)->fscache, inode); nfs_fscache_zap_inode_cookie(inode); } } diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 7c4d72f5581f..9ec20dec3353 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -204,6 +204,8 @@ extern bool __fscache_check_page_write(struct fscache_cookie *, struct page *); extern void __fscache_wait_on_page_write(struct fscache_cookie *, struct page *); extern bool __fscache_maybe_release_page(struct fscache_cookie *, struct page *, gfp_t); +extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *, + struct inode *); /** * fscache_register_netfs - Register a filesystem as desiring caching services @@ -643,4 +645,23 @@ bool fscache_maybe_release_page(struct fscache_cookie *cookie, return false; } +/** + * fscache_uncache_all_inode_pages - Uncache all an inode's pages + * @cookie: The cookie representing the inode's cache object. + * @inode: The inode to uncache pages from. + * + * Uncache all the pages in an inode that are marked PG_fscache, assuming them + * to be associated with the given cookie. + * + * This function may sleep. It will wait for pages that are being written out + * and will wait whilst the PG_fscache mark is removed by the cache. + */ +static inline +void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie, + struct inode *inode) +{ + if (fscache_cookie_valid(cookie)) + __fscache_uncache_all_inode_pages(cookie, inode); +} + #endif /* _LINUX_FSCACHE_H */ -- cgit v1.2.3 From f607e7fc5fb94d92030c4527287e9c149ddf9e65 Mon Sep 17 00:00:00 2001 From: Jean-François Dagenais Date: Fri, 8 Jul 2011 15:39:44 -0700 Subject: w1: ds1wm: add a reset recovery parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a regression in 3.0 reported by Paul Parsons regarding the removal of the msleep(1) in the ds1wm_reset() function: : The linux-3.0-rc4 DS1WM 1-wire driver is logging "bus error, retrying" : error messages on an HP iPAQ hx4700 PDA (XScale-PXA270): : : : Driver for 1-wire Dallas network protocol. : DS1WM w1 busmaster driver - (c) 2004 Szabolcs Gyurko : 1-Wire driver for the DS2760 battery monitor chip - (c) 2004-2005, Szabolcs Gyurko : ds1wm ds1wm: pass: 1 bus error, retrying : ds1wm ds1wm: pass: 2 bus error, retrying : ds1wm ds1wm: pass: 3 bus error, retrying : ds1wm ds1wm: pass: 4 bus error, retrying : ds1wm ds1wm: pass: 5 bus error, retrying : ... : : The visible result is that the battery charging LED is erratic; sometimes : it works, mostly it doesn't. : : The linux-2.6.39 DS1WM 1-wire driver worked OK. I haven't tried 3.0-rc1, : 3.0-rc2, or 3.0-rc3. This sleep should not be required on normal circuitry provided the pull-ups on the bus are correctly adapted to the slaves. Unfortunately, this is not always the case. The sleep is restored but as a parameter to the probe function in the pdata. [akpm@linux-foundation.org: coding-style fixes] Reported-by: Paul Parsons Tested-by: Paul Parsons Signed-off-by: Jean-François Dagenais Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mfd/asic3.c | 1 + drivers/mfd/htc-pasic3.c | 1 + drivers/w1/masters/ds1wm.c | 5 +++++ include/linux/mfd/ds1wm.h | 7 +++++++ 4 files changed, 14 insertions(+) (limited to 'include') diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index c27fd1fc3b86..c71ae09430c5 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -619,6 +619,7 @@ static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk) /* MFD cells (SPI, PWM, LED, DS1WM, MMC) */ static struct ds1wm_driver_data ds1wm_pdata = { .active_high = 1, + .reset_recover_delay = 1, }; static struct resource ds1wm_resources[] = { diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 2808bd125d13..04c7093d6499 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -99,6 +99,7 @@ static int ds1wm_disable(struct platform_device *pdev) static struct ds1wm_driver_data ds1wm_pdata = { .active_high = 0, + .reset_recover_delay = 1, }; static struct resource ds1wm_resources[] __initdata = { diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index ad57593d224a..a0c8965c1a79 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c @@ -109,6 +109,7 @@ struct ds1wm_data { /* byte to write that makes all intr disabled, */ /* considering active_state (IAS) (optimization) */ u8 int_en_reg_none; + unsigned int reset_recover_delay; /* see ds1wm.h */ }; static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg, @@ -187,6 +188,9 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data) return 1; } + if (ds1wm_data->reset_recover_delay) + msleep(ds1wm_data->reset_recover_delay); + return 0; } @@ -490,6 +494,7 @@ static int ds1wm_probe(struct platform_device *pdev) } ds1wm_data->irq = res->start; ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0); + ds1wm_data->reset_recover_delay = plat->reset_recover_delay; if (res->flags & IORESOURCE_IRQ_HIGHEDGE) irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); diff --git a/include/linux/mfd/ds1wm.h b/include/linux/mfd/ds1wm.h index be469a357cbb..38a372a0e285 100644 --- a/include/linux/mfd/ds1wm.h +++ b/include/linux/mfd/ds1wm.h @@ -3,4 +3,11 @@ struct ds1wm_driver_data { int active_high; int clock_rate; + /* in milliseconds, the amount of time to */ + /* sleep following a reset pulse. Zero */ + /* should work if your bus devices recover*/ + /* time respects the 1-wire spec since the*/ + /* ds1wm implements the precise timings of*/ + /* a reset pulse/presence detect sequence.*/ + unsigned int reset_recover_delay; }; -- cgit v1.2.3