From 96266edf0e9e9679664e6fc07eccfd4c02516dc8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:17 +0200 Subject: [PATCH 0001/1071] usb: gadget: make g_printer enumerate again commit 5a175bb84d7344fbe5e26cf61b597129e7c80564 upstream. This was broken in 2e87edf49 ("usb: gadget: make g_printer use composite"). The USB-strings were not setup properly and were not used. No function was added which results in an empty USB config. While fixing this, the interface number is now auto generated and not hard coded to 0. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/printer.c | 128 ++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 63 deletions(-) diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index f1f9290a2f47d1..75876155797cb6 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -141,18 +141,14 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); * descriptors are built on demand. */ -#define STRING_MANUFACTURER 1 -#define STRING_PRODUCT 2 -#define STRING_SERIALNUM 3 +#define STRING_MANUFACTURER 0 +#define STRING_PRODUCT 1 +#define STRING_SERIALNUM 2 /* holds our biggest descriptor */ #define USB_DESC_BUFSIZE 256 #define USB_BUFSIZE 8192 -/* This device advertises one configuration. */ -#define DEV_CONFIG_VALUE 1 -#define PRINTER_INTERFACE 0 - static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -162,16 +158,12 @@ static struct usb_device_descriptor device_desc = { .bDeviceProtocol = 0, .idVendor = cpu_to_le16(PRINTER_VENDOR_NUM), .idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM), - .iManufacturer = STRING_MANUFACTURER, - .iProduct = STRING_PRODUCT, - .iSerialNumber = STRING_SERIALNUM, .bNumConfigurations = 1 }; static struct usb_interface_descriptor intf_desc = { .bLength = sizeof intf_desc, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = PRINTER_INTERFACE, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_PRINTER, .bInterfaceSubClass = 1, /* Printer Sub-Class */ @@ -260,9 +252,9 @@ static char pnp_string [1024] = /* static strings, in UTF-8 */ static struct usb_string strings [] = { - { STRING_MANUFACTURER, manufacturer, }, - { STRING_PRODUCT, product_desc, }, - { STRING_SERIALNUM, serial_num, }, + [STRING_MANUFACTURER].s = manufacturer, + [STRING_PRODUCT].s = product_desc, + [STRING_SERIALNUM].s = serial_num, { } /* end of list */ }; @@ -871,25 +863,13 @@ static int set_interface(struct printer_dev *dev, unsigned number) int result = 0; /* Free the current interface */ - switch (dev->interface) { - case PRINTER_INTERFACE: - printer_reset_interface(dev); - break; - } + printer_reset_interface(dev); - switch (number) { - case PRINTER_INTERFACE: - result = set_printer_interface(dev); - if (result) { - printer_reset_interface(dev); - } else { - dev->interface = PRINTER_INTERFACE; - } - break; - default: - result = -EINVAL; - /* FALL THROUGH */ - } + result = set_printer_interface(dev); + if (result) + printer_reset_interface(dev); + else + dev->interface = number; if (!result) INFO(dev, "Using interface %x\n", number); @@ -972,7 +952,7 @@ static int printer_func_setup(struct usb_function *f, switch (ctrl->bRequest) { case 0: /* Get the IEEE-1284 PNP String */ /* Only one printer interface is supported. */ - if ((wIndex>>8) != PRINTER_INTERFACE) + if ((wIndex>>8) != dev->interface) break; value = (pnp_string[0]<<8)|pnp_string[1]; @@ -983,7 +963,7 @@ static int printer_func_setup(struct usb_function *f, case 1: /* Get Port Status */ /* Only one printer interface is supported. */ - if (wIndex != PRINTER_INTERFACE) + if (wIndex != dev->interface) break; *(u8 *)req->buf = dev->printer_status; @@ -992,7 +972,7 @@ static int printer_func_setup(struct usb_function *f, case 2: /* Soft Reset */ /* Only one printer interface is supported. */ - if (wIndex != PRINTER_INTERFACE) + if (wIndex != dev->interface) break; printer_soft_reset(dev); @@ -1020,6 +1000,37 @@ static int printer_func_setup(struct usb_function *f, static int __init printer_func_bind(struct usb_configuration *c, struct usb_function *f) { + struct printer_dev *dev = container_of(f, struct printer_dev, function); + struct usb_composite_dev *cdev = c->cdev; + struct usb_ep *in_ep, *out_ep; + int id; + + id = usb_interface_id(c, f); + if (id < 0) + return id; + intf_desc.bInterfaceNumber = id; + + /* all we really need is bulk IN/OUT */ + in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc); + if (!in_ep) { +autoconf_fail: + dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n", + cdev->gadget->name); + return -ENODEV; + } + in_ep->driver_data = in_ep; /* claim */ + + out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc); + if (!out_ep) + goto autoconf_fail; + out_ep->driver_data = out_ep; /* claim */ + + /* assumes that all endpoints are dual-speed */ + hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; + hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; + + dev->in_ep = in_ep; + dev->out_ep = out_ep; return 0; } @@ -1035,7 +1046,8 @@ static int printer_func_set_alt(struct usb_function *f, int ret = -ENOTSUPP; if (!alt) - ret = set_interface(dev, PRINTER_INTERFACE); + ret = set_interface(dev, intf); + return ret; } @@ -1107,13 +1119,14 @@ static int __init printer_bind_config(struct usb_configuration *c) { struct usb_gadget *gadget = c->cdev->gadget; struct printer_dev *dev; - struct usb_ep *in_ep, *out_ep; int status = -ENOMEM; int gcnum; size_t len; u32 i; struct usb_request *req; + usb_ep_autoconfig_reset(gadget); + dev = &usb_printer_gadget; dev->function.name = shortname; @@ -1125,6 +1138,10 @@ static int __init printer_bind_config(struct usb_configuration *c) dev->function.set_alt = printer_func_set_alt; dev->function.disable = printer_func_disable; + status = usb_add_function(c, &dev->function); + if (status) + return status; + /* Setup the sysfs files for the printer gadget. */ dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, NULL, "g_printer"); @@ -1169,26 +1186,6 @@ static int __init printer_bind_config(struct usb_configuration *c) pnp_string[0] = (len >> 8) & 0xFF; pnp_string[1] = len & 0xFF; - /* all we really need is bulk IN/OUT */ - usb_ep_autoconfig_reset(gadget); - in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc); - if (!in_ep) { -autoconf_fail: - dev_err(&gadget->dev, "can't autoconfigure on %s\n", - gadget->name); - return -ENODEV; - } - in_ep->driver_data = in_ep; /* claim */ - - out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc); - if (!out_ep) - goto autoconf_fail; - out_ep->driver_data = out_ep; /* claim */ - - /* assumes that all endpoints are dual-speed */ - hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; - hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; - usb_gadget_set_selfpowered(gadget); if (gadget->is_otg) { @@ -1215,9 +1212,6 @@ static int __init printer_bind_config(struct usb_configuration *c) dev->current_rx_bytes = 0; dev->current_rx_buf = NULL; - dev->in_ep = in_ep; - dev->out_ep = out_ep; - for (i = 0; i < QLEN; i++) { req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL); if (!req) { @@ -1250,8 +1244,6 @@ static int __init printer_bind_config(struct usb_configuration *c) dev->gadget = gadget; INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); - INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name, - in_ep->name); return 0; fail: @@ -1266,7 +1258,17 @@ static int printer_unbind(struct usb_composite_dev *cdev) static int __init printer_bind(struct usb_composite_dev *cdev) { - return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); + int ret; + + ret = usb_string_ids_tab(cdev, strings); + if (ret < 0) + return ret; + device_desc.iManufacturer = strings[STRING_MANUFACTURER].id; + device_desc.iProduct = strings[STRING_PRODUCT].id; + device_desc.iSerialNumber = strings[STRING_SERIALNUM].id; + + ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); + return ret; } static struct usb_composite_driver printer_driver = { From cd46958d3b8b5e3c22596c2ec3da3d8dd0501777 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:18 +0200 Subject: [PATCH 0002/1071] usb: gadget: initialize the strings in tcm_usb_gadget properly commit 18786da4853017d983ff6911648543ca617c12d1 upstream. I have no idea what I've been thinking while I was doing this in the first place. Now the strings are initialized properly and reported by lsusb. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/tcm_usb_gadget.c | 33 +++++++++++++++++------------ drivers/usb/gadget/tcm_usb_gadget.h | 14 ++++++------ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 5444866e13ef72..d37334cc7e0805 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -1977,7 +1977,6 @@ static struct usb_interface_descriptor bot_intf_desc = { .bInterfaceClass = USB_CLASS_MASS_STORAGE, .bInterfaceSubClass = USB_SC_SCSI, .bInterfaceProtocol = USB_PR_BULK, - .iInterface = USB_G_STR_INT_UAS, }; static struct usb_interface_descriptor uasp_intf_desc = { @@ -1988,7 +1987,6 @@ static struct usb_interface_descriptor uasp_intf_desc = { .bInterfaceClass = USB_CLASS_MASS_STORAGE, .bInterfaceSubClass = USB_SC_SCSI, .bInterfaceProtocol = USB_PR_UAS, - .iInterface = USB_G_STR_INT_BBB, }; static struct usb_endpoint_descriptor uasp_bi_desc = { @@ -2209,20 +2207,16 @@ static struct usb_device_descriptor usbg_device_desc = { .bDeviceClass = USB_CLASS_PER_INTERFACE, .idVendor = cpu_to_le16(UAS_VENDOR_ID), .idProduct = cpu_to_le16(UAS_PRODUCT_ID), - .iManufacturer = USB_G_STR_MANUFACTOR, - .iProduct = USB_G_STR_PRODUCT, - .iSerialNumber = USB_G_STR_SERIAL, - .bNumConfigurations = 1, }; static struct usb_string usbg_us_strings[] = { - { USB_G_STR_MANUFACTOR, "Target Manufactor"}, - { USB_G_STR_PRODUCT, "Target Product"}, - { USB_G_STR_SERIAL, "000000000001"}, - { USB_G_STR_CONFIG, "default config"}, - { USB_G_STR_INT_UAS, "USB Attached SCSI"}, - { USB_G_STR_INT_BBB, "Bulk Only Transport"}, + [USB_G_STR_MANUFACTOR].s = "Target Manufactor", + [USB_G_STR_PRODUCT].s = "Target Product", + [USB_G_STR_SERIAL].s = "000000000001", + [USB_G_STR_CONFIG].s = "default config", + [USB_G_STR_INT_UAS].s = "USB Attached SCSI", + [USB_G_STR_INT_BBB].s = "Bulk Only Transport", { }, }; @@ -2244,7 +2238,6 @@ static int guas_unbind(struct usb_composite_dev *cdev) static struct usb_configuration usbg_config_driver = { .label = "Linux Target", .bConfigurationValue = 1, - .iConfiguration = USB_G_STR_CONFIG, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; @@ -2417,6 +2410,9 @@ static int usbg_cfg_bind(struct usb_configuration *c) fu->function.disable = usbg_disable; fu->tpg = the_only_tpg_I_currently_have; + bot_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_BBB].id; + uasp_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_UAS].id; + ret = usb_add_function(c, &fu->function); if (ret) goto err; @@ -2431,6 +2427,17 @@ static int usb_target_bind(struct usb_composite_dev *cdev) { int ret; + ret = usb_string_ids_tab(cdev, usbg_us_strings); + if (ret) + return ret; + + usbg_device_desc.iManufacturer = + usbg_us_strings[USB_G_STR_MANUFACTOR].id; + usbg_device_desc.iProduct = usbg_us_strings[USB_G_STR_PRODUCT].id; + usbg_device_desc.iSerialNumber = usbg_us_strings[USB_G_STR_SERIAL].id; + usbg_config_driver.iConfiguration = + usbg_us_strings[USB_G_STR_CONFIG].id; + ret = usb_add_config(cdev, &usbg_config_driver, usbg_cfg_bind); return 0; diff --git a/drivers/usb/gadget/tcm_usb_gadget.h b/drivers/usb/gadget/tcm_usb_gadget.h index bb18999a9a8d9b..9d32ec30f4e4b2 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.h +++ b/drivers/usb/gadget/tcm_usb_gadget.h @@ -16,12 +16,14 @@ #define UASP_SS_EP_COMP_LOG_STREAMS 4 #define UASP_SS_EP_COMP_NUM_STREAMS (1 << UASP_SS_EP_COMP_LOG_STREAMS) -#define USB_G_STR_MANUFACTOR 1 -#define USB_G_STR_PRODUCT 2 -#define USB_G_STR_SERIAL 3 -#define USB_G_STR_CONFIG 4 -#define USB_G_STR_INT_UAS 5 -#define USB_G_STR_INT_BBB 6 +enum { + USB_G_STR_MANUFACTOR, + USB_G_STR_PRODUCT, + USB_G_STR_SERIAL, + USB_G_STR_CONFIG, + USB_G_STR_INT_UAS, + USB_G_STR_INT_BBB, +}; #define USB_G_ALT_INT_BBB 0 #define USB_G_ALT_INT_UAS 1 From 2f710e1def8d4639f124f06aa08bc06c142efb84 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 30 Aug 2012 18:26:25 -0300 Subject: [PATCH 0003/1071] usb: otg: mxs-phy: Fix mx23 operation commit 363366cf61c544ea476f3d220f43a95cb03014f5 upstream. Currently mx23 fails to enumerate a USB device: [ 1.300000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.520000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.740000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.960000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 2.180000] hub 1-0:1.0: unable to enumerate USB device on port 1 Use a kernel workqueue to asynchronously delay the setting of ENHOSTDISCONDETECT bit until after higher level hub connect/reset processing is complete. Prematurely setting the bit prevents the connection processing from completing and not setting it prevents disconnect from being detected. No delay is needed for clearing of ENHOSTDISCONDETECT. Successfully tested on mx23-olinuxino (micro, mini and maxi variants) and mx28evk. Signed-off-by: Mike Thompson Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/mxs-phy.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c index c1a67cb8e24483..88db976647cf35 100644 --- a/drivers/usb/otg/mxs-phy.c +++ b/drivers/usb/otg/mxs-phy.c @@ -20,6 +20,7 @@ #include #include #include +#include #define DRIVER_NAME "mxs_phy" @@ -34,9 +35,16 @@ #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) +/* + * Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit + * so that connection and reset processing can be completed for the root hub. + */ +#define MXY_PHY_ENHOSTDISCONDETECT_DELAY 250 + struct mxs_phy { struct usb_phy phy; struct clk *clk; + struct delayed_work enhostdiscondetect_work; }; #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) @@ -62,6 +70,7 @@ static int mxs_phy_init(struct usb_phy *phy) clk_prepare_enable(mxs_phy->clk); mxs_phy_hw_init(mxs_phy); + INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL); return 0; } @@ -76,13 +85,34 @@ static void mxs_phy_shutdown(struct usb_phy *phy) clk_disable_unprepare(mxs_phy->clk); } +static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws) +{ + struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy, + enhostdiscondetect_work.work); + + /* Enable HOSTDISCONDETECT after delay. */ + dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n"); + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET); +} + static int mxs_phy_on_connect(struct usb_phy *phy, int port) { + struct mxs_phy *mxs_phy = to_mxs_phy(phy); + dev_dbg(phy->dev, "Connect on port %d\n", port); - mxs_phy_hw_init(to_mxs_phy(phy)); - writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, - phy->io_priv + HW_USBPHY_CTRL_SET); + mxs_phy_hw_init(mxs_phy); + + /* + * Delay enabling ENHOSTDISCONDETECT so that connection and + * reset processing can be completed for the root hub. + */ + dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n"); + PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, + mxs_phy_enhostdiscondetect_delay); + schedule_delayed_work(&mxs_phy->enhostdiscondetect_work, + msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY)); return 0; } @@ -91,6 +121,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) { dev_dbg(phy->dev, "Disconnect on port %d\n", port); + /* No need to delay before clearing ENHOSTDISCONDETECT. */ + dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n"); writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, phy->io_priv + HW_USBPHY_CTRL_CLR); From 0eccd99ec841350981e50b36e162a5dd18873699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Sep 2012 22:02:12 +0200 Subject: [PATCH 0004/1071] USB: option: blacklist QMI interface on ZTE MF683 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 160c9425ac52cb30502be2d9c5e848cec91bb115 upstream. Interface #5 on ZTE MF683 is a QMI/wwan interface. Signed-off-by: Bjørn Mork Cc: Shawn J. Goff Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5ce88d1bc6f1e3..5f30800663b238 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -870,7 +870,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, From 7135bbef51bf1c2624c6e87952b3d1b99a9bd0ed Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Sun, 23 Sep 2012 09:57:25 +0200 Subject: [PATCH 0005/1071] USB: ftdi_sio: add TIAO USB Multi-Protocol Adapter (TUMPA) support commit 54575b05af36959dfb6a49a3e9ca0c2b456b7126 upstream. TIAO/DIYGADGET USB Multi-Protocol Adapter (TUMPA) is an FTDI FT2232H based device which provides an easily accessible JTAG, SPI, I2C, serial breakout. http://www.diygadget.com/tiao-usb-multi-protocol-adapter-jtag-spi-i2c-serial.html http://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_User%27s_Manual FTDI FT2232H provides two serial channels (A and B), but on the TUMPA channel A is dedicated to JTAG/SPI while channel B can be used for UART/RS-232: use the ftdi_jtag_quirk to expose only channel B as a usb-serial interface to userspace. Signed-off-by: Antonio Ospite Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f906b3aec2179c..b71ee32e0c4b32 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -584,6 +584,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* * ELV devices: */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 41fe5826100c0a..57c12ef6625e3c 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -517,6 +517,11 @@ */ #define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */ +/* + * TIAO product ids (FTDI_VID) + * http://www.tiaowiki.com/w/Main_Page + */ +#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */ /********************************/ From 57bbde3fc3220a82f7fb1cf0326f08b59cb3cbbe Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 19 Sep 2012 17:02:29 -0400 Subject: [PATCH 0006/1071] USB: EHCI: convert warning messages to debug-level commit d16ba48774913d244c7eb894d28d8ae2c019a827 upstream. This patch (as1606) converts two warning messages in the ehci-hcd driver to debug messages, and adds a little extra information to each. The log messages occur when an EHCI controller takes too long (more than 20 ms) to turn its async or periodic schedule on or off. If this happens at all, it's liable to happen quite often and there's no point spamming the system log with these warnings. Furthermore, there's nothing much we can do about it when the problem happens. Signed-off-by: Alan Stern Reported-and-tested-by: Thomas Voegtle Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-timer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index eb896a2c8f2ed9..20dbdcbe9b0fc1 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -118,7 +118,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci) ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); return; } - ehci_warn(ehci, "Waited too long for the async schedule status, giving up\n"); + ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", + want, actual); } ehci->ASS_poll_count = 0; @@ -163,7 +164,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci) ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); return; } - ehci_warn(ehci, "Waited too long for the periodic schedule status, giving up\n"); + ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", + want, actual); } ehci->PSS_poll_count = 0; From 782d8021f3300f226ef7000119a8c98ab91bf446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Sep 2012 22:02:03 +0200 Subject: [PATCH 0007/1071] USB: qcaux: add Pantech vendor class match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c638eb2872b3af079501e7ee44cbb8a5cce9b4b5 upstream. The three Pantech devices UML190 (106c:3716), UML290 (106c:3718) and P4200 (106c:3721) all use the same subclasses to identify vendor specific functions. Replace the existing device specific entries with generic vendor matching, adding support for the P4200. Signed-off-by: Bjørn Mork Cc: Thomas Schäfer Acked-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcaux.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index a4edc7ee9c8a02..9b1b96f2d0955d 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,8 +36,6 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 -#define PANTECH_PRODUCT_UML190_VZW 0x3716 -#define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ #define CMOTECH_VENDOR_ID 0x16d8 @@ -68,11 +66,9 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); From ccc3dda4b13170a784c7995e4bb16a4026949fb7 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Sat, 22 Sep 2012 18:11:19 +0530 Subject: [PATCH 0008/1071] usb: host: xhci: Fix Null pointer dereferencing with 71c731a for non-x86 systems commit 457a73d346187c2cc5d599072f38676f18f130e0 upstream. In 71c731a: usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware when extracting DMI strings (vendor or product_name) to mark them as quirk we may get NULL pointer in case of non-x86 systems which won't define CONFIG_DMI. Hence susbsequent strstr() calls crash while driver probing. So, returning 'false' here in case we get a NULL vendor or product_name. This is tested with ARM (exynos) system. This patch should be backported to stable kernels as old as 3.6, that contain the commit 71c731a296f1b08a3724bd1b514b64f1bda87a23 "usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware" Signed-off-by: Vivek Gautam Signed-off-by: Sarah Sharp Reported-by: Sebastian Gottschall (DD-WRT) Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6ece0ed288d4da..8e80cfd125249d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -470,6 +470,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + if (!dmi_product_name || !dmi_sys_vendor) + return false; if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) return false; From cef87aeb39d942deac8196e46c4233721357cce2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Sep 2012 08:15:21 +0100 Subject: [PATCH 0009/1071] USB: serial: fix up bug with missing {} commit 44b0f0836b62171617d56c6528c821ceaa6ea506 upstream. As reported by Fengguang: FYI, coccinelle warns about drivers/usb/serial/usb-serial.c:1415:3-51: code aligned with following code on line 1416 vim +1415 drivers/usb/serial/usb-serial.c 1412 /* we only set the reset_resume field if the serial_driver has one */ 1413 for (sd = serial_drivers; *sd; ++sd) { 1414 if ((*sd)->reset_resume) > 1415 udriver->reset_resume = usb_serial_reset_resume; > 1416 break; 1417 } Reported-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 27483f91a4a38a..667c39cbbe9796 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1426,9 +1426,10 @@ int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[] /* we only set the reset_resume field if the serial_driver has one */ for (sd = serial_drivers; *sd; ++sd) { - if ((*sd)->reset_resume) + if ((*sd)->reset_resume) { udriver->reset_resume = usb_serial_reset_resume; break; + } } rc = usb_register(udriver); From 3d6cbe2361ebbb5a0037225af0cd890e666b2ec0 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 16 Sep 2012 04:18:50 +0100 Subject: [PATCH 0010/1071] staging: speakup_soft: Fix reading of init string commit 40fe4f89671fb3c7ded94190fb267402a38b0261 upstream. softsynth_read() reads a character at a time from the init string; when it finds the null terminator it sets the initialized flag but then repeats the last character. Additionally, if the read() buffer is not big enough for the init string, the next read() will start reading from the beginning again. So the caller may never progress to reading anything else. Replace the simple initialized flag with the current position in the init string, carried over between calls. Switch to reading real data once this reaches the null terminator. (This assumes that the length of the init string can't change, which seems to be the case. Really, the string and position belong together in a per-file private struct.) Tested-by: Samuel Thibault Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/speakup_soft.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index 42cdafeea35eac..b5130c8bcb64e0 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -40,7 +40,7 @@ static int softsynth_is_alive(struct spk_synth *synth); static unsigned char get_index(void); static struct miscdevice synth_device; -static int initialized; +static int init_pos; static int misc_registered; static struct var_t vars[] = { @@ -194,7 +194,7 @@ static int softsynth_close(struct inode *inode, struct file *fp) unsigned long flags; spk_lock(flags); synth_soft.alive = 0; - initialized = 0; + init_pos = 0; spk_unlock(flags); /* Make sure we let applications go before leaving */ speakup_start_ttys(); @@ -239,13 +239,8 @@ static ssize_t softsynth_read(struct file *fp, char *buf, size_t count, ch = '\x18'; } else if (synth_buffer_empty()) { break; - } else if (!initialized) { - if (*init) { - ch = *init; - init++; - } else { - initialized = 1; - } + } else if (init[init_pos]) { + ch = init[init_pos++]; } else { ch = synth_buffer_getc(); } From 46b91997f613b86e7cf8e5afa9cea01045e2f0e1 Mon Sep 17 00:00:00 2001 From: Christopher Brannon Date: Fri, 22 Jun 2012 08:16:34 -0500 Subject: [PATCH 0011/1071] tty: keyboard.c: Remove locking from vt_get_leds. commit 157a4b311c45c9aba75a990464d9680867dc8805 upstream. There are three call sites for this function, and all three are called within a keyboard handler. kbd_event_lock is already held within keyboard handlers, so attempting to lock it in vt_get_leds causes deadlock. Signed-off-by: Christopher Brannon Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 48cc6f25cfd39c..770a8544d53a22 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1049,13 +1049,10 @@ static int kbd_update_leds_helper(struct input_handle *handle, void *data) */ int vt_get_leds(int console, int flag) { - unsigned long flags; struct kbd_struct * kbd = kbd_table + console; int ret; - spin_lock_irqsave(&kbd_event_lock, flags); ret = vc_kbd_led(kbd, flag); - spin_unlock_irqrestore(&kbd_event_lock, flags); return ret; } From 42ff6af381dff1dfbe1d819afb7639dc1a27bc02 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 26 Sep 2012 14:01:31 -0500 Subject: [PATCH 0012/1071] staging: r8712u: Do not queue cloned skb commit fa16e5ea25d7dd83f663f333e70713aa2fa5dffe upstream. Some post-3.4 kernels have a problem when a cloned skb is used in the RX path. This patch handles one such case for r8712u. The patch was suggested by Eric Dumazet. Signed-off-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 8e82ce2fee38df..88e3ca633424c7 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -1127,6 +1127,9 @@ static void recv_tasklet(void *priv) recvbuf2recvframe(padapter, pskb); skb_reset_tail_pointer(pskb); pskb->len = 0; - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); + if (!skb_cloned(pskb)) + skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); + else + consume_skb(pskb); } } From 63c50ecb1e4a027a8246b92ce20095d3a0162b5e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 24 Sep 2012 17:20:52 +0100 Subject: [PATCH 0013/1071] staging: comedi: s626: don't dereference insn->data commit b655c2c4782ed3e2e71d2608154e295a3e860311 upstream. `s626_enc_insn_config()` is incorrectly dereferencing `insn->data` which is a pointer to user memory. It should be dereferencing the separate `data` parameter that points to a copy of the data in kernel memory. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s626.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index f90578e5e72758..2b03b6834a0b47 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1868,7 +1868,7 @@ static int s626_enc_insn_config(struct comedi_device *dev, /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ k->SetMode(dev, k, Setup, TRUE); - Preload(dev, k, *(insn->data)); + Preload(dev, k, data[0]); k->PulseIndex(dev, k); SetLatchSource(dev, k, valueSrclatch); k->SetEnable(dev, k, (uint16_t) (enab != 0)); From 22d0fff1579e4d040fe22100f4712391a3c0cf4a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 27 Sep 2012 17:45:27 +0100 Subject: [PATCH 0014/1071] staging: comedi: jr3_pci: fix iomem dereference commit e1878957b4676a17cf398f7f5723b365e9a2ca48 upstream. Correct a direct dereference of I/O memory to use an appropriate I/O memory access function. Note that the pointer being dereferenced is not currently tagged with `__iomem` but I plan to correct that for 3.7. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/jr3_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 93f94cd7bae2e8..9c133a0ea8174f 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -884,7 +884,7 @@ static int jr3_pci_attach(struct comedi_device *dev, } /* Reset DSP card */ - devpriv->iobase->channel[0].reset = 0; + writel(0, &devpriv->iobase->channel[0].reset); result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware); dev_dbg(dev->class_dev, "Firmare load %d\n", result); From 4c68fab02c7b1ab1bba6abd3ac1ab06e72301128 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 18 Sep 2012 19:46:58 +0100 Subject: [PATCH 0015/1071] staging: comedi: don't dereference user memory for INSN_INTTRIG commit 5d06e3df280bd230e2eadc16372e62818c63e894 upstream. `parse_insn()` is dereferencing the user-space pointer `insn->data` directly when handling the `INSN_INTTRIG` comedi instruction. It shouldn't be using `insn->data` at all; it should be using the separate `data` pointer passed to the function. Fix it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e82126407e9559..d6972ee6c42a12 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -951,7 +951,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = -EAGAIN; break; } - ret = s->async->inttrig(dev, s, insn->data[0]); + ret = s->async->inttrig(dev, s, data[0]); if (ret >= 0) ret = 1; break; From c8181245e0031c9edcc925407bc87a17b2a06271 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 Sep 2012 19:37:39 +0100 Subject: [PATCH 0016/1071] staging: comedi: fix memory leak for saved channel list commit c8cad4c89ee3b15935c532210ae6ebb5c0a2734d upstream. When `do_cmd_ioctl()` allocates memory for the kernel copy of a channel list, it frees any previously allocated channel list in `async->cmd.chanlist` and replaces it with the new one. However, if the device is ever removed (or "detached") the cleanup code in `cleanup_device()` in "drivers.c" does not free this memory so it is lost. A sensible place to free the kernel copy of the channel list is in `do_become_nonbusy()` as at that point the comedi asynchronous command associated with the channel list is no longer valid. Free the channel list in `do_become_nonbusy()` instead of `do_cmd_ioctl()` and clear the pointer to prevent it being freed more than once. Note that `cleanup_device()` could be called at an inappropriate time while the comedi device is open, but that's a separate bug not related to this this patch. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index d6972ee6c42a12..41dea18f27cb61 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1196,7 +1196,6 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } - kfree(async->cmd.chanlist); async->cmd = user_cmd; async->cmd.data = NULL; /* load channel/gain list */ @@ -2033,6 +2032,8 @@ void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) if (async) { comedi_reset_async_buf(async); async->inttrig = NULL; + kfree(async->cmd.chanlist); + async->cmd.chanlist = NULL; } else { printk(KERN_ERR "BUG: (?) do_become_nonbusy called with async=0\n"); From 79abf5039669ff6761d785d78b0c1767811b70ae Mon Sep 17 00:00:00 2001 From: Stanislav Kozina Date: Thu, 16 Aug 2012 12:01:47 +0100 Subject: [PATCH 0017/1071] Remove BUG_ON from n_tty_read() commit e9490e93c1978b6669f3e993caa3189be13ce459 upstream. Change the BUG_ON to WARN_ON and return in case of tty->read_buf==NULL. We want to track a couple of long standing reports of this but at the same time we can avoid killing the box. Signed-off-by: Stanislav Kozina Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index ee1c268f5f9d65..26f0d0e4484bbd 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1728,7 +1728,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, do_it_again: - BUG_ON(!tty->read_buf); + if (WARN_ON(!tty->read_buf)) + return -EAGAIN; c = job_control(tty, file); if (c < 0) From 10b96fa9ff7a3607bb39548025cbad3009f7d587 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 7 Aug 2012 21:47:39 +0200 Subject: [PATCH 0018/1071] TTY: ttyprintk, don't touch behind tty->write_buf commit ee8b593affdf893012e57f4c54a21984d1b0d92e upstream. If a user provides a buffer larger than a tty->write_buf chunk and passes '\r' at the end of the buffer, we touch an out-of-bound memory. Add a check there to prevent this. Signed-off-by: Jiri Slaby Cc: Samo Pogacnik Signed-off-by: Greg Kroah-Hartman --- drivers/char/ttyprintk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 46b77ede84c01c..a7c6d6a07d3c0c 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count) tmp[tpk_curr + 1] = '\0'; printk(KERN_INFO "%s%s", tpk_tag, tmp); tpk_curr = 0; - if (buf[i + 1] == '\n') + if ((i + 1) < count && buf[i + 1] == '\n') i++; break; case '\n': From d980f62588cafb47b71a22db51b7bdebdf7f2bb8 Mon Sep 17 00:00:00 2001 From: Vikram Pandita Date: Thu, 6 Sep 2012 15:45:37 +0300 Subject: [PATCH 0019/1071] serial: omap: fix software flow control commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6 upstream. Software flow control register bits were not defined correctly. Also clarify the IXON and IXOFF logic to reflect what userspace wants. Tested-by: Shubhrajyoti D Signed-off-by: Vikram Pandita Signed-off-by: Shubhrajyoti D Acked-by: Tony Lindgren Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/include/plat/omap-serial.h | 4 ++-- drivers/tty/serial/omap-serial.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 1a52725ffcf25c..3a5764494d474d 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -42,10 +42,10 @@ #define OMAP_UART_WER_MOD_WKUP 0X7F /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x04 +#define OMAP_UART_SW_TX 0x8 /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x04 +#define OMAP_UART_SW_RX 0x2 #define OMAP_UART_SYSC_RESET 0X07 #define OMAP_UART_TCR_TRIG 0X0F diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d3cda0cb2df0a9..22992cda572b9b 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -667,19 +667,19 @@ serial_omap_configure_xonxoff /* * IXON Flag: - * Enable XON/XOFF flow control on output. - * Transmit XON1, XOFF1 + * Flow control for OMAP.TX + * OMAP.RX should listen for XON/XOFF */ if (termios->c_iflag & IXON) - up->efr |= OMAP_UART_SW_TX; + up->efr |= OMAP_UART_SW_RX; /* * IXOFF Flag: - * Enable XON/XOFF flow control on input. - * Receiver compares XON1, XOFF1. + * Flow control for OMAP.RX + * OMAP.TX should send XON/XOFF */ if (termios->c_iflag & IXOFF) - up->efr |= OMAP_UART_SW_RX; + up->efr |= OMAP_UART_SW_TX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); From f680d991564301f523f6929886bc758d253a198a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 Sep 2012 17:21:36 +0200 Subject: [PATCH 0020/1071] serial: pl011: handle corruption at high clock speeds commit c5dd553b9fd069892c9e2de734f4f604e280fa7a upstream. This works around a few glitches in the ST version of the PL011 serial driver when using very high baud rates, as we do in the Ux500: 3, 3.25, 4 and 4.05 Mbps. Problem Observed/rootcause: When using high baud-rates, and the baudrate*8 is getting close to the provided clock frequency (so a division factor close to 1), when using bursts of characters (so they are abutted), then it seems as if there is not enough time to detect the beginning of the start-bit which is a timing reference for the entire character, and thus the sampling moment of character bits is moving towards the end of each bit, instead of the middle. Fix: Increase slightly the RX baud rate of the UART above the theoretical baudrate by 5%. This will definitely give more margin time to the UART_RX to correctly sample the data at the middle of the bit period. Also fix the ages old copy-paste error in the very stressed comment, it's referencing the registers used in the PL010 driver rather than the PL011 ones. Signed-off-by: Guillaume Jaunet Signed-off-by: Christophe Arnal Signed-off-by: Matthias Locher Signed-off-by: Rajanikanth HV Cc: Bibek Basu Cc: Par-Gunnar Hjalmdahl Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d3553b5d3fcabd..762f5fda22d410 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1603,13 +1603,26 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, old_cr &= ~ST_UART011_CR_OVSFACT; } + /* + * Workaround for the ST Micro oversampling variants to + * increase the bitrate slightly, by lowering the divisor, + * to avoid delayed sampling of start bit at high speeds, + * else we see data corruption. + */ + if (uap->vendor->oversampling) { + if ((baud >= 3000000) && (baud < 3250000) && (quot > 1)) + quot -= 1; + else if ((baud > 3250000) && (quot > 2)) + quot -= 2; + } /* Set baud rate */ writew(quot & 0x3f, port->membase + UART011_FBRD); writew(quot >> 6, port->membase + UART011_IBRD); /* * ----------v----------v----------v----------v----- - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L + * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER + * UART011_FBRD & UART011_IBRD. * ----------^----------^----------^----------^----- */ writew(lcr_h, port->membase + uap->lcrh_rx); From 5ded9348b78e714abc658ce48fabf1afd438dd01 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Fri, 21 Sep 2012 21:04:34 -0300 Subject: [PATCH 0021/1071] serial: set correct baud_base for EXSYS EX-41092 Dual 16950 commit 26e8220adb0aec43b7acafa0f1431760eee28522 upstream. Apparently the same card model has two IDs, so this patch complements the commit 39aced68d664291db3324d0fcf0985ab5626aac2 adding the missing one. Signed-off-by: Flavio Leitner Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 9 +++++++-- include/linux/pci_ids.h | 1 - 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 28e7c7cce8935a..6b8fcb48f3fb70 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1164,6 +1164,8 @@ pci_xr17c154_setup(struct serial_private *priv, #define PCI_SUBDEVICE_ID_OCTPRO422 0x0208 #define PCI_SUBDEVICE_ID_POCTAL232 0x0308 #define PCI_SUBDEVICE_ID_POCTAL422 0x0408 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 #define PCI_VENDOR_ID_ADVANTECH 0x13fe #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 #define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 @@ -3232,8 +3234,11 @@ static struct pci_device_id serial_pci_tbl[] = { * For now just used the hex ID 0x950a. */ { PCI_VENDOR_ID_OXSEMI, 0x950a, - PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0, - pbn_b0_2_115200 }, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00, + 0, 0, pbn_b0_2_115200 }, + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30, + 0, 0, pbn_b0_2_115200 }, { PCI_VENDOR_ID_OXSEMI, 0x950a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_1130000 }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 6b4565c440c879..8d3c427193878d 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1847,7 +1847,6 @@ #define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 #define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 -#define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL 0x2530 #define PCI_VENDOR_ID_RADISYS 0x1331 From 115df7d533ba2c51cfe9f29cc5817bc85ad32df9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 5 Sep 2012 14:37:35 -0700 Subject: [PATCH 0022/1071] tools/hv: Fix file handle leak commit d5ab482799e7c4c4b7c0aa67e8710dce28115d03 upstream. Match up each fopen() with an fclose(). Signed-off-by: Ben Hutchings Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index d9834b36294373..a08213b2250b5e 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -144,7 +144,7 @@ static void kvp_update_file(int pool) sizeof(struct kvp_record), kvp_file_info[pool].num_records, filep); - fflush(filep); + fclose(filep); kvp_release_lock(pool); } @@ -191,6 +191,7 @@ static void kvp_update_mem_state(int pool) kvp_file_info[pool].records = record; kvp_file_info[pool].num_records = records_read; + fclose(filep); kvp_release_lock(pool); } static int kvp_file_init(void) From c08f21a0017df9e98861fe87bd4ad0a931fb5abb Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 5 Sep 2012 14:37:36 -0700 Subject: [PATCH 0023/1071] tools/hv: Fix exit() error code commit 6bb22fea25624ab593eee376fa5fb82d1b13f45a upstream. Linux native exit codes are 8-bit unsigned values. exit(-1) results in an exit code of 255, which is usually reserved for shells reporting 'command not found'. Use the portable value EXIT_FAILURE. (Not that this matters much for a daemon.) Signed-off-by: Ben Hutchings Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index a08213b2250b5e..edab6e90038a76 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -106,7 +106,7 @@ static void kvp_acquire_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } } @@ -118,7 +118,7 @@ static void kvp_release_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { perror("fcntl"); syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } } @@ -137,7 +137,7 @@ static void kvp_update_file(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } bytes_written = fwrite(kvp_file_info[pool].records, @@ -163,7 +163,7 @@ static void kvp_update_mem_state(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } while (!feof(filep)) { readp = &record[records_read]; @@ -180,7 +180,7 @@ static void kvp_update_mem_state(int pool) if (record == NULL) { syslog(LOG_ERR, "malloc failed"); - exit(-1); + exit(EXIT_FAILURE); } continue; } @@ -209,7 +209,7 @@ static int kvp_file_init(void) if (access("/var/opt/hyperv", F_OK)) { if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) { syslog(LOG_ERR, " Failed to create /var/opt/hyperv"); - exit(-1); + exit(EXIT_FAILURE); } } @@ -658,13 +658,13 @@ int main(void) if (kvp_file_init()) { syslog(LOG_ERR, "Failed to initialize the pools"); - exit(-1); + exit(EXIT_FAILURE); } fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); - exit(-1); + exit(EXIT_FAILURE); } addr.nl_family = AF_NETLINK; addr.nl_pad = 0; @@ -676,7 +676,7 @@ int main(void) if (error < 0) { syslog(LOG_ERR, "bind failed; error:%d", error); close(fd); - exit(-1); + exit(EXIT_FAILURE); } sock_opt = addr.nl_groups; setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); @@ -696,7 +696,7 @@ int main(void) if (len < 0) { syslog(LOG_ERR, "netlink_send failed; error:%d", len); close(fd); - exit(-1); + exit(EXIT_FAILURE); } pfd.fd = fd; @@ -864,7 +864,7 @@ int main(void) len = netlink_send(fd, incoming_cn_msg); if (len < 0) { syslog(LOG_ERR, "net_link send failed; error:%d", len); - exit(-1); + exit(EXIT_FAILURE); } } From 43f7940638e3135e4536c326a8eb1b9c4f66d87b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 5 Sep 2012 14:37:37 -0700 Subject: [PATCH 0024/1071] tools/hv: Check for read/write errors commit 436473bc2173499ae274d0f50111d1e355006caf upstream. hv_kvp_daemon currently does not check whether fread() or fwrite() succeed. Add the necessary checks. Also, remove the incorrect use of feof() before fread(). Signed-off-by: Ben Hutchings Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index edab6e90038a76..2984ffb7bac7aa 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -144,7 +144,12 @@ static void kvp_update_file(int pool) sizeof(struct kvp_record), kvp_file_info[pool].num_records, filep); - fclose(filep); + if (ferror(filep) || fclose(filep)) { + kvp_release_lock(pool); + syslog(LOG_ERR, "Failed to write file, pool: %d", pool); + exit(EXIT_FAILURE); + } + kvp_release_lock(pool); } @@ -165,12 +170,17 @@ static void kvp_update_mem_state(int pool) syslog(LOG_ERR, "Failed to open file, pool: %d", pool); exit(EXIT_FAILURE); } - while (!feof(filep)) { + for (;;) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK * num_blocks, filep); + if (ferror(filep)) { + syslog(LOG_ERR, "Failed to read file, pool: %d", pool); + exit(EXIT_FAILURE); + } + if (!feof(filep)) { /* * We have more data to read. @@ -233,12 +243,18 @@ static int kvp_file_init(void) fclose(filep); return 1; } - while (!feof(filep)) { + for (;;) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK, filep); + if (ferror(filep)) { + syslog(LOG_ERR, "Failed to read file, pool: %d", + i); + exit(EXIT_FAILURE); + } + if (!feof(filep)) { /* * We have more data to read. From 2975303676cea3f3d7cc076e32c1542637ef7edc Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 26 Sep 2012 12:32:02 -0500 Subject: [PATCH 0025/1071] b43legacy: Fix crash on unload when firmware not available commit 2d838bb608e2d1f6cb4280e76748cb812dc822e7 upstream. When b43legacy is loaded without the firmware being available, a following unload generates a kernel NULL pointer dereference BUG as follows: [ 214.330789] BUG: unable to handle kernel NULL pointer dereference at 0000004c [ 214.330997] IP: [] drain_workqueue+0x15/0x170 [ 214.331179] *pde = 00000000 [ 214.331311] Oops: 0000 [#1] SMP [ 214.331471] Modules linked in: b43legacy(-) ssb pcmcia mac80211 cfg80211 af_packet mperf arc4 ppdev sr_mod cdrom sg shpchp yenta_socket pcmcia_rsrc pci_hotplug pcmcia_core battery parport_pc parport floppy container ac button edd autofs4 ohci_hcd ehci_hcd usbcore usb_common thermal processor scsi_dh_rdac scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua scsi_dh fan thermal_sys hwmon ata_generic pata_ali libata [last unloaded: cfg80211] [ 214.333421] Pid: 3639, comm: modprobe Not tainted 3.6.0-rc6-wl+ #163 Source Technology VIC 9921/ALI Based Notebook [ 214.333580] EIP: 0060:[] EFLAGS: 00010246 CPU: 0 [ 214.333687] EIP is at drain_workqueue+0x15/0x170 [ 214.333788] EAX: c162ac40 EBX: cdfb8360 ECX: 0000002a EDX: 00002a2a [ 214.333890] ESI: 00000000 EDI: 00000000 EBP: cd767e7c ESP: cd767e5c [ 214.333957] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 214.333957] CR0: 8005003b CR2: 0000004c CR3: 0c96a000 CR4: 00000090 [ 214.333957] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 214.333957] DR6: ffff0ff0 DR7: 00000400 [ 214.333957] Process modprobe (pid: 3639, ti=cd766000 task=cf802e90 task.ti=cd766000) [ 214.333957] Stack: [ 214.333957] 00000292 cd767e74 c12c5e09 00000296 00000296 cdfb8360 cdfb9220 00000000 [ 214.333957] cd767e90 c104c4fd cdfb8360 cdfb9220 cd682800 cd767ea4 d0c10184 cd682800 [ 214.333957] cd767ea4 cba31064 cd767eb8 d0867908 cba31064 d087e09c cd96f034 cd767ec4 [ 214.333957] Call Trace: [ 214.333957] [] ? skb_dequeue+0x49/0x60 [ 214.333957] [] destroy_workqueue+0xd/0x150 [ 214.333957] [] ieee80211_unregister_hw+0xc4/0x100 [mac80211] [ 214.333957] [] b43legacy_remove+0x78/0x80 [b43legacy] [ 214.333957] [] ssb_device_remove+0x1d/0x30 [ssb] [ 214.333957] [] __device_release_driver+0x5a/0xb0 [ 214.333957] [] driver_detach+0x87/0x90 [ 214.333957] [] bus_remove_driver+0x6c/0xe0 [ 214.333957] [] driver_unregister+0x40/0x70 [ 214.333957] [] ssb_driver_unregister+0xb/0x10 [ssb] [ 214.333957] [] b43legacy_exit+0xd/0xf [b43legacy] [ 214.333957] [] sys_delete_module+0x14e/0x2b0 [ 214.333957] [] ? vfs_write+0xf7/0x150 [ 214.333957] [] ? tty_write_lock+0x50/0x50 [ 214.333957] [] ? sys_write+0x38/0x70 [ 214.333957] [] syscall_call+0x7/0xb [ 214.333957] Code: bc 27 00 00 00 00 a1 74 61 56 c1 55 89 e5 e8 a3 fc ff ff 5d c3 90 55 89 e5 57 56 89 c6 53 b8 40 ac 62 c1 83 ec 14 e8 bb b7 34 00 <8b> 46 4c 8d 50 01 85 c0 89 56 4c 75 03 83 0e 40 80 05 40 ac 62 [ 214.333957] EIP: [] drain_workqueue+0x15/0x170 SS:ESP 0068:cd767e5c [ 214.333957] CR2: 000000000000004c [ 214.341110] ---[ end trace c7e90ec026d875a6 ]---Index: wireless-testing/drivers/net/wireless/b43legacy/main.c The problem is fixed by making certain that the ucode pointer is not NULL before deregistering the driver in mac80211. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43legacy/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 8156135a059077..0ef08e058ec73c 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3894,6 +3894,8 @@ static void b43legacy_remove(struct ssb_device *dev) cancel_work_sync(&wl->firmware_load); B43legacy_WARN_ON(!wl); + if (!wldev->fw.ucode) + return; /* NULL if fw never loaded */ if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); From 320e71f47b21945764985786c4baa4857c8dce98 Mon Sep 17 00:00:00 2001 From: Khalid Aziz Date: Mon, 10 Sep 2012 12:52:42 -0600 Subject: [PATCH 0026/1071] firmware: Add missing attributes to EFI variable attribute print out from sysfs commit 7083909023bbe29b3176e92d2d089def1aa7aa1e upstream. Some of the EFI variable attributes are missing from print out from /sys/firmware/efi/vars/*/attributes. This patch adds those in. It also updates code to use pre-defined constants for masking current value of attributes. Signed-off-by: Khalid Aziz Reviewed-by: Kees Cook Acked-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/efivars.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 47408e802ab6ef..d10c9873dd9a86 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -435,12 +435,23 @@ efivar_attr_read(struct efivar_entry *entry, char *buf) if (status != EFI_SUCCESS) return -EIO; - if (var->Attributes & 0x1) + if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); - if (var->Attributes & 0x2) + if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); - if (var->Attributes & 0x4) + if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) + str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); + if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) + str += sprintf(str, + "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) + str += sprintf(str, + "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) + str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); return str - buf; } From ea0337dea773f15e92e491093930741c7b9f7cdd Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 19 Sep 2012 16:27:26 -0700 Subject: [PATCH 0027/1071] xhci: Intel Panther Point BEI quirk. commit 80fab3b244a22e0ca539d2439bdda50e81e5666f upstream. When a device with an isochronous endpoint is behind a hub plugged into the Intel Panther Point xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under a Panther Point xHCI host controller, if the parent hub is unplugged when one or more events from transfers with BEI set are on the event ring, a port status change event is placed on the event ring, but no interrupt is generated. This means URBs stop completing, and the USB device disconnect is not noticed. Something like a USB headset will cause mplayer to hang when the device is disconnected. If another transfer is sent (such as running `sudo lsusb -v`), the next transfer event seems to "unstick" the event ring, the xHCI driver gets an interrupt, and the disconnect is reported to the USB core. The fix is not to use the BEI flag under the Panther Point xHCI host. This will impact power consumption and system responsiveness, because the xHCI driver will receive an interrupt for every frame in all isochronous URBs instead of once per URB. Intel chipset developers confirm that this bug will be hit if the BEI flag is used on any endpoint, not just ones that are behind a hub. This patch should be backported to kernels as old as 3.0, that contain the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci-ring.c | 4 +++- drivers/usb/host/xhci.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 9bfd4ca1153c32..8345d7c23061c2 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -103,6 +103,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) * PPT chipsets. */ xhci->quirks |= XHCI_SPURIOUS_REBOOT; + xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 643c2f3f3e738e..c1df87b1c9daeb 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3400,7 +3400,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } else { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; - if (xhci->hci_version == 0x100) { + if (xhci->hci_version == 0x100 && + !(xhci->quirks & + XHCI_AVOID_BEI)) { /* Set BEI bit except for the last td */ if (i < num_tds - 1) field |= TRB_BEI; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 1a05908c66737c..e41557901e93e7 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1496,6 +1496,7 @@ struct xhci_hcd { #define XHCI_INTEL_HOST (1 << 12) #define XHCI_SPURIOUS_REBOOT (1 << 13) #define XHCI_COMP_MODE_QUIRK (1 << 14) +#define XHCI_AVOID_BEI (1 << 15) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ From ec2cbc5e8dd36c17d99cee7f270e649d3220c92c Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:30:57 +0800 Subject: [PATCH 0028/1071] xHCI: add cmd_ring_state commit c181bc5b5d5c79b71203cd10cef97f802fb6f9c1 upstream. Adding cmd_ring_state for command ring. It helps to verify the current command ring state for controlling the command ring operations. This patch should be backported to kernels as old as 3.0. The commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." papers over the NULL pointer dereference that I now believe is related to a timed out Set Address command. This (and the four patches that follow it) contain the real fix that also allows VIA USB 3.0 hubs to consistently re-enumerate during the plug/unplug stress tests. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 3 +++ drivers/usb/host/xhci.c | 6 ++++-- drivers/usb/host/xhci.h | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c1df87b1c9daeb..855a462f1c87ad 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -280,6 +280,9 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, /* Ring the host controller doorbell after placing a command on the ring */ void xhci_ring_cmd_db(struct xhci_hcd *xhci) { + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) + return; + xhci_dbg(xhci, "// Ding dong!\n"); xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8e80cfd125249d..de57002f43fe8f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -105,9 +105,10 @@ int xhci_halt(struct xhci_hcd *xhci) ret = handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (!ret) + if (!ret) { xhci->xhc_state |= XHCI_STATE_HALTED; - else + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + } else xhci_warn(xhci, "Host not halted after %u microseconds.\n", XHCI_MAX_HALT_USEC); return ret; @@ -583,6 +584,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci) return -ENODEV; } xhci->shared_hcd->state = HC_STATE_RUNNING; + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e41557901e93e7..d5d40ae7441f79 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1421,6 +1421,10 @@ struct xhci_hcd { /* data structures */ struct xhci_device_context_array *dcbaa; struct xhci_ring *cmd_ring; + unsigned int cmd_ring_state; +#define CMD_RING_STATE_RUNNING (1 << 0) +#define CMD_RING_STATE_ABORTED (1 << 1) +#define CMD_RING_STATE_STOPPED (1 << 2) unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; From f83994f3e2438b982fb9821d948199b3327638d8 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:31:12 +0800 Subject: [PATCH 0029/1071] xHCI: add aborting command ring function commit b92cc66c047ff7cf587b318fe377061a353c120f upstream. Software have to abort command ring and cancel command when a command is failed or hang. Otherwise, the command ring will hang up and can't handle the others. An example of a command that may hang is the Address Device Command, because waiting for a SET_ADDRESS request to be acknowledged by a USB device is outside of the xHC's ability to control. To cancel a command, software will initialize a command descriptor for the cancel command, and add it into a cancel_cmd_list of xhci. Sarah: Fixed missing newline on "Have the command ring been stopped?" debugging statement. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 7 +++ drivers/usb/host/xhci-ring.c | 108 +++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 12 ++++ 4 files changed, 128 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 77689bd64cace8..487bc083dead0a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1772,6 +1772,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; + struct xhci_cd *cur_cd, *next_cd; unsigned long flags; int size; int i, j, num_ports; @@ -1795,6 +1796,11 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; xhci_dbg(xhci, "Freed command ring\n"); + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } for (i = 1; i < MAX_HC_SLOTS; ++i) xhci_free_virt_device(xhci, i); @@ -2340,6 +2346,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags); if (!xhci->cmd_ring) goto fail; + INIT_LIST_HEAD(&xhci->cancel_cmd_list); xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 855a462f1c87ad..5d9956c8dbeebc 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -289,6 +289,114 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci) xhci_readl(xhci, &xhci->dba->doorbell[0]); } +static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) +{ + u64 temp_64; + int ret; + + xhci_dbg(xhci, "Abort command ring\n"); + + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) { + xhci_dbg(xhci, "The command ring isn't running, " + "Have the command ring been stopped?\n"); + return 0; + } + + temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + if (!(temp_64 & CMD_RING_RUNNING)) { + xhci_dbg(xhci, "Command ring had been stopped\n"); + return 0; + } + xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; + xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, + &xhci->op_regs->cmd_ring); + + /* Section 4.6.1.2 of xHCI 1.0 spec says software should + * time the completion od all xHCI commands, including + * the Command Abort operation. If software doesn't see + * CRR negated in a timely manner (e.g. longer than 5 + * seconds), then it should assume that the there are + * larger problems with the xHC and assert HCRST. + */ + ret = handshake(xhci, &xhci->op_regs->cmd_ring, + CMD_RING_RUNNING, 0, 5 * 1000 * 1000); + if (ret < 0) { + xhci_err(xhci, "Stopped the command ring failed, " + "maybe the host is dead\n"); + xhci->xhc_state |= XHCI_STATE_DYING; + xhci_quiesce(xhci); + xhci_halt(xhci); + return -ESHUTDOWN; + } + + return 0; +} + +static int xhci_queue_cd(struct xhci_hcd *xhci, + struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cd; + cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC); + if (!cd) + return -ENOMEM; + INIT_LIST_HEAD(&cd->cancel_cmd_list); + + cd->command = command; + cd->cmd_trb = cmd_trb; + list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list); + + return 0; +} + +/* + * Cancel the command which has issue. + * + * Some commands may hang due to waiting for acknowledgement from + * usb device. It is outside of the xHC's ability to control and + * will cause the command ring is blocked. When it occurs software + * should intervene to recover the command ring. + * See Section 4.6.1.1 and 4.6.1.2 + */ +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&xhci->lock, flags); + + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_warn(xhci, "Abort the command ring," + " but the xHCI is dead.\n"); + retval = -ESHUTDOWN; + goto fail; + } + + /* queue the cmd desriptor to cancel_cmd_list */ + retval = xhci_queue_cd(xhci, command, cmd_trb); + if (retval) { + xhci_warn(xhci, "Queuing command descriptor failed.\n"); + goto fail; + } + + /* abort command ring */ + retval = xhci_abort_cmd_ring(xhci); + if (retval) { + xhci_err(xhci, "Abort command ring failed\n"); + if (unlikely(retval == -ESHUTDOWN)) { + spin_unlock_irqrestore(&xhci->lock, flags); + usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); + xhci_dbg(xhci, "xHCI host controller is dead.\n"); + return retval; + } + } + +fail: + spin_unlock_irqrestore(&xhci->lock, flags); + return retval; +} + void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index de57002f43fe8f..3091d5424d167c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); * handshake done). There are two failure modes: "usec" have passed (major * hardware flakeout), or the register reads as all-ones (hardware removed). */ -static int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d5d40ae7441f79..32d42357b35575 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1256,6 +1256,13 @@ struct xhci_td { union xhci_trb *last_trb; }; +/* command descriptor */ +struct xhci_cd { + struct list_head cancel_cmd_list; + struct xhci_command *command; + union xhci_trb *cmd_trb; +}; + struct xhci_dequeue_state { struct xhci_segment *new_deq_seg; union xhci_trb *new_deq_ptr; @@ -1425,6 +1432,7 @@ struct xhci_hcd { #define CMD_RING_STATE_RUNNING (1 << 0) #define CMD_RING_STATE_ABORTED (1 << 1) #define CMD_RING_STATE_STOPPED (1 << 2) + struct list_head cancel_cmd_list; unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; @@ -1709,6 +1717,8 @@ static inline void xhci_unregister_plat(void) /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, + u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_reset(struct xhci_hcd *xhci); @@ -1799,6 +1809,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); void xhci_stop_endpoint_command_watchdog(unsigned long arg); +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb); void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); From d128a534496366095b822885c0a4249ffc952c58 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:31:52 +0800 Subject: [PATCH 0030/1071] xHCI: cancel command after command timeout commit 6e4468b9a0793dfb53eb80d9fe52c739b13b27fd upstream. The patch is used to cancel command when the command isn't acknowledged and a timeout occurs. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 26 +++++++++++++++++++------- drivers/usb/host/xhci.h | 3 +++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3091d5424d167c..e826ef33045858 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2525,6 +2525,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, struct completion *cmd_completion; u32 *cmd_status; struct xhci_virt_device *virt_dev; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); virt_dev = xhci->devs[udev->slot_id]; @@ -2570,6 +2571,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, } init_completion(cmd_completion); + cmd_trb = xhci->cmd_ring->dequeue; if (!ctx_change) ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, udev->slot_id, must_succeed); @@ -2591,14 +2593,17 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, /* Wait for the configure endpoint command to complete */ timeleft = wait_for_completion_interruptible_timeout( cmd_completion, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for %s command\n", timeleft == 0 ? "Timeout" : "Signal", ctx_change == 0 ? "configure endpoint" : "evaluate context"); - /* FIXME cancel the configure endpoint command */ + /* cancel the configure endpoint command */ + ret = xhci_cancel_cmd(xhci, command, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } @@ -3547,8 +3552,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) unsigned long flags; int timeleft; int ret; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); @@ -3560,12 +3567,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) /* XXX: how much time for xHC slot assignment? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for a slot\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the enable slot request */ - return 0; + /* cancel the enable slot request */ + return xhci_cancel_cmd(xhci, NULL, cmd_trb); } if (!xhci->slot_id) { @@ -3626,6 +3633,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u64 temp_64; + union xhci_trb *cmd_trb; if (!udev->slot_id) { xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); @@ -3664,6 +3672,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret) { @@ -3676,7 +3685,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); /* FIXME: From section 4.3.4: "Software shall be responsible for timing * the SetAddress() "recovery interval" required by USB and aborting the * command on a timeout. @@ -3684,7 +3693,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for address device command\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the address device command */ + /* cancel the address device command */ + ret = xhci_cancel_cmd(xhci, NULL, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 32d42357b35575..53df4e70ca074c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1256,6 +1256,9 @@ struct xhci_td { union xhci_trb *last_trb; }; +/* xHCI command default timeout value */ +#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ) + /* command descriptor */ struct xhci_cd { struct list_head cancel_cmd_list; From 2b66cca8004827d84023e5c9d69b74e1e5c03734 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:55:43 +0800 Subject: [PATCH 0031/1071] xHCI: handle command after aborting the command ring commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d upstream. According to xHCI spec section 4.6.1.1 and section 4.6.1.2, after aborting a command on the command ring, xHC will generate a command completion event with its completion code set to Command Ring Stopped at least. If a command is currently executing at the time of aborting a command, xHC also generate a command completion event with its completion code set to Command Abort. When the command ring is stopped, software may remove, add, or rearrage Command Descriptors. To cancel a command, software will initialize a command descriptor for the cancel command, and add it into a cancel_cmd_list of xhci. When the command ring is stopped, software will find the command trbs described by command descriptors in cancel_cmd_list and modify it to No Op command. If software can't find the matched trbs, we can think it had been finished. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 171 +++++++++++++++++++++++++++++++++-- 1 file changed, 165 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 5d9956c8dbeebc..a6e18b96f15f59 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1170,6 +1170,20 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci, } } +/* Complete the command and detele it from the devcie's command queue. + */ +static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, + struct xhci_command *command, u32 status) +{ + command->status = status; + list_del(&command->cmd_list); + if (command->completion) + complete(command->completion); + else + xhci_free_command(xhci, command); +} + + /* Check to see if a command in the device's command queue matches this one. * Signal the completion or free the command, and return 1. Return 0 if the * completed command isn't at the head of the command list. @@ -1188,15 +1202,144 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, if (xhci->cmd_ring->dequeue != command->command_trb) return 0; - command->status = GET_COMP_CODE(le32_to_cpu(event->status)); - list_del(&command->cmd_list); - if (command->completion) - complete(command->completion); - else - xhci_free_command(xhci, command); + xhci_complete_cmd_in_cmd_wait_list(xhci, command, + GET_COMP_CODE(le32_to_cpu(event->status))); return 1; } +/* + * Finding the command trb need to be cancelled and modifying it to + * NO OP command. And if the command is in device's command wait + * list, finishing and freeing it. + * + * If we can't find the command trb, we think it had already been + * executed. + */ +static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) +{ + struct xhci_segment *cur_seg; + union xhci_trb *cmd_trb; + u32 cycle_state; + + if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue) + return; + + /* find the current segment of command ring */ + cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, + xhci->cmd_ring->dequeue, &cycle_state); + + /* find the command trb matched by cd from command ring */ + for (cmd_trb = xhci->cmd_ring->dequeue; + cmd_trb != xhci->cmd_ring->enqueue; + next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) { + /* If the trb is link trb, continue */ + if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3])) + continue; + + if (cur_cd->cmd_trb == cmd_trb) { + + /* If the command in device's command list, we should + * finish it and free the command structure. + */ + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + + /* get cycle state from the origin command trb */ + cycle_state = le32_to_cpu(cmd_trb->generic.field[3]) + & TRB_CYCLE; + + /* modify the command trb to NO OP command */ + cmd_trb->generic.field[0] = 0; + cmd_trb->generic.field[1] = 0; + cmd_trb->generic.field[2] = 0; + cmd_trb->generic.field[3] = cpu_to_le32( + TRB_TYPE(TRB_CMD_NOOP) | cycle_state); + break; + } + } +} + +static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + xhci_cmd_to_noop(xhci, cur_cd); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } +} + +/* + * traversing the cancel_cmd_list. If the command descriptor according + * to cmd_trb is found, the function free it and return 1, otherwise + * return 0. + */ +static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return 0; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + if (cur_cd->cmd_trb == cmd_trb) { + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + return 1; + } + } + + return 0; +} + +/* + * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the + * trb pointed by the command ring dequeue pointer is the trb we want to + * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will + * traverse the cancel_cmd_list to trun the all of the commands according + * to command descriptor to NO-OP trb. + */ +static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, + int cmd_trb_comp_code) +{ + int cur_trb_is_good = 0; + + /* Searching the cmd trb pointed by the command ring dequeue + * pointer in command descriptor list. If it is found, free it. + */ + cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci, + xhci->cmd_ring->dequeue); + + if (cmd_trb_comp_code == COMP_CMD_ABORT) + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + else if (cmd_trb_comp_code == COMP_CMD_STOP) { + /* traversing the cancel_cmd_list and canceling + * the command according to command descriptor + */ + xhci_cancel_cmd_in_cd_list(xhci); + + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + /* + * ring command ring doorbell again to restart the + * command ring + */ + if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) + xhci_ring_cmd_db(xhci); + } + return cur_trb_is_good; +} + static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { @@ -1222,6 +1365,22 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci->error_bitmask |= 1 << 5; return; } + + if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) || + (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) { + /* If the return value is 0, we think the trb pointed by + * command ring dequeue pointer is a good trb. The good + * trb means we don't want to cancel the trb, but it have + * been stopped by host. So we should handle it normally. + * Otherwise, driver should invoke inc_deq() and return. + */ + if (handle_stopped_cmd_ring(xhci, + GET_COMP_CODE(le32_to_cpu(event->status)))) { + inc_deq(xhci, xhci->cmd_ring); + return; + } + } + switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): From ee537508bdc0c00b96ac497f3d82a68f820e6182 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Fri, 14 Sep 2012 13:05:49 -0400 Subject: [PATCH 0032/1071] Increase XHCI suspend timeout to 16ms commit a6e097dfdfd189b6929af6efa1d289af61858386 upstream. The Intel XHCI specification says that after clearing the run/stop bit the controller may take up to 16ms to halt. We've seen a device take 14ms, which with the current timeout of 10ms causes the kernel to abort the suspend. Increasing the timeout to the recommended value fixes the problem. This patch should be backported to kernels as old as 2.6.37, that contain the commit 5535b1d5f8885695c6ded783c692e3c0d0eda8ca "USB: xHCI: PCI power management implementation". Signed-off-by: Michael Spang Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index e826ef33045858..a49868d938120d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -890,7 +890,7 @@ int xhci_suspend(struct xhci_hcd *xhci) command &= ~CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_HALT, STS_HALT, 100*100)) { + STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) { xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; From 8002daf988b55edc56c69b3c824b5a68c258ace3 Mon Sep 17 00:00:00 2001 From: Kevin Daughtridge Date: Thu, 20 Sep 2012 12:00:32 -0700 Subject: [PATCH 0033/1071] HID: keep dev_rdesc unmodified and use it for comparisons commit 86e6b77eb7cf9ca2e9c7092b4dfd588f0a3307b6 upstream. The dev_rdesc member of the hid_device structure is meant to store the original report descriptor received from the device, but it is currently passed to any report_fixup method before it is copied to the rdesc member. This patch uses a temporary buffer to shield dev_rdesc from the side effects of many HID drivers' report_fixup implementations. usbhid's hid_post_reset checks the report descriptor currently returned by the device against a descriptor that may have been modified by a driver's report_fixup method. That leaves some devices nonfunctional after a resume, with a "reset_resume error 1" reported. This patch checks the new descriptor against the unmodified dev_rdesc instead and uses the original, instead of modified, report size. BugLink: http://bugs.launchpad.net/bugs/1049623 Signed-off-by: Kevin Daughtridge Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 16 +++++++++++++--- drivers/hid/usbhid/hid-core.c | 6 +++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8bcd168fffaebb..5de3bb307067ca 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -757,6 +757,7 @@ int hid_open_report(struct hid_device *device) struct hid_item item; unsigned int size; __u8 *start; + __u8 *buf; __u8 *end; int ret; static int (*dispatch_type[])(struct hid_parser *parser, @@ -775,12 +776,21 @@ int hid_open_report(struct hid_device *device) return -ENODEV; size = device->dev_rsize; + buf = kmemdup(start, size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + if (device->driver->report_fixup) - start = device->driver->report_fixup(device, start, &size); + start = device->driver->report_fixup(device, buf, &size); + else + start = buf; - device->rdesc = kmemdup(start, size, GFP_KERNEL); - if (device->rdesc == NULL) + start = kmemdup(start, size, GFP_KERNEL); + kfree(buf); + if (start == NULL) return -ENOMEM; + + device->rdesc = start; device->rsize = size; parser = vzalloc(sizeof(struct hid_parser)); diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index dedd8e4e5c6dde..8e0c4bf94ebc44 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1415,20 +1415,20 @@ static int hid_post_reset(struct usb_interface *intf) * configuration descriptors passed, we already know that * the size of the HID report descriptor has not changed. */ - rdesc = kmalloc(hid->rsize, GFP_KERNEL); + rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL); if (!rdesc) { dbg_hid("couldn't allocate rdesc memory (post_reset)\n"); return 1; } status = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, - HID_DT_REPORT, rdesc, hid->rsize); + HID_DT_REPORT, rdesc, hid->dev_rsize); if (status < 0) { dbg_hid("reading report descriptor failed (post_reset)\n"); kfree(rdesc); return 1; } - status = memcmp(rdesc, hid->rdesc, hid->rsize); + status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize); kfree(rdesc); if (status != 0) { dbg_hid("report descriptor changed\n"); From 1a7dcc9ae24f131dd2ee85eacc9c04d5562ef170 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sat, 22 Sep 2012 00:14:28 +0530 Subject: [PATCH 0034/1071] ath9k: Disable ASPM only for AR9285 commit 046b6802c8d3c8a57448485513bf7291633e0fa3 upstream. Currently, ASPM is disabled for all WLAN+BT combo chipsets when BTCOEX is enabled. This is incorrect since the workaround is required only for WB195, which is a AR9285+AR3011 combo solution. Fix this by checking for the HW version when enabling the workaround. Signed-off-by: Sujith Manoharan Tested-by: Paul Stewart Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index a978984d78a53e..0c43e7f60abebb 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -127,8 +127,9 @@ static void ath_pci_aspm_init(struct ath_common *common) if (!parent) return; - if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { - /* Bluetooth coexistance requires disabling ASPM. */ + if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) && + (AR_SREV_9285(ah))) { + /* Bluetooth coexistance requires disabling ASPM for AR9285. */ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); From f366ac017fb51edec10ad02d5f557557cce5162a Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 25 Sep 2012 16:48:24 -0400 Subject: [PATCH 0035/1071] xen/pciback: Restore the PCI config space after an FLR. commit c341ca45ce56143804ef5a8f4db753e554e640b4 upstream. When we do an FLR, or D0->D3_hot we may lose the BARs as the device has turned itself off (and on). This means the device cannot function unless the pci_restore_state is called - which it is when the PCI device is unbound from the Xen PCI backend driver. For PV guests it ends up calling pci_enable_device / pci_enable_msi[x] which does the proper steps That however is not happening if a HVM guest is run as QEMU deals with PCI configuration space. QEMU also requires that the device be "parked" under the ownership of a pci-stub driver to guarantee that the PCI device is not being used. Hence we follow the same incantation as pci_reset_function does - by doing an FLR, then restoring the PCI configuration space. The result of this patch is that when you run lspci, you get now this: - Region 0: [virtual] Memory at fe8c0000 (32-bit, non-prefetchable) [size=128K] - Region 1: [virtual] Memory at fe800000 (32-bit, non-prefetchable) [size=512K] + Region 0: Memory at fe8c0000 (32-bit, non-prefetchable) [size=128K] + Region 1: Memory at fe800000 (32-bit, non-prefetchable) [size=512K] Region 2: I/O ports at c000 [size=32] - Region 3: [virtual] Memory at fe8e0000 (32-bit, non-prefetchable) [size=16K] + Region 3: Memory at fe8e0000 (32-bit, non-prefetchable) [size=16K] The [virtual] means that lspci read those entries from SysFS but when it read them from the device it got a different value (0xfffffff). Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xen-pciback/pci_stub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 03342728bf2352..77c9f769daddad 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -362,6 +362,7 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) else { dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); __pci_reset_function_locked(dev); + pci_restore_state(dev); } /* Now disable the device (this also ensures some private device * data is setup before we export) From 9155bc2acdd5b7c11dee00dc9b792b89ca181d61 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Sep 2012 11:34:50 +1000 Subject: [PATCH 0036/1071] coredump: prevent double-free on an error path in core dumper commit f34f9d186df35e5c39163444c43b4fc6255e39c5 upstream. In !CORE_DUMP_USE_REGSET case, if elf_note_info_init fails to allocate memory for info->fields, it frees already allocated stuff and returns error to its caller, fill_note_info. Which in turn returns error to its caller, elf_core_dump. Which jumps to cleanup label and calls free_note_info, which will happily try to free all info->fields again. BOOM. This is the fix. Signed-off-by: Oleg Nesterov Signed-off-by: Denys Vlasenko Cc: Venu Byravarasu Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- fs/binfmt_elf.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 1b52956afe33ab..0225fddf49b7d9 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1696,30 +1696,19 @@ static int elf_note_info_init(struct elf_note_info *info) return 0; info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); if (!info->psinfo) - goto notes_free; + return 0; info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); if (!info->prstatus) - goto psinfo_free; + return 0; info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); if (!info->fpu) - goto prstatus_free; + return 0; #ifdef ELF_CORE_COPY_XFPREGS info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); if (!info->xfpu) - goto fpu_free; + return 0; #endif return 1; -#ifdef ELF_CORE_COPY_XFPREGS - fpu_free: - kfree(info->fpu); -#endif - prstatus_free: - kfree(info->prstatus); - psinfo_free: - kfree(info->psinfo); - notes_free: - kfree(info->notes); - return 0; } static int fill_note_info(struct elfhdr *elf, int phdrs, From 4cac0c9a7374d8e5456093b5ca8800d8dd362973 Mon Sep 17 00:00:00 2001 From: xiaojin Date: Mon, 13 Aug 2012 13:43:15 +0100 Subject: [PATCH 0037/1071] n_gsm.c: Implement 3GPP27.010 DLC start-up procedure in MUX commit 7e8ac7b23b67416700dfb8b4136a4e81ce675b48 upstream. In 3GPP27.010 5.8.1, it defined: The TE multiplexer initiates the establishment of the multiplexer control channel by sending a SABM frame on DLCI 0 using the procedures of clause 5.4.1. Once the multiplexer channel is established other DLCs may be established using the procedures of clause 5.4.1. This patch implement 5.8.1 in MUX level, it make sure DLC0 is the first channel to be setup. [or for those not familiar with the specification: it was possible to try and open a data connection while the control channel was not yet fully open, which is a spec violation and confuses some modems] Signed-off-by: xiaojin Tested-by: Yin, Fengwei [tweaked the order we check things and error code] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c43b683b6eb811..0a73b59f797d6c 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2889,6 +2889,10 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) gsm = gsm_mux[mux]; if (gsm->dead) return -EL2HLT; + /* If DLCI 0 is not yet fully open return an error. This is ok from a locking + perspective as we don't have to worry about this if DLCI0 is lost */ + if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) + return -EL2NSYNC; dlci = gsm->dlci[line]; if (dlci == NULL) dlci = gsm_dlci_alloc(gsm, line); From 409939cebede783ea6526805123bbc5cca505a5a Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Mon, 13 Aug 2012 13:43:36 +0100 Subject: [PATCH 0038/1071] n_gsm: uplink SKBs accumulate on list commit 192b6041e75bb4a2aae73834037038cea139a92d upstream. gsm_dlci_data_kick will not call any output function if tx_bytes > THRESH_LO furthermore it will call the output function only once if tx_bytes == 0 If the size of the IP writes are on the order of THRESH_LO we can get into a situation where skbs accumulate on the outbound list being starved for events to call the output function. gsm_dlci_data_kick now calls the sweep function when tx_bytes==0 Signed-off-by: Russ Gorby Tested-by: Kappel, LaurentX Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 0a73b59f797d6c..1720055ca97b1d 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -971,16 +971,19 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) static void gsm_dlci_data_kick(struct gsm_dlci *dlci) { unsigned long flags; + int sweep; spin_lock_irqsave(&dlci->gsm->tx_lock, flags); /* If we have nothing running then we need to fire up */ + sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO); if (dlci->gsm->tx_bytes == 0) { if (dlci->net) gsm_dlci_data_output_framed(dlci->gsm, dlci); else gsm_dlci_data_output(dlci->gsm, dlci); - } else if (dlci->gsm->tx_bytes < TX_THRESH_LO) - gsm_dlci_data_sweep(dlci->gsm); + } + if (sweep) + gsm_dlci_data_sweep(dlci->gsm); spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } From efdd902a13b786961c072d947c548af4730733e0 Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Mon, 13 Aug 2012 13:44:40 +0100 Subject: [PATCH 0039/1071] n_gsm: added interlocking for gsm_data_lock for certain code paths commit 5e44708f75b0f8712da715d6babb0c21089b2317 upstream. There were some locking holes in the management of the MUX's message queue for 2 code paths: 1) gsmld_write_wakeup 2) receipt of CMD_FCON flow-control message In both cases gsm_data_kick is called w/o locking so it can collide with other other instances of gsm_data_kick (pulling messages tx_tail) or potentially other instances of __gsm_data_queu (adding messages to tx_head) Changed to take the tx_lock in these 2 cases Signed-off-by: Russ Gorby Tested-by: Yin, Fengwei Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 1720055ca97b1d..671fbc2d79353a 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1193,6 +1193,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, u8 *data, int clen) { u8 buf[1]; + unsigned long flags; + switch (command) { case CMD_CLD: { struct gsm_dlci *dlci = gsm->dlci[0]; @@ -1218,7 +1220,9 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, gsm->constipated = 0; gsm_control_reply(gsm, CMD_FCOFF, NULL, 0); /* Kick the link in case it is idling */ + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); + spin_unlock_irqrestore(&gsm->tx_lock, flags); break; case CMD_MSC: /* Out of band modem line change indicator for a DLCI */ @@ -2380,12 +2384,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty) /* Queue poll */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); if (gsm->tx_bytes < TX_THRESH_LO) { - spin_lock_irqsave(&gsm->tx_lock, flags); gsm_dlci_data_sweep(gsm); - spin_unlock_irqrestore(&gsm->tx_lock, flags); } + spin_unlock_irqrestore(&gsm->tx_lock, flags); } /** From 743e705ee4cb2fd05ba4ed5584c4731c55f98766 Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Mon, 13 Aug 2012 13:45:30 +0100 Subject: [PATCH 0040/1071] n_gsm: memory leak in uplink error path commit 88ed2a60610974443335c924d7cb8e5dcf9dbdc1 upstream. Uplink (TX) network data will go through gsm_dlci_data_output_framed there is a bug where if memory allocation fails, the skb which has already been pulled off the list will be lost. In addition TX skbs were being processed in LIFO order Fixed the memory leak, and changed to FIFO order processing Signed-off-by: Russ Gorby Tested-by: Kappel, LaurentX Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 671fbc2d79353a..90dff8233efdc0 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -875,7 +875,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* dlci->skb is locked by tx_lock */ if (dlci->skb == NULL) { - dlci->skb = skb_dequeue(&dlci->skb_list); + dlci->skb = skb_dequeue_tail(&dlci->skb_list); if (dlci->skb == NULL) return 0; first = 1; @@ -899,8 +899,11 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* FIXME: need a timer or something to kick this so it can't get stuck with no work outstanding and no buffer free */ - if (msg == NULL) + if (msg == NULL) { + skb_queue_tail(&dlci->skb_list, dlci->skb); + dlci->skb = NULL; return -ENOMEM; + } dp = msg->data; if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */ From 27356a5bb5f72d7ebd42ee81df32492d0236a585 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sat, 18 Aug 2012 14:11:42 +0200 Subject: [PATCH 0041/1071] UBI: fix autoresize handling in R/O mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit abb3e01103eb4e2ea5c15e6fedbc74e08bd4cc2b upstream. Currently UBI fails in autoresize when it is in R/O mode (e.g., because the underlying MTD device is R/O). This patch fixes the issue - we just skip autoresize and print a warning. Reported-by: Pali Rohár Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/build.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 2c5ed5ca9c3370..da052ed4f79824 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -759,6 +759,11 @@ static int autoresize(struct ubi_device *ubi, int vol_id) struct ubi_volume *vol = ubi->volumes[vol_id]; int err, old_reserved_pebs = vol->reserved_pebs; + if (ubi->ro_mode) { + ubi_warn("skip auto-resize because of R/O mode"); + return 0; + } + /* * Clear the auto-resize flag in the volume in-memory copy of the * volume table, and 'ubi_resize_volume()' will propagate this change From 9c9cc09d08b083a38a341195597c6809113454c7 Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Wed, 22 Aug 2012 16:03:46 +0200 Subject: [PATCH 0042/1071] UBI: erase free PEB with bitflip in EC header commit 193819cf2e6e395b1e1be2d36785dc5563a6edca upstream. Without this patch, these PEB are not scrubbed until we put data in them. Bitflip can accumulate latter and we can loose the EC header (but VID header should be intact and allow to recover data). Signed-off-by: Matthieu Castet Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/attach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index bd27cbbb4066df..68d4d1f76d1eaf 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -975,7 +975,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, return err; goto adjust_mean_ec; case UBI_IO_FF: - if (ec_err) + if (ec_err || bitflips) err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, 1, &ai->erase); else From 762083a99afd67cc2661e3a7de97abd6ab657dce Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 27 Aug 2012 11:38:13 -0700 Subject: [PATCH 0043/1071] Yama: handle 32-bit userspace prctl commit 2e4930eb7c8fb20a39dfb5f8a8f80402710dcea8 upstream. When running a 64-bit kernel and receiving prctls from a 32-bit userspace, the "-1" used as an unsigned long will end up being misdetected. The kernel is looking for 0xffffffffffffffff instead of 0xffffffff. Since prctl lacks a distinct compat interface, Yama needs to handle this translation itself. As such, support either value as meaning PR_SET_PTRACER_ANY, to avoid breaking the ABI for 64-bit. Signed-off-by: Kees Cook Acked-by: John Johansen Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- security/yama/yama_lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 0cc99a3ea42d65..dcd617829fae54 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -143,7 +143,7 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, if (arg2 == 0) { yama_ptracer_del(NULL, myself); rc = 0; - } else if (arg2 == PR_SET_PTRACER_ANY) { + } else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) { rc = yama_ptracer_add(NULL, myself); } else { struct task_struct *tracer; From 0ee643c28867d5c05aee64b910f1d70a0c263529 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 30 Jul 2012 11:33:05 +1000 Subject: [PATCH 0044/1071] SCSI: ibmvscsi: Fix host config length field overflow commit 225c56960fcafeccc2b6304f96cd3f0dbf42a16a upstream. The length field in the host config packet is only 16-bit long, so passing it 0x10000 (64K which is our standard PAGE_SIZE) doesn't work and result in an empty config from the server. Signed-off-by: Benjamin Herrenschmidt Acked-by: Robert Jennings Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/ibmvscsi/ibmvscsi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 3a6c4742951ea4..337e8b33d9aacb 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1541,6 +1541,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, host_config = &evt_struct->iu.mad.host_config; + /* The transport length field is only 16-bit */ + length = min(0xffff, length); + /* Set up a lun reset SRP command */ memset(host_config, 0x00, sizeof(*host_config)); host_config->common.type = VIOSRP_HOST_CONFIG_TYPE; From edbce27e33fe170dc18cd42672cedb3b49613a20 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 26 Jul 2012 11:34:10 -0500 Subject: [PATCH 0045/1071] SCSI: hpsa: Use LUN reset instead of target reset commit 21e89afd325849eb38adccf382df16cc895911f9 upstream. It turns out Smart Array logical drives do not support target reset and when the target reset fails, the logical drive will be taken off line. Symptoms look like this: hpsa 0000:03:00.0: Abort request on C1:B0:T0:L0 hpsa 0000:03:00.0: resetting device 1:0:0:0 hpsa 0000:03:00.0: cp ffff880037c56000 is reported invalid (probably means target device no longer present) hpsa 0000:03:00.0: resetting device failed. sd 1:0:0:0: Device offlined - not ready after error recovery sd 1:0:0:0: rejecting I/O to offline device EXT3-fs error (device sdb1): read_block_bitmap: LUN reset is supported though, and is what we should be using. Target reset is also disruptive in shared SAS situations, for example, an external MSA1210m which does support target reset attached to Smart Arrays in multiple hosts -- a target reset from one host is disruptive to other hosts as all LUNs on the target will be reset and will abort all outstanding i/os back to all the attached hosts. So we should use LUN reset, not target reset. Tested this with Smart Array logical drives and with tape drives. Not sure how this bug survived since 2009, except it must be very rare for a Smart Array to require more than 30s to complete a request. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 2b4261cb77424b..f9823f2b0c5196 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3266,7 +3266,7 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.Timeout = 0; /* Don't time out */ memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); c->Request.CDB[0] = cmd; - c->Request.CDB[1] = 0x03; /* Reset target above */ + c->Request.CDB[1] = HPSA_RESET_TYPE_LUN; /* If bytes 4-7 are zero, it means reset the */ /* LunID device */ c->Request.CDB[4] = 0x00; From b2be9b06f9f9682943fe274c0d3c07945e623e76 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 21 Sep 2012 15:09:47 +0800 Subject: [PATCH 0046/1071] can: mscan-mpc5xxx: fix return value check in mpc512x_can_get_clock() commit f61bd0585dfc7d99db4936d7467de4ca8e2f7ea0 upstream. In case of error, the function clk_get() returns ERR_PTR() and never returns NULL pointer. The NULL test in the error handling should be replaced with IS_ERR(). dpatch engine is used to auto generated this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/mscan/mpc5xxx_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 06adf881ea24b3..524ef96dc24d86 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -181,7 +181,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (!clock_name || !strcmp(clock_name, "sys")) { sys_clk = clk_get(&ofdev->dev, "sys_clk"); - if (!sys_clk) { + if (IS_ERR(sys_clk)) { dev_err(&ofdev->dev, "couldn't get sys_clk\n"); goto exit_unmap; } @@ -204,7 +204,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (clocksrc < 0) { ref_clk = clk_get(&ofdev->dev, "ref_clk"); - if (!ref_clk) { + if (IS_ERR(ref_clk)) { dev_err(&ofdev->dev, "couldn't get ref_clk\n"); goto exit_unmap; } From d18c73f23f7487c3fd091c2e4a989066056c882c Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Fri, 28 Sep 2012 10:29:21 -0700 Subject: [PATCH 0047/1071] Input: synaptics - adjust threshold for treating position values as negative commit 824efd37415961d38821ecbd9694e213fb2e8b32 upstream. Commit c039450 (Input: synaptics - handle out of bounds values from the hardware) caused any hardware reported values over 7167 to be treated as a wrapped-around negative value. It turns out that some firmware uses the value 8176 to indicate a finger near the edge of the touchpad whose actual position cannot be determined. This value now gets treated as negative, which can cause pointer jumps and broken edge scrolling on these machines. I only know of one touchpad which reports negative values, and this hardware never reports any value lower than -8 (i.e. 8184). Moving the threshold for treating a value as negative up to 8176 should work fine then for any hardware we currently know about, and since we're dealing with unspecified behavior it's probably the best we can do. The special 8176 value is also likely to result in sudden jumps in position, so let's also clamp this to the maximum specified value for the axis. BugLink: http://bugs.launchpad.net/bugs/1046512 https://bugzilla.kernel.org/show_bug.cgi?id=46371 Signed-off-by: Seth Forshee Reviewed-by: Daniel Kurtz Tested-by: Alan Swanson Tested-by: Arteom Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/synaptics.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 14eaecea2b7066..0786919c15cdc6 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -53,14 +53,19 @@ #define ABS_POS_BITS 13 /* - * Any position values from the hardware above the following limits are - * treated as "wrapped around negative" values that have been truncated to - * the 13-bit reporting range of the hardware. These are just reasonable - * guesses and can be adjusted if hardware is found that operates outside - * of these parameters. + * These values should represent the absolute maximum value that will + * be reported for a positive position value. Some Synaptics firmware + * uses this value to indicate a finger near the edge of the touchpad + * whose precise position cannot be determined. + * + * At least one touchpad is known to report positions in excess of this + * value which are actually negative values truncated to the 13-bit + * reporting range. These values have never been observed to be lower + * than 8184 (i.e. -8), so we treat all values greater than 8176 as + * negative and any other value as positive. */ -#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2) -#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2) +#define X_MAX_POSITIVE 8176 +#define Y_MAX_POSITIVE 8176 /***************************************************************************** * Stuff we need even when we do not want native Synaptics support @@ -604,11 +609,21 @@ static int synaptics_parse_hw_state(const unsigned char buf[], hw->right = (buf[0] & 0x02) ? 1 : 0; } - /* Convert wrap-around values to negative */ + /* + * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE + * is used by some firmware to indicate a finger at the edge of + * the touchpad whose precise position cannot be determined, so + * convert these values to the maximum axis value. + */ if (hw->x > X_MAX_POSITIVE) hw->x -= 1 << ABS_POS_BITS; + else if (hw->x == X_MAX_POSITIVE) + hw->x = XMAX; + if (hw->y > Y_MAX_POSITIVE) hw->y -= 1 << ABS_POS_BITS; + else if (hw->y == Y_MAX_POSITIVE) + hw->y = YMAX; return 0; } From 5006010c7ae4c0b0db7e6f0cdc29e3d8f22b2365 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Sun, 30 Sep 2012 10:25:34 +0200 Subject: [PATCH 0048/1071] remoteproc: select VIRTIO to avoid build breakage commit 2ed6d29c725c4aead510b5c23f563795b265acf5 upstream. drivers/built-in.o: In function `rproc_virtio_finalize_features': remoteproc_virtio.c:(.text+0x2f9a02): undefined reference to `vring_transport_features' drivers/built-in.o: In function `rproc_virtio_del_vqs': remoteproc_virtio.c:(.text+0x2f9a74): undefined reference to `vring_del_virtqueue' drivers/built-in.o: In function `rproc_virtio_find_vqs': remoteproc_virtio.c:(.text+0x2f9c44): undefined reference to `vring_new_virtqueue' drivers/built-in.o: In function `rproc_add_virtio_dev': (.text+0x2f9e2c): undefined reference to `register_virtio_device' drivers/built-in.o: In function `rproc_vq_interrupt': (.text+0x2f9db7): undefined reference to `vring_interrupt' drivers/built-in.o: In function `rproc_remove_virtio_dev': (.text+0x2f9e9f): undefined reference to `unregister_virtio_device' Reported-by: Randy Dunlap Signed-off-by: Ohad Ben-Cohen Signed-off-by: Greg Kroah-Hartman --- drivers/remoteproc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f8d818abf98caf..811ff72df4dba2 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -5,6 +5,7 @@ config REMOTEPROC tristate depends on EXPERIMENTAL select FW_CONFIG + select VIRTIO config OMAP_REMOTEPROC tristate "OMAP remoteproc support" From 1c4fc5e51d50f5da0b84bed2204046529b19db8a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Sep 2012 10:01:56 +0300 Subject: [PATCH 0049/1071] remoteproc: fix a potential NULL-dereference on cleanup commit 7168d914a782086e217214c57ddfc7cc4b738c0c upstream. We only need to allocate mapping if there is an IOMMU domain. Otherwise, when the mappings are released, the assumption that an IOMMU domain is there will crash and burn. Signed-off-by: Dan Carpenter [ohad: revise commit log] Signed-off-by: Ohad Ben-Cohen Signed-off-by: Greg Kroah-Hartman --- drivers/remoteproc/remoteproc_core.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index d5c2dbfc7443c0..70b296f4c7f414 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -545,17 +545,10 @@ static int rproc_handle_carveout(struct rproc *rproc, dev_dbg(dev, "carveout rsc: da %x, pa %x, len %x, flags %x\n", rsc->da, rsc->pa, rsc->len, rsc->flags); - mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); - if (!mapping) { - dev_err(dev, "kzalloc mapping failed\n"); - return -ENOMEM; - } - carveout = kzalloc(sizeof(*carveout), GFP_KERNEL); if (!carveout) { dev_err(dev, "kzalloc carveout failed\n"); - ret = -ENOMEM; - goto free_mapping; + return -ENOMEM; } va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL); @@ -585,11 +578,18 @@ static int rproc_handle_carveout(struct rproc *rproc, * physical address in this case. */ if (rproc->domain) { + mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) { + dev_err(dev, "kzalloc mapping failed\n"); + ret = -ENOMEM; + goto dma_free; + } + ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len, rsc->flags); if (ret) { dev_err(dev, "iommu_map failed: %d\n", ret); - goto dma_free; + goto free_mapping; } /* @@ -634,12 +634,12 @@ static int rproc_handle_carveout(struct rproc *rproc, return 0; +free_mapping: + kfree(mapping); dma_free: dma_free_coherent(dev->parent, rsc->len, va, dma); free_carv: kfree(carveout); -free_mapping: - kfree(mapping); return ret; } From e3052eb712da474b11f43b1ec602c22b885b5403 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 30 Aug 2012 07:01:30 +0000 Subject: [PATCH 0050/1071] IPoIB: Fix use-after-free of multicast object commit bea1e22df494a729978e7f2c54f7bda328f74bc3 upstream. Fix a crash in ipoib_mcast_join_task(). (with help from Or Gerlitz) Commit c8c2afe360b7 ("IPoIB: Use rtnl lock/unlock when changing device flags") added a call to rtnl_lock() in ipoib_mcast_join_task(), which is run from the ipoib_workqueue, and hence the workqueue can't be flushed from the context of ipoib_stop(). In the current code, ipoib_stop() (which doesn't flush the workqueue) calls ipoib_mcast_dev_flush(), which goes and deletes all the multicast entries. This takes place without any synchronization with a possible running instance of ipoib_mcast_join_task() for the same ipoib device, leading to a crash due to NULL pointer dereference. Fix this by making sure that the workqueue is flushed before ipoib_mcast_dev_flush() is called. To make that possible, we move the RTNL-lock wrapped code to ipoib_mcast_join_finish(). Signed-off-by: Patrick McHardy Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- .../infiniband/ulp/ipoib/ipoib_multicast.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1e19b5ae7c479a..ea0dfc77a7f46a 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev) netif_stop_queue(dev); - ipoib_ib_dev_down(dev, 0); + ipoib_ib_dev_down(dev, 1); ipoib_ib_dev_stop(dev, 0); if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 75367249f447f4..cecb98a4c662b7 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -175,7 +175,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, mcast->mcmember = *mcmember; - /* Set the cached Q_Key before we attach if it's the broadcast group */ + /* Set the multicast MTU and cached Q_Key before we attach if it's + * the broadcast group. + */ if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4, sizeof (union ib_gid))) { spin_lock_irq(&priv->lock); @@ -183,10 +185,17 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, spin_unlock_irq(&priv->lock); return -EAGAIN; } + priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey); spin_unlock_irq(&priv->lock); priv->tx_wr.wr.ud.remote_qkey = priv->qkey; set_qkey = 1; + + if (!ipoib_cm_admin_enabled(dev)) { + rtnl_lock(); + dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); + rtnl_unlock(); + } } if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { @@ -574,14 +583,6 @@ void ipoib_mcast_join_task(struct work_struct *work) return; } - priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); - - if (!ipoib_cm_admin_enabled(dev)) { - rtnl_lock(); - dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); - rtnl_unlock(); - } - ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n"); clear_bit(IPOIB_MCAST_RUN, &priv->flags); From c4a3b460296bb69d5109d46a7e94df7f97774c56 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 24 Aug 2012 10:27:54 +0000 Subject: [PATCH 0051/1071] IB/srp: Fix use-after-free in srp_reset_req() commit 9b796d06d5d1b1e85ae2316a283ea11dd739ef96 upstream. srp_free_req() uses the scsi_cmnd structure contents to unmap buffers, so we must invoke srp_free_req() before we release ownership of that structure. Signed-off-by: Bart Van Assche Acked-by: David Dillow Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srp/ib_srp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 1b5b0c7300549c..ac66e6b43ee200 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -638,9 +638,9 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); if (scmnd) { + srp_free_req(target, req, scmnd, 0); scmnd->result = DID_RESET << 16; scmnd->scsi_done(scmnd); - srp_free_req(target, req, scmnd, 0); } } From b3f3b814add77a464911df0080d812b18f61ff38 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 24 Aug 2012 10:29:11 +0000 Subject: [PATCH 0052/1071] IB/srp: Avoid having aborted requests hang commit d8536670916a685df116b5c2cb256573fd25e4e3 upstream. We need to call scsi_done() for commands after we abort them. Signed-off-by: Bart Van Assche Acked-by: David Dillow Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srp/ib_srp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index ac66e6b43ee200..922d845f76b0a2 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1687,6 +1687,7 @@ static int srp_abort(struct scsi_cmnd *scmnd) SRP_TSK_ABORT_TASK); srp_free_req(target, req, scmnd, 0); scmnd->result = DID_ABORT << 16; + scmnd->scsi_done(scmnd); return SUCCESS; } From f3b01b793ca3a8787df8994e4a0cab5a59a24e5f Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 28 Sep 2012 17:33:52 +0000 Subject: [PATCH 0053/1071] IB/qib: Fix local access validation for user MRs commit c00aaa1a0221a22153071fcb2f320e2ebaecc2fd upstream. Commit 8aac4cc3a9d7 ("IB/qib: RCU locking for MR validation") introduced a bug that broke user post sends. The proper validation of the MR was lost in the patch. This patch corrects that validation. Reviewed-by: Dean Luick Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/qib/qib_keys.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c index e9486c74c2262b..81c7b73695d26c 100644 --- a/drivers/infiniband/hw/qib/qib_keys.c +++ b/drivers/infiniband/hw/qib/qib_keys.c @@ -186,8 +186,9 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, goto bail; off = sge->addr - mr->user_base; - if (unlikely(sge->addr < mr->iova || off + sge->length > mr->length || - (mr->access_flags & acc) == 0)) + if (unlikely(sge->addr < mr->user_base || + off + sge->length > mr->length || + (mr->access_flags & acc) != acc)) goto bail; if (unlikely(!atomic_inc_not_zero(&mr->refcount))) goto bail; From 0651bd3e20bb320f32ede9773e9d0ec0e569ab96 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 22 Jun 2012 11:31:14 -0700 Subject: [PATCH 0054/1071] isci: fix isci_pci_probe() generates warning on efi failure path commit 6d70a74ffd616073a68ae0974d98819bfa8e6da6 upstream. The oem parameter image embedded in the efi variable is at an offset from the start of the variable. However, in the failure path we try to free the 'orom' pointer which is only valid when the paramaters are being read from the legacy option-rom space. Since failure to load the oem parameters is unlikely and we keep the memory around in the success case just defer all de-allocation to devm. Reported-by: Don Morris Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/isci/init.c | 1 - drivers/scsi/isci/probe_roms.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 92c1d86d1fc647..1286a8a787e2bc 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -644,7 +644,6 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic orom->hdr.version)) { dev_warn(&pdev->dev, "[%d]: invalid oem parameters detected, falling back to firmware\n", i); - devm_kfree(&pdev->dev, orom); orom = NULL; break; } diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 4d95654c3fd485..8ac646e5eddc94 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -104,7 +104,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) if (i >= len) { dev_err(&pdev->dev, "oprom parse error\n"); - devm_kfree(&pdev->dev, rom); rom = NULL; } pci_unmap_biosrom(oprom); From 8b8706101460ed34e6f05aa8f577b9829221130d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 28 Aug 2012 22:12:10 -0700 Subject: [PATCH 0055/1071] SCSI: scsi_remove_target: fix softlockup regression on hot remove commit bc3f02a795d3b4faa99d37390174be2a75d091bd upstream. John reports: BUG: soft lockup - CPU#2 stuck for 23s! [kworker/u:8:2202] [..] Call Trace: [] scsi_remove_target+0xda/0x1f0 [] sas_rphy_remove+0x55/0x60 [] sas_rphy_delete+0x11/0x20 [] sas_port_delete+0x25/0x160 [] mptsas_del_end_device+0x183/0x270 ...introduced by commit 3b661a9 "[SCSI] fix hot unplug vs async scan race". Don't restart lookup of more stargets in the multi-target case, just arrange to traverse the list once, on the assumption that new targets are always added at the end. There is no guarantee that the target will change state in scsi_target_reap() so we can end up spinning if we restart. Acked-by: Jack Wang LKML-Reference: Reported-by: John Drescher Tested-by: John Drescher Signed-off-by: Dan Williams Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_sysfs.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 093d4f6a54d2f1..ce5224c92edae6 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1031,33 +1031,31 @@ static void __scsi_remove_target(struct scsi_target *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev->parent); - struct scsi_target *starget, *found; + struct scsi_target *starget, *last = NULL; unsigned long flags; - restart: - found = NULL; + /* remove targets being careful to lookup next entry before + * deleting the last + */ spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL) continue; if (starget->dev.parent == dev || &starget->dev == dev) { - found = starget; - found->reap_ref++; - break; + /* assuming new targets arrive at the end */ + starget->reap_ref++; + spin_unlock_irqrestore(shost->host_lock, flags); + if (last) + scsi_target_reap(last); + last = starget; + __scsi_remove_target(starget); + spin_lock_irqsave(shost->host_lock, flags); } } spin_unlock_irqrestore(shost->host_lock, flags); - if (found) { - __scsi_remove_target(found); - scsi_target_reap(found); - /* in the case where @dev has multiple starget children, - * continue removing. - * - * FIXME: does such a case exist? - */ - goto restart; - } + if (last) + scsi_target_reap(last); } EXPORT_SYMBOL(scsi_remove_target); From 49a1ecd51adc4fb6cc229840c568ad19b051190d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 24 Aug 2012 09:08:41 +0000 Subject: [PATCH 0056/1071] SCSI: scsi_dh_alua: Enable STPG for unavailable ports commit e47f8976d8e573928824a06748f7bc82c58d747f upstream. A quote from SPC-4: "While in the unavailable primary target port asymmetric access state, the device server shall support those of the following commands that it supports while in the active/optimized state: [ ... ] d) SET TARGET PORT GROUPS; [ ... ]". Hence enable sending STPG to a target port group that is in the unavailable state. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Acked-by: Hannes Reinecke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/device_handler/scsi_dh_alua.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 08d80a6d272a0c..6f4d8e6f32f15d 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -641,8 +641,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) h->state = TPGS_STATE_STANDBY; break; case TPGS_STATE_OFFLINE: - case TPGS_STATE_UNAVAILABLE: - /* Path unusable for unavailable/offline */ + /* Path unusable */ err = SCSI_DH_DEV_OFFLINED; break; default: From c6092bb74442d4ee1dfea60e2934915836f53528 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Oct 2012 08:41:28 -0700 Subject: [PATCH 0057/1071] Linux 3.6.1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bb9fff26f07806..9ed5898e0e61b6 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 0 +SUBLEVEL = 1 EXTRAVERSION = NAME = Terrified Chipmunk From 562cc37c095ddc6873a1541d36250ad59ce59549 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 4 Oct 2012 17:11:13 -0700 Subject: [PATCH 0058/1071] mn10300: only add -mmem-funcs to KBUILD_CFLAGS if gcc supports it commit 9957423f035c2071f6d1c5d2f095cdafbeb25ad7 upstream. It seems the current (gcc 4.6.3) no longer provides this so make it conditional. As reported by Tony before, the mn10300 architecture cross-compiles with gcc-4.6.3 if -mmem-funcs is not added to KBUILD_CFLAGS. Reported-by: Tony Breeds Signed-off-by: Geert Uytterhoeven Cc: David Howells Cc: Koichi Yasutake Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/mn10300/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile index 33188b6e81e450..a3d0fef3b126ba 100644 --- a/arch/mn10300/Makefile +++ b/arch/mn10300/Makefile @@ -26,7 +26,7 @@ CHECKFLAGS += PROCESSOR := unset UNIT := unset -KBUILD_CFLAGS += -mam33 -mmem-funcs -DCPU=AM33 +KBUILD_CFLAGS += -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,) KBUILD_AFLAGS += -mam33 -DCPU=AM33 ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y) From 1d9465b68211c801acadde7dc3520eaba5e176c5 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 4 Oct 2012 17:11:17 -0700 Subject: [PATCH 0059/1071] kbuild: make: fix if_changed when command contains backslashes commit c353acba28fb3fa1fd05fd6b85a9fc7938330f9c upstream. The call if_changed mechanism does not work when the command contains backslashes. This basically is an issue with lzo and bzip2 compressed kernels. The compressed binaries do not contain the uncompressed image size, so these use size_append to append the size. This results in backslashes in the executed command. With this if_changed always detects a change in the command and rebuilds the compressed image even if nothing has changed. Fix this by escaping backslashes in make-cmd Signed-off-by: Sascha Hauer Signed-off-by: Jan Luebbe Cc: Sam Ravnborg Cc: Bernhard Walle Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- scripts/Kbuild.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 6a3ee981931d3c..afa44595f34868 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -209,7 +209,7 @@ endif # >$< substitution to preserve $ when reloading .cmd file # note: when using inline perl scripts [perl -e '...$$t=1;...'] # in $(cmd_xxx) double $$ your perl vars -make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) +make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))) # Find any prerequisites that is newer than target or that does not exist. # PHONY targets skipped in both cases. From 4bb50fa92f02d4b05067501919b280b44c6f4659 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 25 Sep 2012 16:03:03 +0200 Subject: [PATCH 0060/1071] kbuild: Do not package /boot and /lib in make tar-pkg commit fe04ddf7c2910362f3817c8156e41cbd6c0ee35d upstream. There were reports of users destroying their Fedora installs by a kernel tarball that replaces the /lib -> /usr/lib symlink. Let's remove the toplevel directories from the tarball to prevent this from happening. Reported-by: Andi Kleen Suggested-by: Ben Hutchings Signed-off-by: Michal Marek Signed-off-by: Greg Kroah-Hartman --- arch/x86/Makefile | 2 +- scripts/Makefile.fwinst | 4 ++-- scripts/package/buildtar | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 474ca35b1bce34..682e9c210baacb 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) -archscripts: scripts_basic +archscripts: $(Q)$(MAKE) $(build)=arch/x86/tools relocs ### diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index 4d908d16c035c4..c3f69ae275d1f7 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst @@ -27,7 +27,7 @@ endif installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) -installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./ +installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs @@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@) $(installed-fw-dirs): $(call cmd,mkdir) -$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %) +$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%) $(call cmd,install) PHONY += __fw_install __fw_modinst FORCE diff --git a/scripts/package/buildtar b/scripts/package/buildtar index 8a7b15598ea96c..d0d748e72915b2 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -109,7 +109,7 @@ esac if tar --owner=root --group=root --help >/dev/null 2>&1; then opts="--owner=root --group=root" fi - tar cf - . $opts | ${compress} > "${tarball}${file_ext}" + tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}" ) echo "Tarball successfully created in ${tarball}${file_ext}" From 29f7d41bd8864713f28a63c7706afa7816b8e6e2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 2 Oct 2012 16:42:36 +0200 Subject: [PATCH 0061/1071] kbuild: Fix gcc -x syntax commit b1e0d8b70fa31821ebca3965f2ef8619d7c5e316 upstream. The correct syntax for gcc -x is "gcc -x assembler", not "gcc -xassembler". Even though the latter happens to work, the former is what is documented in the manual page and thus what gcc wrappers such as icecream do expect. This isn't a cosmetic change. The missing space prevents icecream from recognizing compilation tasks it can't handle, leading to silent kernel miscompilations. Besides me, credits go to Michael Matz and Dirk Mueller for investigating the miscompilation issue and tracking it down to this incorrect -x parameter syntax. Signed-off-by: Jean Delvare Acked-by: Ingo Molnar Cc: Bernhard Walle Cc: Michal Marek Cc: Ralf Baechle Signed-off-by: Michal Marek Signed-off-by: Greg Kroah-Hartman --- arch/mips/Makefile | 2 +- arch/mips/kernel/Makefile | 2 +- arch/x86/Makefile | 2 +- scripts/Kbuild.include | 12 ++++++------ scripts/gcc-version.sh | 6 +++--- scripts/gcc-x86_32-has-stack-protector.sh | 2 +- scripts/gcc-x86_64-has-stack-protector.sh | 2 +- scripts/kconfig/check.sh | 2 +- scripts/kconfig/lxdialog/check-lxdialog.sh | 2 +- tools/perf/Makefile | 2 +- tools/power/cpupower/Makefile | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 764e37a9dbb34c..654b1ad39f05fb 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -225,7 +225,7 @@ KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0) LDFLAGS += -m $(ld-emul) ifdef CONFIG_MIPS -CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \ +CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/") ifdef CONFIG_64BIT diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index fdaf65e1a99d04..c6136cb4cd40b6 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -104,7 +104,7 @@ obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o obj-$(CONFIG_OF) += prom.o -CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) +CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 682e9c210baacb..58790bd85c1d38 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -92,7 +92,7 @@ endif ifdef CONFIG_X86_X32 x32_ld_ok := $(call try-run,\ /bin/echo -e '1: .quad 1b' | \ - $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" - && \ + $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \ $(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMPO" && \ $(LD) -m elf32_x86_64 "$$TMPO" -o "$$TMP",y,n) ifeq ($(x32_ld_ok),y) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index afa44595f34868..978416dd31ca0e 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -98,24 +98,24 @@ try-run = $(shell set -e; \ # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) as-option = $(call try-run,\ - $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2)) # as-instr # Usage: cflags-y += $(call as-instr,instr,option1,option2) as-instr = $(call try-run,\ - printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3)) # cc-option # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) cc-option = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) # cc-option-yn # Usage: flag := $(call cc-option-yn,-march=winchip-c6) cc-option-yn = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) # cc-option-align # Prefix align with either -falign or -malign @@ -125,7 +125,7 @@ cc-option-align = $(subst -functions=0,,\ # cc-disable-warning # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) cc-disable-warning = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) # cc-version # Usage gcc-ver := $(call cc-version) @@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) # cc-ldoption # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) cc-ldoption = $(call try-run,\ - $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) # ld-option # Usage: LDFLAGS += $(call ld-option, -X) diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh index debecb5561c481..7f2126df91f2a8 100644 --- a/scripts/gcc-version.sh +++ b/scripts/gcc-version.sh @@ -22,10 +22,10 @@ if [ ${#compiler} -eq 0 ]; then exit 1 fi -MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) -MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) +MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1) +MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1) if [ "x$with_patchlevel" != "x" ] ; then - PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1) + PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1) printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL else printf "%02d%02d\\n" $MAJOR $MINOR diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh index 29493dc4528d0b..12dbd0b11ea4fe 100644 --- a/scripts/gcc-x86_32-has-stack-protector.sh +++ b/scripts/gcc-x86_32-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh index afaec618b3955c..973e8c1415677e 100644 --- a/scripts/gcc-x86_64-has-stack-protector.sh +++ b/scripts/gcc-x86_64-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh index fa59cbf9d62cf4..854d9c7c675ca4 100755 --- a/scripts/kconfig/check.sh +++ b/scripts/kconfig/check.sh @@ -1,6 +1,6 @@ #!/bin/sh # Needed for systems without gettext -$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +$* -x c -o /dev/null - > /dev/null 2>&1 << EOF #include int main() { diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index e3b12c010417c8..c8e8a7154753b8 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15 # Check if we can link to ncurses check() { - $cc -xc - -o $tmp 2>/dev/null <<'EOF' + $cc -x c - -o $tmp 2>/dev/null <<'EOF' #include CURSES_LOC main() {} EOF diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 35655c3a7b7a43..3657ab08bc35aa 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -62,7 +62,7 @@ ifeq ($(ARCH),x86_64) ARCH := x86 IS_X86_64 := 0 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) - IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) endif ifeq (${IS_X86_64}, 1) RAW_ARCH := x86_64 diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index a93e06cfcc2a2f..cf397bd26d0c64 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -111,7 +111,7 @@ GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS # check if compiler option is supported -cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} +cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} # use '-Os' optimization if available, else use -O2 OPTIMIZATION := $(call cc-supports,-Os,-O2) From caeb8b844999f194c3f76a9a3b0a8b94e17eadca Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Fri, 5 Oct 2012 22:23:55 +0200 Subject: [PATCH 0062/1071] i2c-piix4: Fix build failure commit c415b303a704e5c5f766fc0404093910c36cc4ab upstream. Fix build failure in Intel PIIX4 I2C driver. Signed-off-by: Daniel J Blueman Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-piix4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index ef511df2c96565..8bbd6ece7c41ed 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include From 987bb385ef97fba0dcaf531e63a9bc5ca2e2f9f1 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Wed, 5 Sep 2012 10:33:18 +0800 Subject: [PATCH 0063/1071] slab: fix the DEADLOCK issue on l3 alien lock commit 947ca1856a7e60aa6d20536785e6a42dff25aa6e upstream. DEADLOCK will be report while running a kernel with NUMA and LOCKDEP enabled, the process of this fake report is: kmem_cache_free() //free obj in cachep -> cache_free_alien() //acquire cachep's l3 alien lock -> __drain_alien_cache() -> free_block() -> slab_destroy() -> kmem_cache_free() //free slab in cachep->slabp_cache -> cache_free_alien() //acquire cachep->slabp_cache's l3 alien lock Since the cachep and cachep->slabp_cache's l3 alien are in the same lock class, fake report generated. This should not happen since we already have init_lock_keys() which will reassign the lock class for both l3 list and l3 alien. However, init_lock_keys() was invoked at a wrong position which is before we invoke enable_cpucache() on each cache. Since until set slab_state to be FULL, we won't invoke enable_cpucache() on caches to build their l3 alien while creating them, so although we invoked init_lock_keys(), the l3 alien lock class won't change since we don't have them until invoked enable_cpucache() later. This patch will invoke init_lock_keys() after we done enable_cpucache() instead of before to avoid the fake DEADLOCK report. Michael traced the problem back to a commit in release 3.0.0: commit 30765b92ada267c5395fc788623cb15233276f5c Author: Peter Zijlstra Date: Thu Jul 28 23:22:56 2011 +0200 slab, lockdep: Annotate the locks before using them Fernando found we hit the regular OFF_SLAB 'recursion' before we annotate the locks, cure this. The relevant portion of the stack-trace: > [ 0.000000] [] rt_spin_lock+0x50/0x56 > [ 0.000000] [] __cache_free+0x43/0xc3 > [ 0.000000] [] kmem_cache_free+0x6c/0xdc > [ 0.000000] [] slab_destroy+0x4f/0x53 > [ 0.000000] [] free_block+0x94/0xc1 > [ 0.000000] [] do_tune_cpucache+0x10b/0x2bb > [ 0.000000] [] enable_cpucache+0x7b/0xa7 > [ 0.000000] [] kmem_cache_init_late+0x1f/0x61 > [ 0.000000] [] start_kernel+0x24c/0x363 > [ 0.000000] [] i386_start_kernel+0xa9/0xaf Reported-by: Fernando Lopez-Lezcano Acked-by: Pekka Enberg Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1311888176.2617.379.camel@laptop Signed-off-by: Ingo Molnar The commit moved init_lock_keys() before we build up the alien, so we failed to reclass it. Acked-by: Christoph Lameter Tested-by: Paul E. McKenney Signed-off-by: Michael Wang Signed-off-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- mm/slab.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index c6854759bcf1e0..d066037e3c5c42 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1781,9 +1781,6 @@ void __init kmem_cache_init_late(void) slab_state = UP; - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); - /* 6) resize the head arrays to their final sizes */ mutex_lock(&slab_mutex); list_for_each_entry(cachep, &slab_caches, list) @@ -1791,6 +1788,9 @@ void __init kmem_cache_init_late(void) BUG(); mutex_unlock(&slab_mutex); + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); + /* Done! */ slab_state = FULL; From 11464f790b08f7a8b0e5a98b994f53bd33ecb9e4 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 3 Oct 2012 18:57:10 +0000 Subject: [PATCH 0064/1071] powerpc/iommu: Fix multiple issues with IOMMU pools code commit d900bd7366463fd96a907b2c212242e2b68b27d8 upstream. There are a number of issues in the recent IOMMU pools code: - On a preempt kernel we might switch CPUs in the middle of building a scatter gather list. When this happens the handle hint passed in no longer falls within the local CPU's pool. Check for this and fall back to the pool hint. - We were missing a spin_unlock/spin_lock in one spot where we switch pools. - We need to provide locking around dart_tlb_invalidate_all and dart_tlb_invalidate_one now that the global lock is gone. Reported-by: Alexander Graf Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/iommu.c | 5 ++++- arch/powerpc/sysdev/dart_iommu.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index ff5a6ce027b88e..8226c6cb348afb 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -215,7 +215,8 @@ static unsigned long iommu_range_alloc(struct device *dev, spin_lock_irqsave(&(pool->lock), flags); again: - if ((pass == 0) && handle && *handle) + if ((pass == 0) && handle && *handle && + (*handle >= pool->start) && (*handle < pool->end)) start = *handle; else start = pool->hint; @@ -236,7 +237,9 @@ static unsigned long iommu_range_alloc(struct device *dev, * but on second pass, start at 0 in pool 0. */ if ((start & mask) >= limit || pass > 0) { + spin_unlock(&(pool->lock)); pool = &(tbl->pools[0]); + spin_lock(&(pool->lock)); start = pool->start; } else { start &= mask; diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 4f2680f431b507..b68b0db17b3033 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -74,11 +74,16 @@ static int dart_is_u4; #define DBG(...) +static DEFINE_SPINLOCK(invalidate_lock); + static inline void dart_tlb_invalidate_all(void) { unsigned long l = 0; unsigned int reg, inv_bit; unsigned long limit; + unsigned long flags; + + spin_lock_irqsave(&invalidate_lock, flags); DBG("dart: flush\n"); @@ -111,12 +116,17 @@ static inline void dart_tlb_invalidate_all(void) panic("DART: TLB did not flush after waiting a long " "time. Buggy U3 ?"); } + + spin_unlock_irqrestore(&invalidate_lock, flags); } static inline void dart_tlb_invalidate_one(unsigned long bus_rpn) { unsigned int reg; unsigned int l, limit; + unsigned long flags; + + spin_lock_irqsave(&invalidate_lock, flags); reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE | (bus_rpn & DART_CNTL_U4_IONE_MASK); @@ -138,6 +148,8 @@ static inline void dart_tlb_invalidate_one(unsigned long bus_rpn) panic("DART: TLB did not flush after waiting a long " "time. Buggy U4 ?"); } + + spin_unlock_irqrestore(&invalidate_lock, flags); } static void dart_flush(struct iommu_table *tbl) From ad02e7b197e85889bd2df38bffa3e41c695c35f3 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 11 Nov 2011 17:26:44 -0700 Subject: [PATCH 0065/1071] intel-iommu: Default to non-coherent for domains unattached to iommus commit 2e12bc29fc5a12242d68e11875db3dd58efad9ff upstream. domain_update_iommu_coherency() currently defaults to setting domains as coherent when the domain is not attached to any iommus. This allows for a window in domain_context_mapping_one() where such a domain can update context entries non-coherently, and only after update the domain capability to clear iommu_coherency. This can be seen using KVM device assignment on VT-d systems that do not support coherency in the ecap register. When a device is added to a guest, a domain is created (iommu_coherency = 0), the device is attached, and ranges are mapped. If we then hot unplug the device, the coherency is updated and set to the default (1) since no iommus are attached to the domain. A subsequent attach of a device makes use of the same dmar domain (now marked coherent) updates context entries with coherency enabled, and only disables coherency as the last step in the process. To fix this, switch domain_update_iommu_coherency() to use the safer, non-coherent default for domains not attached to iommus. Signed-off-by: Alex Williamson Tested-by: Donald Dutile Acked-by: Donald Dutile Acked-by: Chris Wright Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 2297ec193eb4b6..cb9e1146b02fe3 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -589,7 +589,9 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) { int i; - domain->iommu_coherency = 1; + i = find_first_bit(domain->iommu_bmp, g_num_of_iommus); + + domain->iommu_coherency = i < g_num_of_iommus ? 1 : 0; for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { if (!ecap_coherent(g_iommus[i]->ecap)) { From d4f7487aa0588291ad992d2921f02f543e25445b Mon Sep 17 00:00:00 2001 From: Wade Farnsworth Date: Tue, 2 Oct 2012 17:08:30 +0100 Subject: [PATCH 0066/1071] ARM: 7548/1: include linux/sched.h in syscall.h commit 8ef102c6b4bc996ff96ca52b34775fe931ec90c9 upstream. The syscall tracing patch introduces a compile bug in lttng-modules when the latter calls syscall_get_nr(), similar to the following: /arch/arm/include/asm/syscall.h:21:2: error: implicit declaration of function 'task_thread_info' [-Werror=implicit-function-declaration] The issue is that we are using task_thread_info() in the syscall_get_nr() function in asm/syscall.h, but not explicitly including sched.h from this file, so we can expect this bug might surface any time that syscall_get_nr() is called. Explicitly including sched.h solves the problem. Signed-off-by: Wade Farnsworth Acked-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/syscall.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index c334a23ddf7591..fce38a684e4493 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h @@ -8,6 +8,7 @@ #define _ASM_ARM_SYSCALL_H #include +#include extern const unsigned long sys_call_table[]; From 3de9e9624b36263618470c6e134f22eabf8f2551 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 2 Oct 2012 15:35:27 -0300 Subject: [PATCH 0067/1071] em28xx: Make all em28xx extensions to be initialized asynchronously commit 6ae5e060840589f567c1837613e8a9d34fc9188a upstream. em28xx-dvb, em28xx-alsa and em28xx-ir are typically initialized asyncrhronously. The exception for it is when those modules are loaded before em28xx (or before an em28xx card insertion) or when they're built in. Make the extentions to always load asynchronously. That allows having all DVB firmwares loaded synchronously with udev-182. Antti tested it with the following hardware: Hauppauge WinTV HVR 930C MaxMedia UB425-TC PCTV QuatroStick nano (520e) Tested-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/em28xx/em28xx-cards.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ca62b998138042..ab98d0845861bb 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2875,12 +2875,20 @@ static void em28xx_card_setup(struct em28xx *dev) } -#if defined(CONFIG_MODULES) && defined(MODULE) static void request_module_async(struct work_struct *work) { struct em28xx *dev = container_of(work, struct em28xx, request_module_wk); + /* + * The em28xx extensions can be modules or builtin. If the + * modules are already loaded or are built in, those extensions + * can be initialised right now. Otherwise, the module init + * code will do it. + */ + em28xx_init_extension(dev); + +#if defined(CONFIG_MODULES) && defined(MODULE) if (dev->has_audio_class) request_module("snd-usb-audio"); else if (dev->has_alsa_audio) @@ -2890,6 +2898,7 @@ static void request_module_async(struct work_struct *work) request_module("em28xx-dvb"); if (dev->board.ir_codes && !disable_ir) request_module("em28xx-rc"); +#endif /* CONFIG_MODULES */ } static void request_modules(struct em28xx *dev) @@ -2902,10 +2911,6 @@ static void flush_request_modules(struct em28xx *dev) { flush_work_sync(&dev->request_module_wk); } -#else -#define request_modules(dev) -#define flush_request_modules(dev) -#endif /* CONFIG_MODULES */ /* * em28xx_release_resources() @@ -3324,13 +3329,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, */ mutex_unlock(&dev->lock); - /* - * These extensions can be modules. If the modules are already - * loaded then we can initialise the device now, otherwise we - * will initialise it when the modules load instead. - */ - em28xx_init_extension(dev); - return 0; unlock_and_free: From 434f4d3f1209d4e4c8b0d577d1c809f349c4f0da Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 19 Aug 2012 19:32:27 -0300 Subject: [PATCH 0068/1071] media: rc: ite-cir: Initialise ite_dev::rdev earlier commit 4b961180ef275035b1538317ffd0e21e80e63e77 upstream. ite_dev::rdev is currently initialised in ite_probe() after rc_register_device() returns. If a newly registered device is opened quickly enough, we may enable interrupts and try to use ite_dev::rdev before it has been initialised. Move it up to the earliest point we can, right after calling rc_allocate_device(). Reported-and-tested-by: YunQiang Su Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/ite-cir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 36fe5a349b95d3..24c77a42fc3645 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1473,6 +1473,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id rdev = rc_allocate_device(); if (!rdev) goto failure; + itdev->rdev = rdev; ret = -ENODEV; @@ -1604,7 +1605,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id if (ret) goto failure3; - itdev->rdev = rdev; ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); return 0; From f0510e6733a31862830ae47703cddb84885e070f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4fer?= Date: Sun, 9 Sep 2012 15:02:19 -0300 Subject: [PATCH 0069/1071] media: gspca_pac7302: add support for device 1ae7:2001 Speedlink Snappy Microphone SL-6825-SBK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 97d2fbf501e3cf105ac957086c7e40e62e15cdf8 upstream. Signed-off-by: Frank Schäfer Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/pac7302.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 4877f7ab3d597e..e906f564ca8554 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -905,6 +905,7 @@ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x262a)}, {USB_DEVICE(0x093a, 0x262c)}, {USB_DEVICE(0x145f, 0x013c)}, + {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */ {} }; MODULE_DEVICE_TABLE(usb, device_table); From a84766cd7b1949ececf525dc93de015110fb5625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4fer?= Date: Sun, 9 Sep 2012 15:02:20 -0300 Subject: [PATCH 0070/1071] media: gspca_pac7302: make red balance and blue balance controls work again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit db43b9ca2f101d0945d043fa7d5ecd8f2da17fef upstream. Fix a regression from kernel 3.4 which has been introduced with the conversion of the gspca driver to the v4l2 control framework. Signed-off-by: Frank Schäfer Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/pac7302.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index e906f564ca8554..eb3c90e4a6582f 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -616,7 +616,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_RED_BALANCE, 0, 3, 1, 1); sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 3, 1, 1); + V4L2_CID_BLUE_BALANCE, 0, 3, 1, 1); gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 1); From 7b9d29463b35f8eafa43b42a40bb10435d258945 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 16 Jul 2012 16:30:21 +0800 Subject: [PATCH 0071/1071] ACPI: run _OSC after ACPI_FULL_INITIALIZATION commit fc54ab72959edbf229b65ac74b2f122d799ca002 upstream. The _OSC method may exist in module level code, so it must be called after ACPI_FULL_INITIALIZATION On some new platforms with Zero-Power-Optical-Disk-Drive (ZPODD) support, this fix is necessary to save power. Signed-off-by: Lin Ming Tested-by: Aaron Lu Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/bus.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e0596954290b8e..d59175efc428e5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -994,14 +994,18 @@ static int __init acpi_bus_init(void) status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ - acpi_bus_osc_support(); - status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); goto error1; } + /* + * _OSC method may exist in module level code, + * so it must be run after ACPI_FULL_INITIALIZATION + */ + acpi_bus_osc_support(); + /* * _PDC control method may load dynamic SSDT tables, * and we need to install the table handler before that. From 196d29c060a92d5a2221dd043b8d6903ec211341 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Aug 2012 19:42:43 +0100 Subject: [PATCH 0072/1071] mfd: max8925: Move _IO resources out of ioport_ioresource commit bee6e1fa617b1fb7f6f91033428410e05f5ab0ed upstream. The removal of mach/io.h from most ARM platforms also set the range of valid IO ports to be empty for most platforms when previously any 32 bit integer had been valid. This makes it impossible to add IO resources as the added range is smaller than that of the root resource for IO ports. Since we're not really using IO memory at all fix this by defining our own root resource outside the normal tree and make that the parent of all IO resources. This also ensures we won't conflict with read IO ports if we ever run on a platform which happens to use them. Signed-off-by: Mark Brown Acked-by: Arnd Bergmann Acked-by: Haojian Zhuang Tested-by: Haojian Zhuang Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/max8925-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index ee53757beca7e8..66d08a7bd3d9f0 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -18,12 +18,19 @@ #include #include +static struct resource io_parent = { + .start = 0, + .end = 0xffffffff, + .flags = IORESOURCE_IO, +}; + static struct resource backlight_resources[] = { { .name = "max8925-backlight", .start = MAX8925_WLED_MODE_CNTL, .end = MAX8925_WLED_CNTL, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -42,6 +49,7 @@ static struct resource touch_resources[] = { .start = MAX8925_TSC_IRQ, .end = MAX8925_ADC_RES_END, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -60,6 +68,7 @@ static struct resource power_supply_resources[] = { .start = MAX8925_CHG_IRQ1, .end = MAX8925_CHG_IRQ1_MASK, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -118,6 +127,7 @@ static struct mfd_cell onkey_devs[] = { .start = MAX8925_##_start, \ .end = MAX8925_##_end, \ .flags = IORESOURCE_IO, \ + .parent = &io_parent, \ } static struct resource regulator_resources[] = { From fdb540f319a7a93ada40636c6313bb8e10438ca7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Aug 2012 19:42:44 +0100 Subject: [PATCH 0073/1071] mfd: 88pm860x: Move _IO resources out of ioport_ioresource commit c10c2aab634a3c61c46b98875988b2f53040bc9c upstream. The removal of mach/io.h from most ARM platforms also set the range of valid IO ports to be empty for most platforms when previously any 32 bit integer had been valid. This makes it impossible to add IO resources as the added range is smaller than that of the root resource for IO ports. Since we're not really using IO memory at all fix this by defining our own root resource outside the normal tree and make that the parent of all IO resources. This also ensures we won't conflict with read IO ports if we ever run on a platform which happens to use them. Signed-off-by: Mark Brown Acked-by: Arnd Bergmann Acked-by: Haojian Zhuang Tested-by: Haojian Zhuang Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/88pm860x-core.c | 92 +++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index b73f033b2c602f..81ba6557bb5fa5 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -21,40 +21,73 @@ #define INT_STATUS_NUM 3 +static struct resource io_parent = { + .start = 0, + .end = 0xffffffff, + .flags = IORESOURCE_IO, +}; + static struct resource bk_resources[] __devinitdata = { - {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, - {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, - {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, + {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO, + &io_parent,}, + {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO, + &io_parent,}, + {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO, + &io_parent,}, }; static struct resource led_resources[] __devinitdata = { - {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, - {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, - {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, - {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,}, - {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,}, - {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, + {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO, + &io_parent,}, + {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO, + &io_parent,}, + {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO, + &io_parent,}, + {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO, + &io_parent,}, + {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO, + &io_parent,}, + {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO, + &io_parent,}, }; static struct resource regulator_resources[] __devinitdata = { - {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, - {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, - {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, - {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,}, - {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,}, - {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,}, - {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,}, - {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,}, - {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,}, - {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,}, - {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,}, - {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,}, - {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,}, - {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,}, - {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,}, - {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,}, - {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,}, - {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, + {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO, + &io_parent,}, + {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO, + &io_parent,}, }; static struct resource touch_resources[] __devinitdata = { @@ -91,11 +124,12 @@ static struct resource charger_resources[] __devinitdata = { }; static struct resource preg_resources[] __devinitdata = { - {PM8606_ID_PREG, PM8606_ID_PREG, "preg", IORESOURCE_IO,}, + {PM8606_ID_PREG, PM8606_ID_PREG, "preg", IORESOURCE_IO, + &io_parent,}, }; static struct resource rtc_resources[] __devinitdata = { - {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, + {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ, &io_parent,}, }; static struct mfd_cell bk_devs[] = { From 5761d00bf5760f044224fd7a7500942ff7ba973c Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 4 Oct 2012 17:13:18 -0700 Subject: [PATCH 0074/1071] lib/gcd.c: prevent possible div by 0 commit e96875677fb2b7cb739c5d7769824dff7260d31d upstream. Account for all properties when a and/or b are 0: gcd(0, 0) = 0 gcd(a, 0) = a gcd(0, b) = b Fixes no known problems in current kernels. Signed-off-by: Davidlohr Bueso Cc: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/gcd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/gcd.c b/lib/gcd.c index cce4f3cd14b36f..3657f129d7b8c5 100644 --- a/lib/gcd.c +++ b/lib/gcd.c @@ -9,6 +9,9 @@ unsigned long gcd(unsigned long a, unsigned long b) if (a < b) swap(a, b); + + if (!b) + return a; while ((r = a % b) != 0) { a = b; b = r; From 842f9ae997e6f29c768fde68ba22be81ab4891ab Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 4 Oct 2012 17:12:23 -0700 Subject: [PATCH 0075/1071] kernel/sys.c: call disable_nonboot_cpus() in kernel_restart() commit f96972f2dc6365421cf2366ebd61ee4cf060c8d5 upstream. As kernel_power_off() calls disable_nonboot_cpus(), we may also want to have kernel_restart() call disable_nonboot_cpus(). Doing so can help machines that require boot cpu be the last alive cpu during reboot to survive with kernel restart. This fixes one reboot issue seen on imx6q (Cortex-A9 Quad). The machine requires that the restart routine be run on the primary cpu rather than secondary ones. Otherwise, the secondary core running the restart routine will fail to come to online after reboot. Signed-off-by: Shawn Guo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sys.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sys.c b/kernel/sys.c index 241507f23eca09..6fab59a1fc24d9 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -368,6 +368,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier); void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); + disable_nonboot_cpus(); if (!cmd) printk(KERN_EMERG "Restarting system.\n"); else From 4b45def3ed7625fa553eb8ae42624dd7dd3239e7 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Thu, 4 Oct 2012 17:11:25 -0700 Subject: [PATCH 0076/1071] drivers/scsi/atp870u.c: fix bad use of udelay commit 0f6d93aa9d96cc9022b51bd10d462b03296be146 upstream. The ACARD driver calls udelay() with a value > 2000, which leads to to the following compilation error on ARM: ERROR: "__bad_udelay" [drivers/scsi/atp870u.ko] undefined! make[1]: *** [__modpost] Error 1 This is because udelay is defined on ARM, roughly speaking, as #define udelay(n) ((n) > 2000 ? __bad_udelay() : \ __const_udelay((n) * ((2199023U*HZ)>>11))) The argument to __const_udelay is the number of jiffies to wait divided by 4, but this does not work unless the multiplication does not overflow, and that is what the build error is designed to prevent. The intended behavior can be achieved by using mdelay to call udelay multiple times in a loop. [jrnieder@gmail.com: adding context] Signed-off-by: Martin Michlmayr Signed-off-by: Jonathan Nieder Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/atp870u.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 68ce08552f699b..a540162ac59c14 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1173,7 +1173,16 @@ static void tscam(struct Scsi_Host *host) outw(val, tmport); outb(2, 0x80); TCM_SYNC: - udelay(0x800); + /* + * The funny division into multiple delays is to accomodate + * arches like ARM where udelay() multiplies its argument by + * a large number to initialize a loop counter. To avoid + * overflow, the maximum supported udelay is 2000 microseconds. + * + * XXX it would be more polite to find a way to use msleep() + */ + mdelay(2); + udelay(48); if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ outw(0, tmport--); outb(0, tmport); From 0c9f520eff046d5dea7ab8ac20f5835288300625 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 4 Oct 2012 17:11:16 -0700 Subject: [PATCH 0077/1071] drivers/dma/dmaengine.c: lower the priority of 'failed to get' dma channel message commit 0eb5a35801df3c438ce3fc91310a415ea4452c00 upstream. Do the same as commit a03a202e95fd ("dmaengine: failure to get a specific DMA channel is not critical") to get rid of the following messages during kernel boot: dmaengine_get: failed to get dma1chan0: (-22) dmaengine_get: failed to get dma1chan1: (-22) dmaengine_get: failed to get dma1chan2: (-22) dmaengine_get: failed to get dma1chan3: (-22) .. Signed-off-by: Fabio Estevam Cc: Vinod Koul Cc: Dan Williams Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/dma/dmaengine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 3491654cdf7b84..a815d44c70a41b 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -582,7 +582,7 @@ void dmaengine_get(void) list_del_rcu(&device->global_node); break; } else if (err) - pr_err("%s: failed to get %s: (%d)\n", + pr_debug("%s: failed to get %s: (%d)\n", __func__, dma_chan_name(chan), err); } } From 60b3e539bffddda2f1dd41d77e7353e864cca210 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 4 Oct 2012 12:03:25 +0930 Subject: [PATCH 0078/1071] lguest: fix occasional crash in example launcher. commit ca16f580a5db7e60bfafe59a50bb133bd3347491 upstream. We usually got away with ->next on the final entry being NULL, but it finally bit me. Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- tools/lguest/lguest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index f759f4f097c7f5..fd2f9221b24120 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -1299,6 +1299,7 @@ static struct device *new_device(const char *name, u16 type) dev->feature_len = 0; dev->num_vq = 0; dev->running = false; + dev->next = NULL; /* * Append to device list. Prepending to a single-linked list is From dede562fbfe509c3e84d8259822f8612416316cf Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 1 Oct 2012 14:59:13 +0000 Subject: [PATCH 0079/1071] powerpc: Fix VMX fix for memcpy case commit c8adfeccee01ce3de6a7d14fcd4e3be02e27f03c upstream. In 2fae7cdb60240e2e2d9b378afbf6d9fcce8a3890 ("powerpc: Fix VMX in interrupt check in POWER7 copy loops"), Anton inadvertently introduced a regression for memcpy on POWER7 machines. copyuser and memcpy diverge slightly in their use of cr1 (copyuser doesn't use it, but memcpy does) and you end up clobbering that register with your fix. That results in (taken from an FC18 kernel): [ 18.824604] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052f40 [ 18.824618] Oops: Unrecoverable VMX/Altivec Unavailable Exception, sig: 6 [#1] [ 18.824623] SMP NR_CPUS=1024 NUMA pSeries [ 18.824633] Modules linked in: tg3(+) be2net(+) cxgb4(+) ipr(+) sunrpc xts lrw gf128mul dm_crypt dm_round_robin dm_multipath linear raid10 raid456 async_raid6_recov async_memcpy async_pq raid6_pq async_xor xor async_tx raid1 raid0 scsi_dh_rdac scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua squashfs cramfs [ 18.824705] NIP: c000000000052f40 LR: c00000000020b874 CTR: 0000000000000512 [ 18.824709] REGS: c000001f1fef7790 TRAP: 0f20 Not tainted (3.6.0-0.rc6.git0.2.fc18.ppc64) [ 18.824713] MSR: 8000000000009032 CR: 4802802e XER: 20000010 [ 18.824726] SOFTE: 0 [ 18.824728] CFAR: 0000000000000f20 [ 18.824731] TASK = c000000fa7128400[0] 'swapper/24' THREAD: c000000fa7480000 CPU: 24 GPR00: 00000000ffffffc0 c000001f1fef7a10 c00000000164edc0 c000000f9b9a8120 GPR04: c000000f9b9a8124 0000000000001438 0000000000000060 03ffffff064657ee GPR08: 0000000080000000 0000000000000010 0000000000000020 0000000000000030 GPR12: 0000000028028022 c00000000ff25400 0000000000000001 0000000000000000 GPR16: 0000000000000000 7fffffffffffffff c0000000016b2180 c00000000156a500 GPR20: c000000f968c7a90 c0000000131c31d8 c000001f1fef4000 c000000001561d00 GPR24: 000000000000000a 0000000000000000 0000000000000001 0000000000000012 GPR28: c000000fa5c04f80 00000000000008bc c0000000015c0a28 000000000000022e [ 18.824792] NIP [c000000000052f40] .memcpy_power7+0x5a0/0x7c4 [ 18.824797] LR [c00000000020b874] .pcpu_free_area+0x174/0x2d0 [ 18.824800] Call Trace: [ 18.824803] [c000001f1fef7a10] [c000000000052c14] .memcpy_power7+0x274/0x7c4 (unreliable) [ 18.824809] [c000001f1fef7b10] [c00000000020b874] .pcpu_free_area+0x174/0x2d0 [ 18.824813] [c000001f1fef7bb0] [c00000000020ba88] .free_percpu+0xb8/0x1b0 [ 18.824819] [c000001f1fef7c50] [c00000000043d144] .throtl_pd_exit+0x94/0xd0 [ 18.824824] [c000001f1fef7cf0] [c00000000043acf8] .blkg_free+0x88/0xe0 [ 18.824829] [c000001f1fef7d90] [c00000000018c048] .rcu_process_callbacks+0x2e8/0x8a0 [ 18.824835] [c000001f1fef7e90] [c0000000000a8ce8] .__do_softirq+0x158/0x4d0 [ 18.824840] [c000001f1fef7f90] [c000000000025ecc] .call_do_softirq+0x14/0x24 [ 18.824845] [c000000fa7483650] [c000000000010e80] .do_softirq+0x160/0x1a0 [ 18.824850] [c000000fa74836f0] [c0000000000a94a4] .irq_exit+0xf4/0x120 [ 18.824854] [c000000fa7483780] [c000000000020c44] .timer_interrupt+0x154/0x4d0 [ 18.824859] [c000000fa7483830] [c000000000003be0] decrementer_common+0x160/0x180 [ 18.824866] --- Exception: 901 at .plpar_hcall_norets+0x84/0xd4 [ 18.824866] LR = .check_and_cede_processor+0x48/0x80 [ 18.824871] [c000000fa7483b20] [c00000000007f018] .check_and_cede_processor+0x18/0x80 (unreliable) [ 18.824877] [c000000fa7483b90] [c00000000007f104] .dedicated_cede_loop+0x84/0x150 [ 18.824883] [c000000fa7483c50] [c0000000006bc030] .cpuidle_enter+0x30/0x50 [ 18.824887] [c000000fa7483cc0] [c0000000006bc9f4] .cpuidle_idle_call+0x104/0x720 [ 18.824892] [c000000fa7483d80] [c000000000070af8] .pSeries_idle+0x18/0x40 [ 18.824897] [c000000fa7483df0] [c000000000019084] .cpu_idle+0x1a4/0x380 [ 18.824902] [c000000fa7483ec0] [c0000000008a4c18] .start_secondary+0x520/0x528 [ 18.824907] [c000000fa7483f90] [c0000000000093f0] .start_secondary_prolog+0x10/0x14 [ 18.824911] Instruction dump: [ 18.824914] 38840008 90030000 90e30004 38630008 7ca62850 7cc300d0 78c7e102 7cf01120 [ 18.824923] 78c60660 39200010 39400020 39600030 <7e00200c> 7c0020ce 38840010 409f001c [ 18.824935] ---[ end trace 0bb95124affaaa45 ]--- [ 18.825046] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052d08 I believe the right fix is to make memcpy match usercopy and not use cr1. Signed-off-by: Nishanth Aravamudan Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/lib/memcpy_power7.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S index 7ba6c96de77856..0663630baf3b46 100644 --- a/arch/powerpc/lib/memcpy_power7.S +++ b/arch/powerpc/lib/memcpy_power7.S @@ -239,8 +239,8 @@ _GLOBAL(memcpy_power7) ori r9,r9,1 /* stream=1 */ srdi r7,r5,7 /* length in cachelines, capped at 0x3FF */ - cmpldi cr1,r7,0x3FF - ble cr1,1f + cmpldi r7,0x3FF + ble 1f li r7,0x3FF 1: lis r0,0x0E00 /* depth=7 */ sldi r7,r7,7 From edfd73d1bff85b117ee3c5d10da6c9645fe60d45 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Mon, 17 Sep 2012 04:34:28 +0000 Subject: [PATCH 0080/1071] powerpc/eeh: Fix crash on converting OF node to edev commit 1e38b7140185e384da216aff66a711df09b5afc9 upstream. The kernel crash was reported by Alexy. He was testing some feature with private kernel, in which Alexy added some code in pci_pm_reset() to read the CSR after writting it. The bug could be reproduced on Fiber Channel card (Fibre Channel: Emulex Corporation Saturn-X: LightPulse Fibre Channel Host Adapter (rev 03)) by the following commands. # echo 1 > /sys/devices/pci0004:01/0004:01:00.0/reset # rmmod lpfc # modprobe lpfc The history behind the test case is that those additional config space reading operations in pci_pm_reset() would cause EEH error, but we didn't detect EEH error until "modprobe lpfc". For the case, all the PCI devices on PCI bus (0004:01) were removed and added after PE reset. Then the EEH devices would be figured out again based on the OF nodes. Unfortunately, there were some child OF nodes under PCI device (0004:01:00.0), but they didn't have attached PCI_DN since they're invisible from PCI domain. However, we were still trying to convert OF node to EEH device without checking on the attached PCI_DN. Eventually, it caused the kernel crash as follows: Unable to handle kernel paging request for data at address 0x00000030 Faulting instruction address: 0xc00000000004d888 cpu 0x0: Vector: 300 (Data Access) at [c000000fc797b950] pc: c00000000004d888: .eeh_add_device_tree_early+0x78/0x140 lr: c00000000004d880: .eeh_add_device_tree_early+0x70/0x140 sp: c000000fc797bbd0 msr: 8000000000009032 dar: 30 dsisr: 40000000 current = 0xc000000fc78d9f70 paca = 0xc00000000edb0000 softe: 0 irq_happened: 0x00 pid = 2951, comm = eehd enter ? for help [c000000fc797bc50] c00000000004d848 .eeh_add_device_tree_early+0x38/0x140 [c000000fc797bcd0] c00000000004d848 .eeh_add_device_tree_early+0x38/0x140 [c000000fc797bd50] c000000000051b54 .pcibios_add_pci_devices+0x34/0x190 [c000000fc797bde0] c00000000004fb10 .eeh_reset_device+0x100/0x160 [c000000fc797be70] c0000000000502dc .eeh_handle_event+0x19c/0x300 [c000000fc797bf00] c000000000050570 .eeh_event_handler+0x130/0x1a0 [c000000fc797bf90] c000000000020138 .kernel_thread+0x54/0x70 The patch changes of_node_to_eeh_dev() and just returns NULL if the passed OF node doesn't have attached PCI_DN. Reported-by: Alexey Kardashevskiy Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/pci-bridge.h | 8 ++++++++ arch/powerpc/platforms/pseries/eeh.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 8cccbee6151988..78326dee93a887 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -182,6 +182,14 @@ static inline int pci_device_from_OF_node(struct device_node *np, #if defined(CONFIG_EEH) static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) { + /* + * For those OF nodes whose parent isn't PCI bridge, they + * don't have PCI_DN actually. So we have to skip them for + * any EEH operations. + */ + if (!dn || !PCI_DN(dn)) + return NULL; + return PCI_DN(dn)->edev; } #endif diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index ecd394cf34e604..9a0b5f59a0d7d3 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1029,7 +1029,7 @@ static void eeh_add_device_early(struct device_node *dn) { struct pci_controller *phb; - if (!dn || !of_node_to_eeh_dev(dn)) + if (!of_node_to_eeh_dev(dn)) return; phb = of_node_to_eeh_dev(dn)->phb; From f1cebb761c0cb4a550f2e8567fdb0a12f27b3878 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 21 Sep 2012 07:23:20 +0000 Subject: [PATCH 0081/1071] ixgbe: fix PTP ethtool timestamping function commit 1cc92eb871d6cbb1da038b4bcd89eec3c73b9781 upstream. This patch fixes a development issue that occurred due to invalid modes reported in the ethtool get_ts_info function. The issue is resolved by removing unsupported modes from the Rx supported list. Signed-off-by: Jacob Keller Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 4104ea25d81844..56b20d17d0e4c5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2690,10 +2690,7 @@ static int ixgbe_get_ts_info(struct net_device *dev, (1 << HWTSTAMP_FILTER_NONE) | (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | - (1 << HWTSTAMP_FILTER_SOME); + (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); break; #endif /* CONFIG_IXGBE_PTP */ default: From e23dfd7c2925856d19b875b1fbb2a0cd5c67180b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 2 Oct 2012 16:01:15 -0300 Subject: [PATCH 0082/1071] drxk: allow loading firmware synchrousnously commit 8e30783b0b3270736b2cff6415c68b894bc411df upstream. Due to udev-182, the firmware load was changed to be async, as otherwise udev would give up of loading a firmware. Add an option to return to the previous behaviour, async firmware loads cause failures with the tda18271 driver. Antti tested it with the following hardware: Hauppauge WinTV HVR 930C MaxMedia UB425-TC PCTV QuatroStick nano (520e) Tested-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/frontends/drxk.h | 2 ++ drivers/media/dvb/frontends/drxk_hard.c | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h index d615d7d055a29d..94fecfbf14c127 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb/frontends/drxk.h @@ -28,6 +28,7 @@ * A value of 0 (default) or lower indicates that * the correct number of parameters will be * automatically detected. + * @load_firmware_sync: Force the firmware load to be synchronous. * * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is * UIO-3. @@ -39,6 +40,7 @@ struct drxk_config { bool parallel_ts; bool dynamic_clk; bool enable_merr_cfg; + bool load_firmware_sync; bool antenna_dvbt; u16 antenna_gpio; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 1ab8154542daeb..8b4c6d5f8f3694 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -6609,15 +6609,25 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, /* Load firmware and initialize DRX-K */ if (state->microcode_name) { - status = request_firmware_nowait(THIS_MODULE, 1, + if (config->load_firmware_sync) { + const struct firmware *fw = NULL; + + status = request_firmware(&fw, state->microcode_name, + state->i2c->dev.parent); + if (status < 0) + fw = NULL; + load_firmware_cb(fw, state); + } else { + status = request_firmware_nowait(THIS_MODULE, 1, state->microcode_name, state->i2c->dev.parent, GFP_KERNEL, state, load_firmware_cb); - if (status < 0) { - printk(KERN_ERR - "drxk: failed to request a firmware\n"); - return NULL; + if (status < 0) { + printk(KERN_ERR + "drxk: failed to request a firmware\n"); + return NULL; + } } } else if (init_drxk(state) < 0) goto error; From 40c975a26226ae76d5d0809dc383544cdf3a11d7 Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Thu, 4 Oct 2012 17:15:48 -0700 Subject: [PATCH 0083/1071] rapidio/rionet: fix multicast packet transmit logic commit 7c4a6106d6451fc03c491e61df37c044505d843a upstream. Fix multicast packet transmit logic to account for repetitive transmission of single skb: - correct check for available buffers (this bug may produce NULL pointer crash dump in case of heavy traffic); - update skb user count (incorrect user counter causes a warning dump from net_tx_action routine during multicast transfers in systems with three or more rionet participants). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: David S. Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/net/rionet.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 91d25888a1b98b..1470d3e86e3ce2 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -79,6 +79,7 @@ static int rionet_capable = 1; * on system trade-offs. */ static struct rio_dev **rionet_active; +static int nact; /* total number of active rionet peers */ #define is_rionet_capable(src_ops, dst_ops) \ ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ @@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct ethhdr *eth = (struct ethhdr *)skb->data; u16 destid; unsigned long flags; + int add_num = 1; local_irq_save(flags); if (!spin_trylock(&rnet->tx_lock)) { @@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_LOCKED; } - if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) { + if (is_multicast_ether_addr(eth->h_dest)) + add_num = nact; + + if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { netif_stop_queue(ndev); spin_unlock_irqrestore(&rnet->tx_lock, flags); printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", @@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) } if (is_multicast_ether_addr(eth->h_dest)) { + int count = 0; for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); i++) - if (rionet_active[i]) + if (rionet_active[i]) { rionet_queue_tx_msg(skb, ndev, rionet_active[i]); + if (count) + atomic_inc(&skb->users); + count++; + } } else if (RIONET_MAC_MATCH(eth->h_dest)) { destid = RIONET_GET_DESTID(eth->h_dest); if (rionet_active[destid]) @@ -220,14 +230,17 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u if (info == RIONET_DOORBELL_JOIN) { if (!rionet_active[sid]) { list_for_each_entry(peer, &rionet_peers, node) { - if (peer->rdev->destid == sid) + if (peer->rdev->destid == sid) { rionet_active[sid] = peer->rdev; + nact++; + } } rio_mport_send_doorbell(mport, sid, RIONET_DOORBELL_JOIN); } } else if (info == RIONET_DOORBELL_LEAVE) { rionet_active[sid] = NULL; + nact--; } else { if (netif_msg_intr(rnet)) printk(KERN_WARNING "%s: unhandled doorbell\n", @@ -523,6 +536,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) rc = rionet_setup_netdev(rdev->net->hport, ndev); rionet_check = 1; + nact = 0; } /* From 05a65b235fb23759f3d0912f2967f6f2cd1a5c1d Mon Sep 17 00:00:00 2001 From: Feng Hong Date: Wed, 19 Sep 2012 14:16:00 +0200 Subject: [PATCH 0084/1071] PM / Sleep: use resume event when call dpm_resume_early commit 997a031107ec962967ce36db9bc500f1fad491c1 upstream. When dpm_suspend_noirq fail, state is PMSG_SUSPEND, should change to PMSG_RESUME when dpm_resume_early is called Signed-off-by: Feng Hong Signed-off-by: Raul Xiong Signed-off-by: Neil Zhang Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 0113adc310dccc..2700f2e4066fdd 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -996,7 +996,7 @@ int dpm_suspend_end(pm_message_t state) error = dpm_suspend_noirq(state); if (error) { - dpm_resume_early(state); + dpm_resume_early(resume_event(state)); return error; } From d878ce75405d3fc90b0253d44ce603e5948584fb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 3 Aug 2012 10:30:45 -0700 Subject: [PATCH 0085/1071] workqueue: add missing smp_wmb() in process_one_work() commit 959d1af8cffc8fd38ed53e8be1cf4ab8782f9c00 upstream. WORK_STRUCT_PENDING is used to claim ownership of a work item and process_one_work() releases it before starting execution. When someone else grabs PENDING, all pre-release updates to the work item should be visible and all updates made by the new owner should happen afterwards. Grabbing PENDING uses test_and_set_bit() and thus has a full barrier; however, clearing doesn't have a matching wmb. Given the preceding spin_unlock and use of clear_bit, I don't believe this can be a problem on an actual machine and there hasn't been any related report but it still is theretically possible for clear_pending to permeate upwards and happen before work->entry update. Add an explicit smp_wmb() before work_clear_pending(). Signed-off-by: Tejun Heo Cc: Oleg Nesterov Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 3c5a79e2134cac..cb16c8a82a148b 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2073,7 +2073,9 @@ __acquires(&gcwq->lock) spin_unlock_irq(&gcwq->lock); + smp_wmb(); /* paired with test_and_set_bit(PENDING) */ work_clear_pending(work); + lock_map_acquire_read(&cwq->wq->lockdep_map); lock_map_acquire(&lockdep_map); trace_workqueue_execute_start(work); From d024fea7032bc7c333c967db530b44d59a180d14 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Tue, 18 Sep 2012 10:40:00 -0700 Subject: [PATCH 0086/1071] workqueue: fix possible stall on try_to_grab_pending() of a delayed work item commit 3aa62497594430ea522050b75c033f71f2c60ee6 upstream. Currently, when try_to_grab_pending() grabs a delayed work item, it leaves its linked work items alone on the delayed_works. The linked work items are always NO_COLOR and will cause future cwq_activate_first_delayed() increase cwq->nr_active incorrectly, and may cause the whole cwq to stall. For example, state: cwq->max_active = 1, cwq->nr_active = 1 one work in cwq->pool, many in cwq->delayed_works. step1: try_to_grab_pending() removes a work item from delayed_works but leaves its NO_COLOR linked work items on it. step2: Later on, cwq_activate_first_delayed() activates the linked work item increasing ->nr_active. step3: cwq->nr_active = 1, but all activated work items of the cwq are NO_COLOR. When they finish, cwq->nr_active will not be decreased due to NO_COLOR, and no further work items will be activated from cwq->delayed_works. the cwq stalls. Fix it by ensuring the target work item is activated before stealing PENDING in try_to_grab_pending(). This ensures that all the linked work items are activated without incorrectly bumping cwq->nr_active. tj: Updated comment and description. Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index cb16c8a82a148b..872bd6d9be2d10 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1927,10 +1927,9 @@ static void move_linked_works(struct work_struct *work, struct list_head *head, *nextp = n; } -static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) +static void cwq_activate_delayed_work(struct work_struct *work) { - struct work_struct *work = list_first_entry(&cwq->delayed_works, - struct work_struct, entry); + struct cpu_workqueue_struct *cwq = get_work_cwq(work); trace_workqueue_activate_work(work); move_linked_works(work, &cwq->pool->worklist, NULL); @@ -1938,6 +1937,14 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) cwq->nr_active++; } +static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) +{ + struct work_struct *work = list_first_entry(&cwq->delayed_works, + struct work_struct, entry); + + cwq_activate_delayed_work(work); +} + /** * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight * @cwq: cwq of interest @@ -2846,6 +2853,18 @@ static int try_to_grab_pending(struct work_struct *work) smp_rmb(); if (gcwq == get_work_gcwq(work)) { debug_work_deactivate(work); + + /* + * A delayed work item cannot be grabbed directly + * because it might have linked NO_COLOR work items + * which, if left on the delayed_list, will confuse + * cwq->nr_active management later on and cause + * stall. Make sure the work item is activated + * before grabbing. + */ + if (*work_data_bits(work) & WORK_STRUCT_DELAYED) + cwq_activate_delayed_work(work); + list_del_init(&work->entry); cwq_dec_nr_in_flight(get_work_cwq(work), get_work_color(work), From 14b4ed22a6b5fc1549504336131be4f5f6ba1bf4 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sat, 18 Aug 2012 22:29:40 -0400 Subject: [PATCH 0087/1071] jbd2: don't write superblock when if its empty commit eeecef0af5ea4efd763c9554cf2bd80fc4a0efd3 upstream. This sequence: # truncate --size=1g fsfile # mkfs.ext4 -F fsfile # mount -o loop,ro fsfile /mnt # umount /mnt # dmesg | tail results in an IO error when unmounting the RO filesystem: [ 318.020828] Buffer I/O error on device loop1, logical block 196608 [ 318.027024] lost page write due to I/O error on loop1 [ 318.032088] JBD2: Error -5 detected when updating journal superblock for loop1-8. This was a regression introduced by commit 24bcc89c7e7c: "jbd2: split updating of journal superblock and marking journal empty". Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/journal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index e149b99a7ffb8e..484b8d1c6cb6cd 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1354,6 +1354,11 @@ static void jbd2_mark_journal_empty(journal_t *journal) BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); read_lock(&journal->j_state_lock); + /* Is it already empty? */ + if (sb->s_start == 0) { + read_unlock(&journal->j_state_lock); + return; + } jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", journal->j_tail_sequence); From c1d5777da53b53e02b38845ef9e80ac542f6a08a Mon Sep 17 00:00:00 2001 From: Yuta Ando Date: Mon, 1 Oct 2012 23:24:30 +0900 Subject: [PATCH 0088/1071] localmodconfig: Fix localyesconfig to set to 'y' not 'm' commit 4eae518d4b01b0cbf2f0d8edb5a6f3d6245ee8fb upstream. The kbuild target 'localyesconfig' has been same as 'localmodconfig' since the commit 50bce3e "kconfig/streamline_config.pl: merge local{mod,yes}config". The commit expects this script generates different configure depending on target, but it was not yet implemented. So I added code that sets to 'yes' when target is 'localyesconfig'. Link: http://lkml.kernel.org/r/1349101470-12243-1-git-send-email-yuta.and@gmail.com Signed-off-by: Yuta Ando Cc: linux-kbuild@vger.kernel.org Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- scripts/kconfig/streamline_config.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 2fbbbc1ddea02a..5eb37772daefc3 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -605,6 +605,8 @@ sub loop_select { if (defined($configs{$1})) { if ($localyesconfig) { $setconfigs{$1} = 'y'; + print "$1=y\n"; + next; } else { $setconfigs{$1} = $2; } From 52fc5048534e9d4127622fa5a269a92f3bb5218b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 4 Oct 2012 01:25:26 +0000 Subject: [PATCH 0089/1071] ipv4: add a fib_type to fib_info [ Upstream commit f4ef85bbda96324785097356336bc79cdd37db0a ] commit d2d68ba9fe8 (ipv4: Cache input routes in fib_info nexthops.) introduced a regression for forwarding. This was hard to reproduce but the symptom was that packets were delivered to local host instead of being forwarded. David suggested to add fib_type to fib_info so that we dont inadvertently share same fib_info for different purposes. With help from Julian Anastasov who provided very helpful hints, reproduced here : Can it be a problem related to fib_info reuse from different routes. For example, when local IP address is created for subnet we have: broadcast 192.168.0.255 dev DEV proto kernel scope link src 192.168.0.1 192.168.0.0/24 dev DEV proto kernel scope link src 192.168.0.1 local 192.168.0.1 dev DEV proto kernel scope host src 192.168.0.1 The "dev DEV proto kernel scope link src 192.168.0.1" is a reused fib_info structure where we put cached routes. The result can be same fib_info for 192.168.0.255 and 192.168.0.0/24. RTN_BROADCAST is cached only for input routes. Incoming broadcast to 192.168.0.255 can be cached and can cause problems for traffic forwarded to 192.168.0.0/24. So, this patch should solve the problem because it separates the broadcast from unicast traffic. And the ip_route_input_slow caching will work for local and broadcast input routes (above routes 1 and 3) just because they differ in scope and use different fib_info. Many thanks to Chris Clayton for his patience and help. Reported-by: Chris Clayton Bisected-by: Chris Clayton Reported-by: Dave Jones Signed-off-by: Eric Dumazet Cc: Julian Anastasov Tested-by: Chris Clayton Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ip_fib.h | 1 + net/ipv4/fib_semantics.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 926142ed8d7aa6..9497be1ad4c0c5 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -102,6 +102,7 @@ struct fib_info { unsigned char fib_dead; unsigned char fib_protocol; unsigned char fib_scope; + unsigned char fib_type; __be32 fib_prefsrc; u32 fib_priority; u32 *fib_metrics; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index da80dc14cc76f5..a74710048b13e3 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -314,6 +314,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) nfi->fib_scope == fi->fib_scope && nfi->fib_prefsrc == fi->fib_prefsrc && nfi->fib_priority == fi->fib_priority && + nfi->fib_type == fi->fib_type && memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(u32) * RTAX_MAX) == 0 && ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && @@ -833,6 +834,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) fi->fib_flags = cfg->fc_flags; fi->fib_priority = cfg->fc_priority; fi->fib_prefsrc = cfg->fc_prefsrc; + fi->fib_type = cfg->fc_type; fi->fib_nhs = nhs; change_nexthops(fi) { From 57d8849c5fa2aa2e0b91aa2f822c6a41b2d879d4 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 2 Oct 2012 06:14:17 +0000 Subject: [PATCH 0090/1071] 8021q: fix mac_len recomputation in vlan_untag() [ Upstream commit 5316cf9a5197eb80b2800e1acadde287924ca975 ] skb_reset_mac_len() relies on the value of the skb->network_header pointer, therefore we must wait for such pointer to be recalculated before computing the new mac_len value. Signed-off-by: Antonio Quartulli Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/8021q/vlan_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 8ca533c95de034..830059ded496cd 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -105,7 +105,6 @@ static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) return NULL; memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); skb->mac_header += VLAN_HLEN; - skb_reset_mac_len(skb); return skb; } @@ -139,6 +138,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb) skb_reset_network_header(skb); skb_reset_transport_header(skb); + skb_reset_mac_len(skb); + return skb; err_free: From 0f1bf6e2dc225d9bfce3be0be0b2f22956bcb313 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Wed, 19 Sep 2012 19:25:34 +0000 Subject: [PATCH 0091/1071] ipv6: release reference of ip6_null_entry's dst entry in __ip6_del_rt [ Upstream commit 6825a26c2dc21eb4f8df9c06d3786ddec97cf53b ] as we hold dst_entry before we call __ip6_del_rt, so we should alse call dst_release not only return -ENOENT when the rt6_info is ip6_null_entry. and we already hold the dst entry, so I think it's safe to call dst_release out of the write-read lock. Signed-off-by: Gao feng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 854e4018d205c8..46eff4238e367d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1589,17 +1589,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) struct fib6_table *table; struct net *net = dev_net(rt->dst.dev); - if (rt == net->ipv6.ip6_null_entry) - return -ENOENT; + if (rt == net->ipv6.ip6_null_entry) { + err = -ENOENT; + goto out; + } table = rt->rt6i_table; write_lock_bh(&table->tb6_lock); - err = fib6_del(rt, info); - dst_release(&rt->dst); - write_unlock_bh(&table->tb6_lock); +out: + dst_release(&rt->dst); return err; } From 15fb2c5df65705de850c003eb23dadebc4042af6 Mon Sep 17 00:00:00 2001 From: Tao Hou Date: Mon, 1 Oct 2012 16:42:43 +0000 Subject: [PATCH 0092/1071] net: ethernet: davinci_cpdma: decrease the desc count when cleaning up the remaining packets [ Upstream commit ffb5ba90017505a19e238e986e6d33f09e4df765 ] chan->count is used by rx channel. If the desc count is not updated by the clean up loop in cpdma_chan_stop, the value written to the rxfree register in cpdma_chan_start will be incorrect. Signed-off-by: Tao Hou Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/ti/davinci_cpdma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index d15c888e9df8a1..49956730cd8db8 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -863,6 +863,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan) next_dma = desc_read(desc, hw_next); chan->head = desc_from_phys(pool, next_dma); + chan->count--; chan->stats.teardown_dequeue++; /* issue callback without locks held */ From 13d536a0bb25c10e183bc022a1b88dc097aad15d Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 26 Sep 2012 00:04:55 +0000 Subject: [PATCH 0093/1071] ipv6: del unreachable route when an addr is deleted on lo [ Upstream commit 64c6d08e6490fb18cea09bb03686c149946bd818 ] When an address is added on loopback (ip -6 a a 2002::1/128 dev lo), two routes are added: - one in the local table: local 2002::1 via :: dev lo proto none metric 0 - one the in main table (for the prefix): unreachable 2002::1 dev lo proto kernel metric 256 error -101 When the address is deleted, the route inserted in the main table remains because we use rt6_lookup(), which returns NULL when dst->error is set, which is the case here! Thus, it is better to use ip6_route_lookup() to avoid this kind of filter. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6bc85f7c31e3c5..ea3e9af86d4bf7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -788,10 +788,16 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) struct in6_addr prefix; struct rt6_info *rt; struct net *net = dev_net(ifp->idev->dev); + struct flowi6 fl6 = {}; + ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); - rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); + fl6.flowi6_oif = ifp->idev->dev->ifindex; + fl6.daddr = prefix; + rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, + RT6_LOOKUP_F_IFACE); - if (rt && addrconf_is_prefix_route(rt)) { + if (rt != net->ipv6.ip6_null_entry && + addrconf_is_prefix_route(rt)) { if (onlink == 0) { ip6_del_rt(rt); rt = NULL; From d70fd1a97eddef329ae3c63e72d38529862bded2 Mon Sep 17 00:00:00 2001 From: Florian Zumbiehl Date: Tue, 2 Oct 2012 12:20:37 +0000 Subject: [PATCH 0094/1071] drm/savage: re-add busmaster enable, regression fix commit df86b5765a48d5f557489577652bd6df145b0e1b upstream. 466e69b8b03b8c1987367912782bc12988ad8794 dropped busmaster enable from the global drm code and moved it to the individual drivers, but missed the savage driver. So, this re-adds busmaster enable to the savage driver, fixing the regression. Signed-off-by: Florian Zumbiehl Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/savage/savage_bci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index 1efbb90758378a..c89aef420971d0 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -547,6 +547,8 @@ int savage_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->chipset = (enum savage_family)chipset; + pci_set_master(dev->pdev); + return 0; } From 6b00187c43c099c6648a6e9fd0f36b0663aca5d6 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:29 +0200 Subject: [PATCH 0095/1071] SCSI: zfcp: Adapt to new FC_PORTSPEED semantics commit d22019778cd9ea04c1dadf7bf453920d5288f8d9 upstream. Commit a9277e7783651d4e0a849f7988340b1c1cf748a4 "[SCSI] scsi_transport_fc: Getting FC Port Speed in sync with FC-GS" changed the semantics of FC_PORTSPEED defines to FDMI port attributes of FC-HBA/SM-HBA which is different from the previous bit reversed Report Port Speed Capabilities (RPSC) ELS of FC-GS/FC-LS. Zfcp showed "10 Gbit" instead of "4 Gbit" for supported_speeds. It now uses explicit bit conversion as the other LLDs already do, in order to be independent of the kernel bit semantics. See also http://marc.info/?l=linux-scsi&m=134452926830730&w=2 Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_fsf.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e1c1efc2c5a0f3..30436d53d358fb 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -437,6 +437,34 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) } } +#define ZFCP_FSF_PORTSPEED_1GBIT (1 << 0) +#define ZFCP_FSF_PORTSPEED_2GBIT (1 << 1) +#define ZFCP_FSF_PORTSPEED_4GBIT (1 << 2) +#define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3) +#define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4) +#define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5) +#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15) + +static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) +{ + u32 fdmi_speed = 0; + if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT) + fdmi_speed |= FC_PORTSPEED_1GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT) + fdmi_speed |= FC_PORTSPEED_2GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT) + fdmi_speed |= FC_PORTSPEED_4GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT) + fdmi_speed |= FC_PORTSPEED_10GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT) + fdmi_speed |= FC_PORTSPEED_8GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT) + fdmi_speed |= FC_PORTSPEED_16GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED) + fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED; + return fdmi_speed; +} + static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) { struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; @@ -456,7 +484,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) fc_host_port_name(shost) = nsp->fl_wwpn; fc_host_node_name(shost) = nsp->fl_wwnn; fc_host_port_id(shost) = ntoh24(bottom->s_id); - fc_host_speed(shost) = bottom->fc_link_speed; + fc_host_speed(shost) = + zfcp_fsf_convert_portspeed(bottom->fc_link_speed); fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; adapter->hydra_version = bottom->adapter_type; @@ -580,7 +609,8 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) } else fc_host_permanent_port_name(shost) = fc_host_port_name(shost); fc_host_maxframe_size(shost) = bottom->maximum_frame_size; - fc_host_supported_speeds(shost) = bottom->supported_speed; + fc_host_supported_speeds(shost) = + zfcp_fsf_convert_portspeed(bottom->supported_speed); memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, FC_FC4_LIST_SIZE); memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, From f2e388ca8361ca66ed4090e54e287000f9c6e3b4 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:30 +0200 Subject: [PATCH 0096/1071] SCSI: zfcp: Make trace record tags unique commit 0100998dbfe6dfcd90a6e912ca7ed6f255d48f25 upstream. Duplicate fssrh_2 from a54ca0f62f953898b05549391ac2a8a4dad6482b "[SCSI] zfcp: Redesign of the debug tracing for HBA records." complicates distinction of generic status read response from local link up. Duplicate fsscth1 from 2c55b750a884b86dea8b4cc5f15e1484cc47a25c "[SCSI] zfcp: Redesign of the debug tracing for SAN records." complicates distinction of good common transport response from invalid port handle. Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_fsf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 30436d53d358fb..6e2892e7c4be96 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) return; } - zfcp_dbf_hba_fsf_uss("fssrh_2", req); + zfcp_dbf_hba_fsf_uss("fssrh_4", req); switch (sr_buf->status_type) { case FSF_STATUS_READ_PORT_CLOSED: @@ -915,7 +915,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_GOOD: - zfcp_dbf_san_res("fsscth1", req); + zfcp_dbf_san_res("fsscth2", req); ct->status = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: From 6698ed992a57761a1d3583e11e492da6ac3bbdc7 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:31 +0200 Subject: [PATCH 0097/1071] SCSI: zfcp: Bounds checking for deferred error trace commit 01e60527f0a49b3d7df603010bd6079bb4b6cf07 upstream. The pl vector has scount elements, i.e. pl[scount-1] is the last valid element. For maximum sized requests, payload->counter == scount after the last loop iteration. Therefore, do bounds checking first (with boolean shortcut) to not access the invalid element pl[scount]. Do not trust the maximum sbale->scount value from the HBA but ensure we won't access the pl vector out of our allocated bounds. While at it, clean up scoping and prevent unnecessary memset. Minor fix for 86a9668a8d29ea711613e1cb37efa68e7c4db564 "[SCSI] zfcp: support for hardware data router" Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_dbf.c | 2 +- drivers/s390/scsi/zfcp_qdio.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 3c1d22097ad0b6..c6e47d553ad907 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, length = min((u16)sizeof(struct qdio_buffer), (u16)ZFCP_DBF_PAY_MAX_REC); - while ((char *)pl[payload->counter] && payload->counter < scount) { + while (payload->counter < scount && (char *)pl[payload->counter]) { memcpy(payload->data, (char *)pl[payload->counter], length); debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); payload->counter++; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index b9fffc8d94a76d..50b5615848f6ed 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, { struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; struct zfcp_adapter *adapter = qdio->adapter; - struct qdio_buffer_element *sbale; int sbal_no, sbal_idx; - void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; - u64 req_id; - u8 scount; if (unlikely(qdio_err)) { - memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); if (zfcp_adapter_multi_buffer_active(adapter)) { + void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; + struct qdio_buffer_element *sbale; + u64 req_id; + u8 scount; + + memset(pl, 0, + ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); sbale = qdio->res_q[idx]->element; req_id = (u64) sbale->addr; - scount = sbale->scount + 1; /* incl. signaling SBAL */ + scount = min(sbale->scount + 1, + ZFCP_QDIO_MAX_SBALS_PER_REQ + 1); + /* incl. signaling SBAL */ for (sbal_no = 0; sbal_no < scount; sbal_no++) { sbal_idx = (idx + sbal_no) % From dd9ec1c64725b0b4deef5fd1bc1af11d624501d4 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:32 +0200 Subject: [PATCH 0098/1071] SCSI: zfcp: Do not wakeup while suspended commit cb45214960bc989af8b911ebd77da541c797717d upstream. If the mapping of FCP device bus ID and corresponding subchannel is modified while the Linux image is suspended, the resume of FCP devices can fail. During resume, zfcp gets callbacks from cio regarding the modified subchannels but they can be arbitrarily mixed with the restore/resume callback. Since the cio callbacks would trigger adapter recovery, zfcp could wakeup before the resume callback. Therefore, ignore the cio callbacks regarding subchannels while being suspended. We can safely do so, since zfcp does not deal itself with subchannels. For problem determination purposes, we still trace the ignored callback events. The following kernel messages could be seen on resume: kernel: : parent should not be sleeping As part of adapter reopen recovery, zfcp performs auto port scanning which can erroneously try to register new remote ports with scsi_transport_fc and the device core code complains about the parent (adapter) still sleeping. kernel: zfcp.3dff9c: :\ Setting up the QDIO connection to the FCP adapter failed kernel: zfcp.574d43: :\ ERP cannot recover an error on the FCP device In such cases, the adapter gave up recovery and remained blocked along with its child objects: remote ports and LUNs/scsi devices. Even the adapter shutdown as part of giving up recovery failed because the ccw device state remained disconnected. Later, the corresponding remote ports ran into dev_loss_tmo. As a result, the LUNs were erroneously not available again after resume. Even a manually triggered adapter recovery (e.g. sysfs attribute failed, or device offline/online via sysfs) could not recover the adapter due to the remaining disconnected state of the corresponding ccw device. Signed-off-by: Steffen Maier Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_ccw.c | 73 +++++++++++++++++++++++++++++++----- drivers/s390/scsi/zfcp_dbf.c | 20 ++++++++++ drivers/s390/scsi/zfcp_dbf.h | 1 + drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + 5 files changed, 86 insertions(+), 10 deletions(-) diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index e37f0455194890..9646766360d3d5 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -39,17 +39,23 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter) spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); } -static int zfcp_ccw_activate(struct ccw_device *cdev) - +/** + * zfcp_ccw_activate - activate adapter and wait for it to finish + * @cdev: pointer to belonging ccw device + * @clear: Status flags to clear. + * @tag: s390dbf trace record tag + */ +static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag) { struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return 0; + zfcp_erp_clear_adapter_status(adapter, clear); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ccresu2"); + tag); zfcp_erp_wait(adapter); flush_work(&adapter->scan_work); @@ -164,32 +170,47 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev) BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); adapter->req_no = 0; - zfcp_ccw_activate(cdev); + zfcp_ccw_activate(cdev, 0, "ccsonl1"); zfcp_ccw_adapter_put(adapter); return 0; } /** - * zfcp_ccw_set_offline - set_offline function of zfcp driver + * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish * @cdev: pointer to belonging ccw device + * @set: Status flags to set. + * @tag: s390dbf trace record tag * * This function gets called by the common i/o layer and sets an adapter * into state offline. */ -static int zfcp_ccw_set_offline(struct ccw_device *cdev) +static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag) { struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return 0; - zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); + zfcp_erp_set_adapter_status(adapter, set); + zfcp_erp_adapter_shutdown(adapter, 0, tag); zfcp_erp_wait(adapter); zfcp_ccw_adapter_put(adapter); return 0; } +/** + * zfcp_ccw_set_offline - set_offline function of zfcp driver + * @cdev: pointer to belonging ccw device + * + * This function gets called by the common i/o layer and sets an adapter + * into state offline. + */ +static int zfcp_ccw_set_offline(struct ccw_device *cdev) +{ + return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1"); +} + /** * zfcp_ccw_notify - ccw notify function * @cdev: pointer to belonging ccw device @@ -207,6 +228,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccnigo1", adapter); + break; + } dev_warn(&cdev->dev, "The FCP device has been detached\n"); zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); break; @@ -216,6 +242,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); break; case CIO_OPER: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccniop1", adapter); + break; + } dev_info(&cdev->dev, "The FCP device is operational again\n"); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); @@ -251,6 +282,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) zfcp_ccw_adapter_put(adapter); } +static int zfcp_ccw_suspend(struct ccw_device *cdev) +{ + zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1"); + return 0; +} + +static int zfcp_ccw_thaw(struct ccw_device *cdev) +{ + /* trace records for thaw and final shutdown during suspend + can only be found in system dump until the end of suspend + but not after resume because it's based on the memory image + right after the very first suspend (freeze) callback */ + zfcp_ccw_activate(cdev, 0, "ccthaw1"); + return 0; +} + +static int zfcp_ccw_resume(struct ccw_device *cdev) +{ + zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1"); + return 0; +} + struct ccw_driver zfcp_ccw_driver = { .driver = { .owner = THIS_MODULE, @@ -263,7 +316,7 @@ struct ccw_driver zfcp_ccw_driver = { .set_offline = zfcp_ccw_set_offline, .notify = zfcp_ccw_notify, .shutdown = zfcp_ccw_shutdown, - .freeze = zfcp_ccw_set_offline, - .thaw = zfcp_ccw_activate, - .restore = zfcp_ccw_activate, + .freeze = zfcp_ccw_suspend, + .thaw = zfcp_ccw_thaw, + .restore = zfcp_ccw_resume, }; diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index c6e47d553ad907..e1a8cc2526e79f 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -200,6 +200,26 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, spin_unlock_irqrestore(&dbf->pay_lock, flags); } +/** + * zfcp_dbf_hba_basic - trace event for basic adapter events + * @adapter: pointer to struct zfcp_adapter + */ +void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter) +{ + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_hba *rec = &dbf->hba_buf; + unsigned long flags; + + spin_lock_irqsave(&dbf->hba_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_HBA_BASIC; + + debug_event(dbf->hba, 1, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->hba_lock, flags); +} + static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, struct zfcp_adapter *adapter, struct zfcp_port *port, diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 714f087eb7a96b..3ac7a4b30dd910 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id { ZFCP_DBF_HBA_RES = 1, ZFCP_DBF_HBA_USS = 2, ZFCP_DBF_HBA_BIT = 3, + ZFCP_DBF_HBA_BASIC = 4, }; /** diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 2955e1a3deaf88..5bc4afba8b0976 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -77,6 +77,7 @@ struct zfcp_reqlist; #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 +#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 36f422770ff54d..4eeef78447f25f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -54,6 +54,7 @@ extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); +extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); From d27f15561fe521b44c0f784514cbd3e6c717bf36 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 4 Sep 2012 15:23:33 +0200 Subject: [PATCH 0099/1071] SCSI: zfcp: remove invalid reference to list iterator variable commit ca579c9f136af4274ccfd1bcaee7f38a29a0e2e9 upstream. If list_for_each_entry, etc complete a traversal of the list, the iterator variable ends up pointing to an address at an offset from the list head, and not a meaningful structure. Thus this value should not be used after the end of the iterator. Replace port->adapter->scsi_host by adapter->scsi_host. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Oversight in upsteam commit of v2.6.37 a1ca48319a9aa1c5b57ce142f538e76050bb8972 "[SCSI] zfcp: Move ACL/CFDC code to zfcp_cfdc.c" which merged the content of zfcp_erp_port_access_changed(). Signed-off-by: Julia Lawall Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_cfdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index fbd8b4db602577..49b82e46629ee4 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter) } read_unlock_irqrestore(&adapter->port_list_lock, flags); - shost_for_each_device(sdev, port->adapter->scsi_host) { + shost_for_each_device(sdev, adapter->scsi_host) { zfcp_sdev = sdev_to_zfcp(sdev); status = atomic_read(&zfcp_sdev->status); if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || From ce6673c6e35541a45622fcd53573c27994f406a3 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:34 +0200 Subject: [PATCH 0100/1071] SCSI: zfcp: restore refcount check on port_remove commit d99b601b63386f3395dc26a699ae703a273d9982 upstream. Upstream commit f3450c7b917201bb49d67032e9f60d5125675d6a "[SCSI] zfcp: Replace local reference counting with common kref" accidentally dropped a reference count check before tearing down zfcp_ports that are potentially in use by zfcp_units. Even remote ports in use can be removed causing unreachable garbage objects zfcp_ports with zfcp_units. Thus units won't come back even after a manual port_rescan. The kref of zfcp_port->dev.kobj is already used by the driver core. We cannot re-use it to track the number of zfcp_units. Re-introduce our own counter for units per port and check on port_remove. Signed-off-by: Steffen Maier Reviewed-by: Heiko Carstens Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_sysfs.c | 18 +++++++++++++++-- drivers/s390/scsi/zfcp_unit.c | 36 ++++++++++++++++++++++++---------- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index aff8621de8069b..f6adde44f226e1 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -519,6 +519,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, rwlock_init(&port->unit_list_lock); INIT_LIST_HEAD(&port->unit_list); + atomic_set(&port->units, 0); INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 5bc4afba8b0976..1305955cbf5978 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -205,6 +205,7 @@ struct zfcp_port { struct zfcp_adapter *adapter; /* adapter used to access port */ struct list_head unit_list; /* head of logical unit list */ rwlock_t unit_list_lock; /* unit list lock */ + atomic_t units; /* zfcp_unit count */ atomic_t status; /* status of this remote port */ u64 wwnn; /* WWNN if known */ u64 wwpn; /* WWPN */ diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 4eeef78447f25f..03441a7fb463c6 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -159,6 +159,7 @@ extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); extern struct attribute_group zfcp_sysfs_unit_attrs; extern struct attribute_group zfcp_sysfs_adapter_attrs; extern struct attribute_group zfcp_sysfs_port_attrs; +extern struct mutex zfcp_sysfs_port_units_mutex; extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; extern struct device_attribute *zfcp_sysfs_shost_attrs[]; diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index c66af27b230bb9..1e0eb089dfbafd 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, zfcp_sysfs_port_rescan_store); +DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); + static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, else retval = 0; + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) > 0) { + retval = -EBUSY; + mutex_unlock(&zfcp_sysfs_port_units_mutex); + goto out; + } + /* port is about to be removed, so no more unit_add */ + atomic_set(&port->units, -1); + mutex_unlock(&zfcp_sysfs_port_units_mutex); + write_lock_irq(&adapter->port_list_lock); list_del(&port->list); write_unlock_irq(&adapter->port_list_lock); @@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, { struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); u64 fcp_lun; + int retval; if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) return -EINVAL; - if (zfcp_unit_add(port, fcp_lun)) - return -EINVAL; + retval = zfcp_unit_add(port, fcp_lun); + if (retval) + return retval; return count; } diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 3f2bff0d3aa21f..1cd2b99ab256c0 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev) { struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); - put_device(&unit->port->dev); + atomic_dec(&unit->port->units); kfree(unit); } @@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev) int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) { struct zfcp_unit *unit; + int retval = 0; + + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) == -1) { + /* port is already gone */ + retval = -ENODEV; + goto out; + } unit = zfcp_unit_find(port, fcp_lun); if (unit) { put_device(&unit->dev); - return -EEXIST; + retval = -EEXIST; + goto out; } unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); - if (!unit) - return -ENOMEM; + if (!unit) { + retval = -ENOMEM; + goto out; + } unit->port = port; unit->fcp_lun = fcp_lun; @@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) if (dev_set_name(&unit->dev, "0x%016llx", (unsigned long long) fcp_lun)) { kfree(unit); - return -ENOMEM; + retval = -ENOMEM; + goto out; } - get_device(&port->dev); - if (device_register(&unit->dev)) { put_device(&unit->dev); - return -ENOMEM; + retval = -ENOMEM; + goto out; } if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { device_unregister(&unit->dev); - return -EINVAL; + retval = -EINVAL; + goto out; } + atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */ + write_lock_irq(&port->unit_list_lock); list_add_tail(&unit->list, &port->unit_list); write_unlock_irq(&port->unit_list_lock); zfcp_unit_scsi_scan(unit); - return 0; +out: + mutex_unlock(&zfcp_sysfs_port_units_mutex); + return retval; } /** From 5cc78bc58829a3cb08404821484744846cf06e66 Mon Sep 17 00:00:00 2001 From: Martin Peschke Date: Tue, 4 Sep 2012 15:23:36 +0200 Subject: [PATCH 0101/1071] SCSI: zfcp: only access zfcp_scsi_dev for valid scsi_device commit d436de8ce25f53a8a880a931886821f632247943 upstream. __scsi_remove_device (e.g. due to dev_loss_tmo) calls zfcp_scsi_slave_destroy which in turn sends a close LUN FSF request to the adapter. After 30 seconds without response, zfcp_erp_timeout_handler kicks the ERP thread failing the close LUN ERP action. zfcp_erp_wait in zfcp_erp_lun_shutdown_wait and thus zfcp_scsi_slave_destroy returns and then scsi_device is no longer valid. Sometime later the response to the close LUN FSF request may finally come in. However, commit b62a8d9b45b971a67a0f8413338c230e3117dff5 "[SCSI] zfcp: Use SCSI device data zfcp_scsi_dev instead of zfcp_unit" introduced a number of attempts to unconditionally access struct zfcp_scsi_dev through struct scsi_device causing a use-after-free. This leads to an Oops due to kernel page fault in one of: zfcp_fsf_abort_fcp_command_handler, zfcp_fsf_open_lun_handler, zfcp_fsf_close_lun_handler, zfcp_fsf_req_trace, zfcp_fsf_fcp_handler_common. Move dereferencing of zfcp private data zfcp_scsi_dev allocated in scsi_device via scsi_transport_reserve_device after the check for potentially aborted FSF request and thus no longer valid scsi_device. Only then assign sdev_to_zfcp(sdev) to the local auto variable struct zfcp_scsi_dev *zfcp_sdev. Signed-off-by: Martin Peschke Signed-off-by: Steffen Maier Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_fsf.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 6e2892e7c4be96..48f875f0c273fc 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -801,12 +801,14 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: if (fsq->word[0] == fsq->word[1]) { @@ -1769,13 +1771,15 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = &req->qtcb->header; struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_COMMON_ACCESS_BOXED | ZFCP_STATUS_LUN_SHARED | @@ -1886,11 +1890,13 @@ int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action) static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); @@ -1980,7 +1986,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) { struct fsf_qual_latency_info *lat_in; struct latency_cont *lat = NULL; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device); + struct zfcp_scsi_dev *zfcp_sdev; struct zfcp_blk_drv_data blktrc; int ticks = req->adapter->timer_ticks; @@ -1995,6 +2001,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA && !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { + zfcp_sdev = sdev_to_zfcp(scsi->device); blktrc.flags |= ZFCP_BLK_LAT_VALID; blktrc.channel_lat = lat_in->channel_lat * ticks; blktrc.fabric_lat = lat_in->fabric_lat * ticks; @@ -2032,12 +2039,14 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) { struct scsi_cmnd *scmnd = req->data; struct scsi_device *sdev = scmnd->device; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = &req->qtcb->header; if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: From 69c212a724fd353e05aeb8dff788a71f68a6b1d8 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 10 Sep 2012 17:19:33 -0700 Subject: [PATCH 0102/1071] PCI: Check P2P bridge for invalid secondary/subordinate range commit 1965f66e7db08d1ebccd24a59043eba826cc1ce8 upstream. For bridges with "secondary > subordinate", i.e., invalid bus number apertures, we don't enumerate anything behind the bridge unless the user specified "pci=assign-busses". This patch makes us automatically try to reassign the downstream bus numbers in this case (just for that bridge, not for all bridges as "pci=assign-busses" does). We don't discover all the devices on the Intel DP43BF motherboard without this change (or "pci=assign-busses") because its BIOS configures a bridge as: pci 0000:00:1e.0: PCI bridge to [bus 20-08] (subtractive decode) [bhelgaas: changelog, change message to dev_info] Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=18412 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=625754 Reported-by: Brian C. Huffman Reported-by: VL Tested-by: VL Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 9f8a6b79a8ecf2..61859d04cfea1c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -729,8 +729,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* Check if setup is sensible at all */ if (!pass && - (primary != bus->number || secondary <= bus->number)) { - dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); + (primary != bus->number || secondary <= bus->number || + secondary > subordinate)) { + dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n", + secondary, subordinate); broken = 1; } From 416a6881ec91623137652ab40e95870ee591e608 Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Wed, 5 Sep 2012 01:21:50 -0400 Subject: [PATCH 0103/1071] ext4: ignore last group w/o enough space when resizing instead of BUG'ing commit 03c1c29053f678234dbd51bf3d65f3b7529021de upstream. If the last group does not have enough space for group tables, ignore it instead of calling BUG_ON(). Reported-by: Daniel Drake Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 41f6ef68e2e1e8..28031c4e15e9c1 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -200,8 +200,11 @@ static void free_flex_gd(struct ext4_new_flex_group_data *flex_gd) * be a partial of a flex group. * * @sb: super block of fs to which the groups belongs + * + * Returns 0 on a successful allocation of the metadata blocks in the + * block group. */ -static void ext4_alloc_group_tables(struct super_block *sb, +static int ext4_alloc_group_tables(struct super_block *sb, struct ext4_new_flex_group_data *flex_gd, int flexbg_size) { @@ -226,6 +229,8 @@ static void ext4_alloc_group_tables(struct super_block *sb, (last_group & ~(flexbg_size - 1)))); next_group: group = group_data[0].group; + if (src_group >= group_data[0].group + flex_gd->count) + return -ENOSPC; start_blk = ext4_group_first_block_no(sb, src_group); last_blk = start_blk + group_data[src_group - group].blocks_count; @@ -235,7 +240,6 @@ static void ext4_alloc_group_tables(struct super_block *sb, start_blk += overhead; - BUG_ON(src_group >= group_data[0].group + flex_gd->count); /* We collect contiguous blocks as much as possible. */ src_group++; for (; src_group <= last_group; src_group++) @@ -300,6 +304,7 @@ static void ext4_alloc_group_tables(struct super_block *sb, group_data[i].free_blocks_count); } } + return 0; } static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, @@ -1729,7 +1734,8 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) */ while (ext4_setup_next_flex_gd(sb, flex_gd, n_blocks_count, flexbg_size)) { - ext4_alloc_group_tables(sb, flex_gd, flexbg_size); + if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0) + break; err = ext4_flex_group_add(sb, resize_inode, flex_gd); if (unlikely(err)) break; From 256ae46c73e0e989c390eaa31833881dd55d6b0c Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Wed, 5 Sep 2012 01:25:50 -0400 Subject: [PATCH 0104/1071] ext4: don't copy non-existent gdt blocks when resizing commit 6df935ad2fced9033ab52078825fcaf6365f34b7 upstream. The resize code was copying blocks at the beginning of each block group in order to copy the superblock and block group descriptor table (gdt) blocks. This was, unfortunately, being done even for block groups that did not have super blocks or gdt blocks. This is a complete waste of perfectly good I/O bandwidth, to skip writing those blocks for sparse bg's. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 28031c4e15e9c1..1afd3e735459ab 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -456,6 +456,9 @@ static int setup_new_flex_group_blocks(struct super_block *sb, gdblocks = ext4_bg_num_gdb(sb, group); start = ext4_group_first_block_no(sb, group); + if (!ext4_bg_has_super(sb, group)) + goto handle_itb; + /* Copy all of the GDT blocks into the backup in this group */ for (j = 0, block = start + 1; j < gdblocks; j++, block++) { struct buffer_head *gdb; @@ -498,6 +501,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb, goto out; } +handle_itb: /* Initialize group tables of the grop @group */ if (!(bg_flags[i] & EXT4_BG_INODE_ZEROED)) goto handle_bb; From 5018ddd6809e3ca755087da51c9808f9535d46f0 Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Wed, 5 Sep 2012 01:27:50 -0400 Subject: [PATCH 0105/1071] ext4: avoid duplicate writes of the backup bg descriptor blocks commit 2ebd1704ded88a8ae29b5f3998b13959c715c4be upstream. The resize code was needlessly writing the backup block group descriptor blocks multiple times (once per block group) during an online resize. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 1afd3e735459ab..0be1789ebc3ba7 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1358,13 +1358,15 @@ static int ext4_flex_group_add(struct super_block *sb, err = err2; if (!err) { - int i; + int gdb_num = group / EXT4_DESC_PER_BLOCK(sb); + int gdb_num_end = ((group + flex_gd->count - 1) / + EXT4_DESC_PER_BLOCK(sb)); + update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, sizeof(struct ext4_super_block)); - for (i = 0; i < flex_gd->count; i++, group++) { + for (; gdb_num <= gdb_num_end; gdb_num++) { struct buffer_head *gdb_bh; - int gdb_num; - gdb_num = group / EXT4_BLOCKS_PER_GROUP(sb); + gdb_bh = sbi->s_group_desc[gdb_num]; update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data, gdb_bh->b_size); From 1638f1fb5b54c51f09769cb8938798d4122225d4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 19 Sep 2012 22:42:36 -0400 Subject: [PATCH 0106/1071] ext4: fix potential deadlock in ext4_nonda_switch() commit 00d4e7362ed01987183e9528295de3213031309c upstream. In ext4_nonda_switch(), if the file system is getting full we used to call writeback_inodes_sb_if_idle(). The problem is that we can be holding i_mutex already, and this causes a potential deadlock when writeback_inodes_sb_if_idle() when it tries to take s_umount. (See lockdep output below). As it turns out we don't need need to hold s_umount; the fact that we are in the middle of the write(2) system call will keep the superblock pinned. Unfortunately writeback_inodes_sb() checks to make sure s_umount is taken, and the VFS uses a different mechanism for making sure the file system doesn't get unmounted out from under us. The simplest way of dealing with this is to just simply grab s_umount using a trylock, and skip kicking the writeback flusher thread in the very unlikely case that we can't take a read lock on s_umount without blocking. Also, we now check the cirteria for kicking the writeback thread before we decide to whether to fall back to non-delayed writeback, so if there are any outstanding delayed allocation writes, we try to get them resolved as soon as possible. [ INFO: possible circular locking dependency detected ] 3.6.0-rc1-00042-gce894ca #367 Not tainted ------------------------------------------------------- dd/8298 is trying to acquire lock: (&type->s_umount_key#18){++++..}, at: [] writeback_inodes_sb_if_idle+0x28/0x46 but task is already holding lock: (&sb->s_type->i_mutex_key#8){+.+...}, at: [] generic_file_aio_write+0x5f/0xd3 which lock already depends on the new lock. 2 locks held by dd/8298: #0: (sb_writers#2){.+.+.+}, at: [] generic_file_aio_write+0x56/0xd3 #1: (&sb->s_type->i_mutex_key#8){+.+...}, at: [] generic_file_aio_write+0x5f/0xd3 stack backtrace: Pid: 8298, comm: dd Not tainted 3.6.0-rc1-00042-gce894ca #367 Call Trace: [] ? console_unlock+0x345/0x372 [] print_circular_bug+0x190/0x19d [] __lock_acquire+0x86d/0xb6c [] ? mark_held_locks+0x5c/0x7b [] lock_acquire+0x66/0xb9 [] ? writeback_inodes_sb_if_idle+0x28/0x46 [] down_read+0x28/0x58 [] ? writeback_inodes_sb_if_idle+0x28/0x46 [] writeback_inodes_sb_if_idle+0x28/0x46 [] ext4_nonda_switch+0xe1/0xf4 [] ext4_da_write_begin+0x27/0x193 [] generic_file_buffered_write+0xc8/0x1bb [] __generic_file_aio_write+0x1dd/0x205 [] generic_file_aio_write+0x78/0xd3 [] ext4_file_write+0x480/0x4a6 [] ? __lock_acquire+0x41e/0xb6c [] ? sched_clock_cpu+0x11a/0x13e [] ? trace_hardirqs_off+0xb/0xd [] ? local_clock+0x37/0x4e [] do_sync_write+0x67/0x9d [] ? wait_on_retry_sync_kiocb+0x44/0x44 [] vfs_write+0x7b/0xe6 [] sys_write+0x3b/0x64 [] syscall_call+0x7/0xb Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 17 ++++++++++------- fs/fs-writeback.c | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index dff171c3a1234e..d0855c2a9c22a3 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2463,6 +2463,16 @@ static int ext4_nonda_switch(struct super_block *sb) free_blocks = EXT4_C2B(sbi, percpu_counter_read_positive(&sbi->s_freeclusters_counter)); dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter); + /* + * Start pushing delalloc when 1/2 of free blocks are dirty. + */ + if (dirty_blocks && (free_blocks < 2 * dirty_blocks) && + !writeback_in_progress(sb->s_bdi) && + down_read_trylock(&sb->s_umount)) { + writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); + up_read(&sb->s_umount); + } + if (2 * free_blocks < 3 * dirty_blocks || free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { /* @@ -2471,13 +2481,6 @@ static int ext4_nonda_switch(struct super_block *sb) */ return 1; } - /* - * Even if we don't switch but are nearing capacity, - * start pushing delalloc when 1/2 of free blocks are dirty. - */ - if (free_blocks < 2 * dirty_blocks) - writeback_inodes_sb_if_idle(sb, WB_REASON_FS_FREE_SPACE); - return 0; } diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index be3efc4f64f4b8..5602d73d4ec7a5 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -63,6 +63,7 @@ int writeback_in_progress(struct backing_dev_info *bdi) { return test_bit(BDI_writeback_running, &bdi->state); } +EXPORT_SYMBOL(writeback_in_progress); static inline struct backing_dev_info *inode_to_bdi(struct inode *inode) { From 2fdb1128f404ab026d2794de3bd604500edd444b Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Sun, 23 Sep 2012 22:49:12 -0400 Subject: [PATCH 0107/1071] ext4: fix crash when accessing /proc/mounts concurrently commit 50df9fd55e4271e89a7adf3b1172083dd0ca199d upstream. The crash was caused by a variable being erronously declared static in token2str(). In addition to /proc/mounts, the problem can also be easily replicated by accessing /proc/fs/ext4//options in parallel: $ cat /proc/fs/ext4//options > options.txt ... and then running the following command in two different terminals: $ while diff /proc/fs/ext4//options options.txt; do true; done This is also the cause of the following a crash while running xfstests #234, as reported in the following bug reports: https://bugs.launchpad.net/bugs/1053019 https://bugzilla.kernel.org/show_bug.cgi?id=47731 Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: "Theodore Ts'o" Cc: Brad Figg Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index c6e0cb3d1f4a9e..e44b23362088d9 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1735,7 +1735,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq, static const char *token2str(int token) { - static const struct match_token *t; + const struct match_token *t; for (t = tokens; t->token != Opt_err; t++) if (t->token == token && !strchr(t->pattern, '=')) From ba57d9ef068e6f55226bfedf0e7cd6adab37a316 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 26 Sep 2012 12:32:19 -0400 Subject: [PATCH 0108/1071] ext4: move_extent code cleanup commit 03bd8b9b896c8e940f282f540e6b4de90d666b7c upstream. - Remove usless checks, because it is too late to check that inode != NULL at the moment it was referenced several times. - Double lock routines looks very ugly and locking ordering relays on order of i_ino, but other kernel code rely on order of pointers. Let's make them simple and clean. - check that inodes belongs to the same SB as soon as possible. Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 167 ++++++++++++------------------------------ 1 file changed, 47 insertions(+), 120 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index c5826c623e7af8..df5cde5130c516 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -140,56 +140,22 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path, return 1; } -/** - * mext_check_null_inode - NULL check for two inodes - * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. - */ -static int -mext_check_null_inode(struct inode *inode1, struct inode *inode2, - const char *function, unsigned int line) -{ - int ret = 0; - - if (inode1 == NULL) { - __ext4_error(inode2->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 NULL inode2 %lu", inode2->i_ino); - ret = -EIO; - } else if (inode2 == NULL) { - __ext4_error(inode1->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 %lu inode2 NULL", inode1->i_ino); - ret = -EIO; - } - return ret; -} - /** * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem * - * @orig_inode: original inode structure - * @donor_inode: donor inode structure - * Acquire write lock of i_data_sem of the two inodes (orig and donor) by - * i_ino order. + * Acquire write lock of i_data_sem of the two inodes */ static void -double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) +double_down_write_data_sem(struct inode *first, struct inode *second) { - struct inode *first = orig_inode, *second = donor_inode; + if (first < second) { + down_write(&EXT4_I(first)->i_data_sem); + down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); + } else { + down_write(&EXT4_I(second)->i_data_sem); + down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING); - /* - * Use the inode number to provide the stable locking order instead - * of its address, because the C language doesn't guarantee you can - * compare pointers that don't come from the same array. - */ - if (donor_inode->i_ino < orig_inode->i_ino) { - first = donor_inode; - second = orig_inode; } - - down_write(&EXT4_I(first)->i_data_sem); - down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); } /** @@ -969,14 +935,6 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } - /* Files should be in the same ext4 FS */ - if (orig_inode->i_sb != donor_inode->i_sb) { - ext4_debug("ext4 move extent: The argument files " - "should be in same FS [ino:orig %lu, donor %lu]\n", - orig_inode->i_ino, donor_inode->i_ino); - return -EINVAL; - } - /* Ext4 move extent supports only extent based file */ if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) { ext4_debug("ext4 move extent: orig file is not extents " @@ -1072,35 +1030,19 @@ mext_check_arguments(struct inode *orig_inode, * @inode1: the inode structure * @inode2: the inode structure * - * Lock two inodes' i_mutex by i_ino order. - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. + * Lock two inodes' i_mutex */ -static int +static void mext_inode_double_lock(struct inode *inode1, struct inode *inode2) { - int ret = 0; - - BUG_ON(inode1 == NULL && inode2 == NULL); - - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1 == inode2) { - mutex_lock(&inode1->i_mutex); - goto out; - } - - if (inode1->i_ino < inode2->i_ino) { + BUG_ON(inode1 == inode2); + if (inode1 < inode2) { mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); } else { mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); } - -out: - return ret; } /** @@ -1109,28 +1051,13 @@ mext_inode_double_lock(struct inode *inode1, struct inode *inode2) * @inode1: the inode that is released first * @inode2: the inode that is released second * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. */ -static int +static void mext_inode_double_unlock(struct inode *inode1, struct inode *inode2) { - int ret = 0; - - BUG_ON(inode1 == NULL && inode2 == NULL); - - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1) - mutex_unlock(&inode1->i_mutex); - - if (inode2 && inode2 != inode1) - mutex_unlock(&inode2->i_mutex); - -out: - return ret; + mutex_unlock(&inode1->i_mutex); + mutex_unlock(&inode2->i_mutex); } /** @@ -1187,16 +1114,23 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, ext4_lblk_t block_end, seq_start, add_blocks, file_end, seq_blocks = 0; ext4_lblk_t rest_blocks; pgoff_t orig_page_offset = 0, seq_end_page; - int ret1, ret2, depth, last_extent = 0; + int ret, depth, last_extent = 0; int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; int data_offset_in_page; int block_len_in_page; int uninit; - /* orig and donor should be different file */ - if (orig_inode->i_ino == donor_inode->i_ino) { + if (orig_inode->i_sb != donor_inode->i_sb) { + ext4_debug("ext4 move extent: The argument files " + "should be in same FS [ino:orig %lu, donor %lu]\n", + orig_inode->i_ino, donor_inode->i_ino); + return -EINVAL; + } + + /* orig and donor should be different inodes */ + if (orig_inode == donor_inode) { ext4_debug("ext4 move extent: The argument files should not " - "be same file [ino:orig %lu, donor %lu]\n", + "be same inode [ino:orig %lu, donor %lu]\n", orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } @@ -1210,16 +1144,14 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, } /* Protect orig and donor inodes against a truncate */ - ret1 = mext_inode_double_lock(orig_inode, donor_inode); - if (ret1 < 0) - return ret1; + mext_inode_double_lock(orig_inode, donor_inode); /* Protect extent tree against block allocations via delalloc */ double_down_write_data_sem(orig_inode, donor_inode); /* Check the filesystem environment whether move_extent can be done */ - ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start, + ret = mext_check_arguments(orig_inode, donor_inode, orig_start, donor_start, &len); - if (ret1) + if (ret) goto out; file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits; @@ -1227,13 +1159,13 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, if (file_end < block_end) len -= block_end - file_end; - ret1 = get_ext_path(orig_inode, block_start, &orig_path); - if (ret1) + ret = get_ext_path(orig_inode, block_start, &orig_path); + if (ret) goto out; /* Get path structure to check the hole */ - ret1 = get_ext_path(orig_inode, block_start, &holecheck_path); - if (ret1) + ret = get_ext_path(orig_inode, block_start, &holecheck_path); + if (ret) goto out; depth = ext_depth(orig_inode); @@ -1252,13 +1184,13 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, last_extent = mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; goto out; } last_extent = mext_next_extent(orig_inode, orig_path, &ext_dummy); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; goto out; } seq_start = le32_to_cpu(ext_cur->ee_block); @@ -1272,7 +1204,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, if (le32_to_cpu(ext_cur->ee_block) > block_end) { ext4_debug("ext4 move extent: The specified range of file " "may be the hole\n"); - ret1 = -EINVAL; + ret = -EINVAL; goto out; } @@ -1292,7 +1224,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, last_extent = mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; break; } add_blocks = ext4_ext_get_actual_len(ext_cur); @@ -1349,18 +1281,18 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, orig_page_offset, data_offset_in_page, block_len_in_page, uninit, - &ret1); + &ret); /* Count how many blocks we have exchanged */ *moved_len += block_len_in_page; - if (ret1 < 0) + if (ret < 0) break; if (*moved_len > len) { EXT4_ERROR_INODE(orig_inode, "We replaced blocks too much! " "sum of replaced: %llu requested: %llu", *moved_len, len); - ret1 = -EIO; + ret = -EIO; break; } @@ -1374,22 +1306,22 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, } double_down_write_data_sem(orig_inode, donor_inode); - if (ret1 < 0) + if (ret < 0) break; /* Decrease buffer counter */ if (holecheck_path) ext4_ext_drop_refs(holecheck_path); - ret1 = get_ext_path(orig_inode, seq_start, &holecheck_path); - if (ret1) + ret = get_ext_path(orig_inode, seq_start, &holecheck_path); + if (ret) break; depth = holecheck_path->p_depth; /* Decrease buffer counter */ if (orig_path) ext4_ext_drop_refs(orig_path); - ret1 = get_ext_path(orig_inode, seq_start, &orig_path); - if (ret1) + ret = get_ext_path(orig_inode, seq_start, &orig_path); + if (ret) break; ext_cur = holecheck_path[depth].p_ext; @@ -1412,12 +1344,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, kfree(holecheck_path); } double_up_write_data_sem(orig_inode, donor_inode); - ret2 = mext_inode_double_unlock(orig_inode, donor_inode); + mext_inode_double_unlock(orig_inode, donor_inode); - if (ret1) - return ret1; - else if (ret2) - return ret2; - - return 0; + return ret; } From 22a5672604ff3eef101c83436ee15d8e2e148187 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 26 Sep 2012 12:32:54 -0400 Subject: [PATCH 0109/1071] ext4: online defrag is not supported for journaled files commit f066055a3449f0e5b0ae4f3ceab4445bead47638 upstream. Proper block swap for inodes with full journaling enabled is truly non obvious task. In order to be on a safe side let's explicitly disable it for now. Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index df5cde5130c516..e2016f34b58f35 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -1142,7 +1142,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } - + /* TODO: This is non obvious task to swap blocks for inodes with full + jornaling enabled */ + if (ext4_should_journal_data(orig_inode) || + ext4_should_journal_data(donor_inode)) { + return -EINVAL; + } /* Protect orig and donor inodes against a truncate */ mext_inode_double_lock(orig_inode, donor_inode); From 12ebdf00d08f21da12c85e1800d5d91beaa4bfbe Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Wed, 26 Sep 2012 21:24:57 -0400 Subject: [PATCH 0110/1071] ext4: always set i_op in ext4_mknod() commit 6a08f447facb4f9e29fcc30fb68060bb5a0d21c2 upstream. ext4_special_inode_operations have their own ifdef CONFIG_EXT4_FS_XATTR to mask those methods. And ext4_iget also always sets it, so there is an inconsistency. Signed-off-by: Bernd Schubert Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/namei.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 2a42cc04466f68..d13873d7cfc1c5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2149,9 +2149,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry, err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); -#ifdef CONFIG_EXT4_FS_XATTR inode->i_op = &ext4_special_inode_operations; -#endif err = ext4_add_nondir(handle, dentry, inode); } ext4_journal_stop(handle); From 34414b2bf58b95110bf8ccef77d66c05de9e923c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 26 Sep 2012 21:52:20 -0400 Subject: [PATCH 0111/1071] ext4: fix fdatasync() for files with only i_size changes commit b71fc079b5d8f42b2a52743c8d2f1d35d655b1c5 upstream. Code tracking when transaction needs to be committed on fdatasync(2) forgets to handle a situation when only inode's i_size is changed. Thus in such situations fdatasync(2) doesn't force transaction with new i_size to disk and that can result in wrong i_size after a crash. Fix the issue by updating inode's i_datasync_tid whenever its size is updated. Reported-by: Kristian Nielsen Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d0855c2a9c22a3..475c211be3e08a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4055,6 +4055,7 @@ static int ext4_do_update_inode(handle_t *handle, struct ext4_inode_info *ei = EXT4_I(inode); struct buffer_head *bh = iloc->bh; int err = 0, rc, block; + int need_datasync = 0; uid_t i_uid; gid_t i_gid; @@ -4105,7 +4106,10 @@ static int ext4_do_update_inode(handle_t *handle, raw_inode->i_file_acl_high = cpu_to_le16(ei->i_file_acl >> 32); raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl); - ext4_isize_set(raw_inode, ei->i_disksize); + if (ei->i_disksize != ext4_isize(raw_inode)) { + ext4_isize_set(raw_inode, ei->i_disksize); + need_datasync = 1; + } if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, @@ -4158,7 +4162,7 @@ static int ext4_do_update_inode(handle_t *handle, err = rc; ext4_clear_inode_state(inode, EXT4_STATE_NEW); - ext4_update_inode_fsync_trans(handle, inode, 0); + ext4_update_inode_fsync_trans(handle, inode, need_datasync); out_brelse: brelse(bh); ext4_std_error(inode->i_sb, err); From 92b77229ee73413c1ebfe793ed0085eb1ff794f1 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 30 Sep 2012 23:04:56 -0400 Subject: [PATCH 0112/1071] ext4: fix mtime update in nodelalloc mode commit 041bbb6d369811e948ae01f3d00414264076be35 upstream. Commits 5e8830dc85d0 and 41c4d25f78c0 introduced a regression into v3.6-rc1 for ext4 in nodealloc mode, such that mtime updates would not take place for files modified via mmap if the page was already in the page cache. This would also affect ext3 file systems mounted using the ext4 file system driver. The problem was that ext4_page_mkwrite() had a shortcut which would avoid calling __block_page_mkwrite() under some circumstances, and the above two commit transferred the responsibility of calling file_update_time() to __block_page_mkwrite --- which woudln't get called in some circumstances. Since __block_page_mkwrite() only has three callers, block_page_mkwrite(), ext4_page_mkwrite, and nilfs_page_mkwrite(), the best way to solve this is to move the responsibility for calling file_update_time() to its caller. This problem was found via xfstests #215 with a file system mounted with -o nodelalloc. Signed-off-by: "Theodore Ts'o" Reviewed-by: Jan Kara Cc: KONISHI Ryusuke Signed-off-by: Greg Kroah-Hartman --- fs/buffer.c | 13 +++++++------ fs/ext4/inode.c | 1 + fs/nilfs2/file.c | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 58e2e7b7737264..b5f044283edb53 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2312,12 +2312,6 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, loff_t size; int ret; - /* - * Update file times before taking page lock. We may end up failing the - * fault so this update may be superfluous but who really cares... - */ - file_update_time(vma->vm_file); - lock_page(page); size = i_size_read(inode); if ((page->mapping != inode->i_mapping) || @@ -2355,6 +2349,13 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb; sb_start_pagefault(sb); + + /* + * Update file times before taking page lock. We may end up failing the + * fault so this update may be superfluous but who really cares... + */ + file_update_time(vma->vm_file); + ret = __block_page_mkwrite(vma, vmf, get_block); sb_end_pagefault(sb); return block_page_mkwrite_return(ret); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 475c211be3e08a..2ce16af1bdbd68 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4787,6 +4787,7 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) int retries = 0; sb_start_pagefault(inode->i_sb); + file_update_time(vma->vm_file); /* Delalloc case is easy... */ if (test_opt(inode->i_sb, DELALLOC) && !ext4_should_journal_data(inode) && diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index a4d56ac02e6cf0..5b387a4c293e42 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -116,6 +116,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (unlikely(ret)) goto out; + file_update_time(vma->vm_file); ret = __block_page_mkwrite(vma, vmf, nilfs_get_block); if (ret) { nilfs_transaction_abort(inode->i_sb); From de153756f0f684a1f2dd660c58a873da2e6cfdd3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 27 Sep 2012 18:35:24 +0100 Subject: [PATCH 0113/1071] ASoC: wm_hubs: Ensure volume updates are handled during class W startup commit eb4d5fc1f0ce89e3d5b072c594a1e213a0e05881 upstream. In some circumstances we may need to flush volume updates to the device after switching to class W mode. Do this unconditionally to ensure that these situations are handled. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm_hubs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 61baa48823cba2..57b27efb54946d 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -634,6 +634,11 @@ void wm_hubs_update_class_w(struct snd_soc_codec *codec) snd_soc_update_bits(codec, WM8993_CLASS_W_0, WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); + + snd_soc_write(codec, WM8993_LEFT_OUTPUT_VOLUME, + snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME)); + snd_soc_write(codec, WM8993_RIGHT_OUTPUT_VOLUME, + snd_soc_read(codec, WM8993_RIGHT_OUTPUT_VOLUME)); } EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); From b84a59a1b43cce7d8efc3cbcdb4a21ac8b184536 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 27 Sep 2012 13:21:48 +0100 Subject: [PATCH 0114/1071] ASoC: wm5110: Adding missing volume update bits commit ae60503741991a36ed6b2a8f53b249b2a72af52b upstream. The volume update bits were being set on all but one input and one output. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm5110.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 01ebbcc5c6a4a5..11dfc339048aea 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -869,6 +869,8 @@ static unsigned int wm5110_digital_vu[] = { ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_ADC_DIGITAL_VOLUME_3L, ARIZONA_ADC_DIGITAL_VOLUME_3R, + ARIZONA_ADC_DIGITAL_VOLUME_4L, + ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_DAC_DIGITAL_VOLUME_1L, ARIZONA_DAC_DIGITAL_VOLUME_1R, @@ -880,6 +882,8 @@ static unsigned int wm5110_digital_vu[] = { ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_DAC_DIGITAL_VOLUME_5L, ARIZONA_DAC_DIGITAL_VOLUME_5R, + ARIZONA_DAC_DIGITAL_VOLUME_6L, + ARIZONA_DAC_DIGITAL_VOLUME_6R, }; static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { From 7c6e1b2ebc9ed6ec255fa06a1320e21fb0075bf6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:37:29 +0100 Subject: [PATCH 0115/1071] ASoC: wm9712: Fix name of Capture Switch commit 689185b78ba6fbe0042f662a468b5565909dff7a upstream. Help UIs associate it with the matching gain control. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm9712.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c6d2076a796bd9..c9516f0c7a9555 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -146,7 +146,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), -SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), +SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), From ac8d33294e016f2003f8bf8caa848ba754a1d08c Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Mon, 8 Oct 2012 16:33:47 -0700 Subject: [PATCH 0116/1071] kpageflags: fix wrong KPF_THP on non-huge compound pages commit 7a71932d5676b7410ab64d149bad8bde6b0d8632 upstream. KPF_THP can be set on non-huge compound pages (like slab pages or pages allocated by drivers with __GFP_COMP) because PageTransCompound only checks PG_head and PG_tail. Obviously this is a bug and breaks user space applications which look for thp via /proc/kpageflags. This patch rules out setting KPF_THP wrongly by additionally checking PageLRU on the head pages. Signed-off-by: Naoya Horiguchi Acked-by: KOSAKI Motohiro Acked-by: David Rientjes Reviewed-by: Fengguang Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/page.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/proc/page.c b/fs/proc/page.c index 7fcd0d60a9680a..b8730d9ebaee65 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c @@ -115,7 +115,13 @@ u64 stable_page_flags(struct page *page) u |= 1 << KPF_COMPOUND_TAIL; if (PageHuge(page)) u |= 1 << KPF_HUGE; - else if (PageTransCompound(page)) + /* + * PageTransCompound can be true for non-huge compound pages (slab + * pages or pages allocated by drivers with __GFP_COMP) because it + * just checks PG_head/PG_tail, so we need to check PageLRU to make + * sure a given page is a thp, not a non-huge compound page. + */ + else if (PageTransCompound(page) && PageLRU(compound_trans_head(page))) u |= 1 << KPF_THP; /* From f037cf000f6b77ceba478a7467d3f80d1f571ad8 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Mon, 8 Oct 2012 16:33:31 -0700 Subject: [PATCH 0117/1071] hugetlb: do not use vma_hugecache_offset() for vma_prio_tree_foreach commit 36e4f20af833d1ce196e6a4ade05dc26c44652d1 upstream. Commit 0c176d52b0b2 ("mm: hugetlb: fix pgoff computation when unmapping page from vma") fixed pgoff calculation but it has replaced it by vma_hugecache_offset() which is not approapriate for offsets used for vma_prio_tree_foreach() because that one expects index in page units rather than in huge_page_shift. Johannes said: : The resulting index may not be too big, but it can be too small: assume : hpage size of 2M and the address to unmap to be 0x200000. This is regular : page index 512 and hpage index 1. If you have a VMA that maps the file : only starting at the second huge page, that VMAs vm_pgoff will be 512 but : you ask for offset 1 and miss it even though it does map the page of : interest. hugetlb_cow() will try to unmap, miss the vma, and retry the : cow until the allocation succeeds or the skipped vma(s) go away. Signed-off-by: Michal Hocko Acked-by: Hillf Danton Cc: Mel Gorman Cc: KAMEZAWA Hiroyuki Cc: Andrea Arcangeli Cc: David Rientjes Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index bc727122dd44de..3adceaf7523d65 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2481,7 +2481,8 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, * from page cache lookup which is in HPAGE_SIZE units. */ address = address & huge_page_mask(h); - pgoff = vma_hugecache_offset(h, vma, address); + pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff; mapping = vma->vm_file->f_dentry->d_inode->i_mapping; /* From 3445cb2e52e98dd2413bdc6bcccab475d3871dc1 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 8 Oct 2012 16:33:14 -0700 Subject: [PATCH 0118/1071] mm: fix invalidate_complete_page2() lock ordering commit ec4d9f626d5908b6052c2973f37992f1db52e967 upstream. In fuzzing with trinity, lockdep protested "possible irq lock inversion dependency detected" when isolate_lru_page() reenabled interrupts while still holding the supposedly irq-safe tree_lock: invalidate_inode_pages2 invalidate_complete_page2 spin_lock_irq(&mapping->tree_lock) clear_page_mlock isolate_lru_page spin_unlock_irq(&zone->lru_lock) isolate_lru_page() is correct to enable interrupts unconditionally: invalidate_complete_page2() is incorrect to call clear_page_mlock() while holding tree_lock, which is supposed to nest inside lru_lock. Both truncate_complete_page() and invalidate_complete_page() call clear_page_mlock() before taking tree_lock to remove page from radix_tree. I guess invalidate_complete_page2() preferred to test PageDirty (again) under tree_lock before committing to the munlock; but since the page has already been unmapped, its state is already somewhat inconsistent, and no worse if clear_page_mlock() moved up. Reported-by: Sasha Levin Deciphered-by: Andrew Morton Signed-off-by: Hugh Dickins Acked-by: Mel Gorman Cc: Rik van Riel Cc: Johannes Weiner Cc: Michel Lespinasse Cc: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/truncate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/truncate.c b/mm/truncate.c index 75801acdaac774..f38055cb8af6df 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -394,11 +394,12 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page) if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL)) return 0; + clear_page_mlock(page); + spin_lock_irq(&mapping->tree_lock); if (PageDirty(page)) goto failed; - clear_page_mlock(page); BUG_ON(page_has_private(page)); __delete_from_page_cache(page); spin_unlock_irq(&mapping->tree_lock); From a6d26c56e266a7b72dc48833f0429b4e0479f8cd Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Mon, 8 Oct 2012 16:33:27 -0700 Subject: [PATCH 0119/1071] mm: thp: fix pmd_present for split_huge_page and PROT_NONE with THP commit 027ef6c87853b0a9df53175063028edb4950d476 upstream. In many places !pmd_present has been converted to pmd_none. For pmds that's equivalent and pmd_none is quicker so using pmd_none is better. However (unless we delete pmd_present) we should provide an accurate pmd_present too. This will avoid the risk of code thinking the pmd is non present because it's under __split_huge_page_map, see the pmd_mknotpresent there and the comment above it. If the page has been mprotected as PROT_NONE, it would also lead to a pmd_present false negative in the same way as the race with split_huge_page. Because the PSE bit stays on at all times (both during split_huge_page and when the _PAGE_PROTNONE bit get set), we could only check for the PSE bit, but checking the PROTNONE bit too is still good to remember pmd_present must always keep PROT_NONE into account. This explains a not reproducible BUG_ON that was seldom reported on the lists. The same issue is in pmd_large, it would go wrong with both PROT_NONE and if it races with split_huge_page. Signed-off-by: Andrea Arcangeli Acked-by: Rik van Riel Cc: Johannes Weiner Cc: Hugh Dickins Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/pgtable.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 49afb3f41eb622..c3520d76820e21 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -146,8 +146,7 @@ static inline unsigned long pmd_pfn(pmd_t pmd) static inline int pmd_large(pmd_t pte) { - return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == - (_PAGE_PSE | _PAGE_PRESENT); + return pmd_flags(pte) & _PAGE_PSE; } #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -415,7 +414,13 @@ static inline int pte_hidden(pte_t pte) static inline int pmd_present(pmd_t pmd) { - return pmd_flags(pmd) & _PAGE_PRESENT; + /* + * Checking for _PAGE_PSE is needed too because + * split_huge_page will temporarily clear the present bit (but + * the _PAGE_PSE flag will remain set at all times while the + * _PAGE_PRESENT bit is clear). + */ + return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE); } static inline int pmd_none(pmd_t pmd) From c2bb4485c33a281d9b58e20c811dfe5711ef9f62 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 1 Sep 2012 18:46:00 +0200 Subject: [PATCH 0120/1071] MIPS: ath79: use correct fractional dividers for {CPU,DDR}_PLL on AR934x commit 65fc7f9957c52ad4fdf4ee5dfe3a75aa0a633d39 upstream. The current dividers in the code are wrong and this leads to broken CPU frequency calculation on boards where the fractional part is used. For example, if the SoC is running from a 40MHz reference clock, refdiv=1, nint=14, outdiv=0 and nfrac=31 the real frequency is 579.375MHz but the current code calculates 569.687MHz instead. Because the system time is indirectly related to the CPU frequency the broken computation causes drift in the system time. The correct divider is 2^6 for the CPU PLL and 2^10 for the DDR PLL. Use the correct values to fix the issue. Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4305/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/ath79/clock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index b91ad3efe29e81..d2728573e9fc78 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -189,7 +189,7 @@ static void __init ar934x_clocks_init(void) AR934X_PLL_CPU_CONFIG_NFRAC_MASK; cpu_pll = nint * ath79_ref_clk.rate / ref_div; - cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 6)); + cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); cpu_pll /= (1 << out_div); pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); @@ -203,7 +203,7 @@ static void __init ar934x_clocks_init(void) AR934X_PLL_DDR_CONFIG_NFRAC_MASK; ddr_pll = nint * ath79_ref_clk.rate / ref_div; - ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 10)); + ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); ddr_pll /= (1 << out_div); clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); From b80c1b7eabd8a93278c36d4692c6d83e74e4bf3e Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Mon, 18 Jun 2012 19:03:38 -0300 Subject: [PATCH 0121/1071] drm/i915: prevent possible pin leak on error path commit ab3951eb74e7c33a2f5b7b64d72e82f1eea61571 upstream. We should not hit this under any sane conditions, but still, this does not looks right. Reported-by: Herton Ronaldo Krzesinski CC: Chris Wilson CC: Daniel Vetter Reviewed-by: Chris Wlison Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c040aee1341cf2..df5570d67f890b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6394,7 +6394,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, default: WARN_ONCE(1, "unknown plane in flip command\n"); ret = -ENODEV; - goto err; + goto err_unpin; } ret = intel_ring_begin(ring, 4); From 3e595be0b92b3a9db691013b00847b5d269d92a7 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 25 Sep 2012 13:23:34 -0300 Subject: [PATCH 0122/1071] drm/i915: make sure we write all the DIP data bytes commit adf00b26d18e1b3570451296e03bcb20e4798cdd upstream. ... even if the actual infoframe is smaller than the maximum possible size. If we don't write all the 32 DIP data bytes the InfoFrame ECC may not be correctly calculated in some cases (e.g., when changing the port), and this will lead to black screens on HDMI monitors. The ECC value is generated by the hardware. I don't see how this should break anything since we're writing 0 and that should be the correct value, so this patch should be safe. Notice that on IVB and older we actually have 64 bytes available for VIDEO_DIP_DATA, but only bytes 0-31 actually store infoframe data: the others are either read-only ECC values or marked as "reserved". On HSW we only have 32 bytes, and the ECC value is stored on its own separate read-only register. See BSpec. This patch fixes bug #46761, which is marked as a regression introduced by commit 4e89ee174bb2da341bf90a84321c7008a3c9210d: drm/i915: set the DIP port on ibx_write_infoframe Before commit 4e89 we were just failing to send AVI infoframes when we needed to change the port, which can lead to black screens in some cases. After commit 4e89 we started sending infoframes, but with a possibly wrong ECC value. After this patch I hope we start sending correct infoframes. Version 2: - Improve commit message - Try to make the code more clear Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46761 Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_hdmi.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 28725ce5b82cc0..a474a1ab1bc9fd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1753,6 +1753,10 @@ /* Video Data Island Packet control */ #define VIDEO_DIP_DATA 0x61178 +/* Read the description of VIDEO_DIP_DATA (before Haswel) or VIDEO_DIP_ECC + * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte + * of the infoframe structure specified by CEA-861. */ +#define VIDEO_DIP_DATA_SIZE 32 #define VIDEO_DIP_CTL 0x61170 /* Pre HSW: */ #define VIDEO_DIP_ENABLE (1 << 31) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 12dc3308ab8c98..34b6724cda2ab3 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -151,6 +151,9 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, I915_WRITE(VIDEO_DIP_DATA, *data); data++; } + /* Write every possible data byte to force correct ECC calculation. */ + for (; i < VIDEO_DIP_DATA_SIZE; i += 4) + I915_WRITE(VIDEO_DIP_DATA, 0); mmiowb(); val |= g4x_infoframe_enable(frame); @@ -186,6 +189,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + /* Write every possible data byte to force correct ECC calculation. */ + for (; i < VIDEO_DIP_DATA_SIZE; i += 4) + I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); mmiowb(); val |= g4x_infoframe_enable(frame); @@ -224,6 +230,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + /* Write every possible data byte to force correct ECC calculation. */ + for (; i < VIDEO_DIP_DATA_SIZE; i += 4) + I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); mmiowb(); val |= g4x_infoframe_enable(frame); @@ -259,6 +268,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + /* Write every possible data byte to force correct ECC calculation. */ + for (; i < VIDEO_DIP_DATA_SIZE; i += 4) + I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0); mmiowb(); val |= g4x_infoframe_enable(frame); @@ -292,6 +304,9 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, I915_WRITE(data_reg + i, *data); data++; } + /* Write every possible data byte to force correct ECC calculation. */ + for (; i < VIDEO_DIP_DATA_SIZE; i += 4) + I915_WRITE(data_reg + i, 0); mmiowb(); val |= hsw_infoframe_enable(frame); From a49679795f592ab764fab31bd94ce533a2e3395d Mon Sep 17 00:00:00 2001 From: Felix Kaechele Date: Wed, 26 Sep 2012 01:20:44 +0200 Subject: [PATCH 0123/1071] ALSA: hda - Add inverted internal mic quirk for Lenovo IdeaPad U310 commit e4db0952e542090c605fd41d31d761f1b4624f4a upstream. The Lenovo IdeaPad U310 has an internal mic where the right channel is phase inverted. Signed-off-by: Felix Kaechele Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5e22a8f43d2eeb..784017e6e589a5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -4462,6 +4462,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), {} }; From b719c952c5d6d24df15f8506f5b440a760b481a0 Mon Sep 17 00:00:00 2001 From: Omair Mohammed Abdullah Date: Sat, 29 Sep 2012 12:24:05 +0530 Subject: [PATCH 0124/1071] ALSA: aloop - add locking to timer access commit d4f1e48bd11e3df6a26811f7a1f06c4225d92f7d upstream. When the loopback timer handler is running, calling del_timer() (for STOP trigger) will not wait for the handler to complete before deactivating the timer. The timer gets rescheduled in the handler as usual. Then a subsequent START trigger will try to start the timer using add_timer() with a timer pending leading to a kernel panic. Serialize the calls to add_timer() and del_timer() using a spin lock to avoid this. Signed-off-by: Omair Mohammed Abdullah Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/drivers/aloop.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 5a34355e78e8f8..0fe6d64ff840f0 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -120,6 +120,7 @@ struct loopback_pcm { unsigned int last_drift; unsigned long last_jiffies; struct timer_list timer; + spinlock_t timer_lock; }; static struct platform_device *devices[SNDRV_CARDS]; @@ -170,6 +171,7 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) unsigned long tick; unsigned int rate_shift = get_rate_shift(dpcm); + spin_lock(&dpcm->timer_lock); if (rate_shift != dpcm->pcm_rate_shift) { dpcm->pcm_rate_shift = rate_shift; dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); @@ -182,12 +184,15 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; dpcm->timer.expires = jiffies + tick; add_timer(&dpcm->timer); + spin_unlock(&dpcm->timer_lock); } static inline void loopback_timer_stop(struct loopback_pcm *dpcm) { + spin_lock(&dpcm->timer_lock); del_timer(&dpcm->timer); dpcm->timer.expires = 0; + spin_unlock(&dpcm->timer_lock); } #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) @@ -667,6 +672,7 @@ static int loopback_open(struct snd_pcm_substream *substream) dpcm->substream = substream; setup_timer(&dpcm->timer, loopback_timer_function, (unsigned long)dpcm); + spin_lock_init(&dpcm->timer_lock); cable = loopback->cables[substream->number][dev]; if (!cable) { From e2e13279e29569c99fd45414abc827400459d817 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Fri, 21 Sep 2012 20:45:19 -0300 Subject: [PATCH 0125/1071] ALSA: hda/via - don't report presence on HPs with no presence support commit cf55e904516947597d75fd3844acc24891a95772 upstream. If headphone jack can't detect plug presence, and we have the jack in the jack table, snd_hda_jack_detect will return the plug as always present (as it'll be considered as a phantom jack). The problem is that when this happens, line out pins will always be disabled, resulting in no sound if there are no headphones connected. This was reported as a no sound problem after suspend on http://bugs.launchpad.net/bugs/1052499, since the bug doesn't manifests on first initialization before the phantom jack is added, but on resume we reexecute the initialization code, and via_hp_automute starts reporting HP always present with the jack now on the table. BugLink: https://bugs.launchpad.net/bugs/1052499 Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 43077177691588..53dfeb072c4464 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1672,7 +1672,8 @@ static void via_hp_automute(struct hda_codec *codec) struct via_spec *spec = codec->spec; if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && - (spec->codec_type != VT1708 || spec->vt1708_jack_detect)) + (spec->codec_type != VT1708 || spec->vt1708_jack_detect) && + is_jack_detectable(codec, spec->autocfg.hp_pins[0])) present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); if (spec->smart51_enabled) From b1b0d462d583585d64dfa3efa1965709c2913011 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 27 Sep 2012 10:38:14 -0300 Subject: [PATCH 0126/1071] ALSA: hda/realtek - Fix detection of ALC271X codec commit 9f720bb9409ea5923361fbd3fdbc505ca36cf012 upstream. In commit af741c1 ("ALSA: hda/realtek - Call alc_auto_parse_customize_define() always after fixup"), alc_auto_parse_customize_define was moved after detection of ALC271X. The problem is that detection of ALC271X relies on spec->cdefine.platform_type, and it's set on alc_auto_parse_customize_define. Move the alc_auto_parse_customize_define and its required fixup setup before the block doing the ALC271X and other codec setup. BugLink: https://bugs.launchpad.net/bugs/1006690 Signed-off-by: Herton Ronaldo Krzesinski Reviewed-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4f81dd44c837e1..56a3eefd3033ed 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6334,6 +6334,12 @@ static int patch_alc269(struct hda_codec *codec) spec = codec->spec; + alc_pick_fixup(codec, alc269_fixup_models, + alc269_fixup_tbl, alc269_fixups); + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); + + alc_auto_parse_customize_define(codec); + if (codec->vendor_id == 0x10ec0269) { spec->codec_variant = ALC269_TYPE_ALC269VA; switch (alc_get_coef0(codec) & 0x00f0) { @@ -6361,12 +6367,6 @@ static int patch_alc269(struct hda_codec *codec) alc269_fill_coef(codec); } - alc_pick_fixup(codec, alc269_fixup_models, - alc269_fixup_tbl, alc269_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - /* automatic parse from the BIOS config */ err = alc269_parse_auto_config(codec); if (err < 0) From 23532ac1552087eb99cc06de4a6b49bfc7b447a5 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 18 Sep 2012 14:26:59 +0200 Subject: [PATCH 0127/1071] ALSA: hda - limit internal mic boost for Asus X202E commit 4b527b6516ab1f0af8aaedd02dbf71ee2c1180f4 upstream. When the input gain for the internal mic is set to its maximum level, the background noise becomes so high - and any relevant signal clipped - that the setting becomes unusable. It is better to limit the amplification. BugLink: https://bugs.launchpad.net/bugs/1052460 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 53dfeb072c4464..4b4072fcec517e 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -3670,6 +3670,32 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) update_power_state(codec, 0x21, AC_PWRST_D3); } +/* + * pin fix-up + */ +enum { + VIA_FIXUP_INTMIC_BOOST, +}; + +static void via_fixup_intmic_boost(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) + override_mic_boost(codec, 0x30, 0, 2, 40); +} + +static const struct hda_fixup via_fixups[] = { + [VIA_FIXUP_INTMIC_BOOST] = { + .type = HDA_FIXUP_FUNC, + .v.func = via_fixup_intmic_boost, + }, +}; + +static const struct snd_pci_quirk vt2002p_fixups[] = { + SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST), + {} +}; + /* patch for vt2002P */ static int patch_vt2002P(struct hda_codec *codec) { @@ -3686,6 +3712,9 @@ static int patch_vt2002P(struct hda_codec *codec) override_mic_boost(codec, 0x29, 0, 3, 40); add_secret_dac_path(codec); + snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) { From 3ebd9559e210f49fe89c6b81177bf05b5ab645e8 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 20 Sep 2012 10:20:41 +0200 Subject: [PATCH 0128/1071] ALSA: usb - disable broken hw volume for Tenx TP6911 commit c10514394ef9e8de93a4ad8c8904d71dcd82c122 upstream. While going through Ubuntu bugs, I discovered this patch being posted and a confirmation that the patch works as expected. Finding out how the hw volume really works would be preferrable to just disabling the broken one, but this would be better than nothing. Credit: sndfnsdfin (qawsnews) BugLink: https://bugs.launchpad.net/bugs/559939 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/mixer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 4f40ba82316316..fe56c9da38e9e6 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1267,6 +1267,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void /* disable non-functional volume control */ master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); break; + case USB_ID(0x1130, 0xf211): + snd_printk(KERN_INFO + "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); + /* disable non-functional volume control */ + channels = 0; + break; + } if (channels > 0) first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); From 90180feb0afe4be06678d9cd965dd730bd773a7e Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 4 Sep 2012 10:23:07 +0200 Subject: [PATCH 0129/1071] ALSA: snd-usb: Add quirks for Playback Designs devices commit 2b58fd5b3193fd3af3d15114d95706087d25a7fe upstream. Playback Designs' USB devices have some hardware limitations on their USB interface. In particular: - They need a 20ms delay after each class compliant request as the hardware ACKs the USB packets before the device is actually ready for the next command. Sending data immediately will result in buffer overflows in the hardware. - The devices send bogus feedback data at the start of each stream which confuse the feedback format auto-detection. This patch introduces a new quirks hook that is called after each control packet and which adds a delay for all devices that match Playback Designs' USB VID for now. In addition, it adds a counter to snd_usb_endpoint to drop received packets on the floor. Another new quirks function that is called once an endpoint is started initializes that counter for these devices on their sync endpoint. Signed-off-by: Daniel Mack Reported-and-tested-by: Andreas Koch Supported-by: Demian Martin Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.h | 2 ++ sound/usb/endpoint.c | 8 ++++++++ sound/usb/helper.c | 5 +++++ sound/usb/quirks.c | 24 ++++++++++++++++++++++++ sound/usb/quirks.h | 10 ++++++++++ 5 files changed, 49 insertions(+) diff --git a/sound/usb/card.h b/sound/usb/card.h index 2b9fffff23b62a..d9d2b5a3bf2fcb 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -92,6 +92,8 @@ struct snd_usb_endpoint { unsigned char silence_value; unsigned int stride; int iface, alt_idx; + int skip_packets; /* quirks for devices to ignore the first n packets + in a stream */ spinlock_t lock; struct list_head list; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 060dccb9ec7551..d9de6670b97ef8 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -31,6 +31,7 @@ #include "card.h" #include "endpoint.h" #include "pcm.h" +#include "quirks.h" #define EP_FLAG_ACTIVATED 0 #define EP_FLAG_RUNNING 1 @@ -170,6 +171,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, { struct urb *urb = urb_ctx->urb; + if (unlikely(ep->skip_packets > 0)) { + ep->skip_packets--; + return; + } + if (ep->sync_slave) snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); @@ -828,6 +834,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) ep->unlink_mask = 0; ep->phase = 0; + snd_usb_endpoint_start_quirk(ep); + /* * If this endpoint has a data endpoint as implicit feedback source, * don't start the urbs here. Instead, mark them all as available, diff --git a/sound/usb/helper.c b/sound/usb/helper.c index 9eed8f40b179dd..c1db28f874c285 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c @@ -21,6 +21,7 @@ #include "usbaudio.h" #include "helper.h" +#include "quirks.h" /* * combine bytes and get an integer value @@ -97,6 +98,10 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, memcpy(data, buf, size); kfree(buf); } + + snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype, + value, index, data, size); + return err; } diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 27817266867ae2..0f58b4b6d7023d 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -761,3 +761,27 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, } } +void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) +{ + /* + * "Playback Design" products send bogus feedback data at the start + * of the stream. Ignore them. + */ + if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) && + ep->type == SND_USB_ENDPOINT_TYPE_SYNC) + ep->skip_packets = 4; +} + +void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, + __u8 request, __u8 requesttype, __u16 value, + __u16 index, void *data, __u16 size) +{ + /* + * "Playback Design" products need a 20ms delay after each + * class compliant request + */ + if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) && + (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + mdelay(20); +} + diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 03e5e94098cdc8..0ca9e91067a664 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -1,6 +1,10 @@ #ifndef __USBAUDIO_QUIRKS_H #define __USBAUDIO_QUIRKS_H +struct audioformat; +struct snd_usb_endpoint; +struct snd_usb_substream; + int snd_usb_create_quirk(struct snd_usb_audio *chip, struct usb_interface *iface, struct usb_driver *driver, @@ -20,4 +24,10 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp); +void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep); + +void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, + __u8 request, __u8 requesttype, __u16 value, + __u16 index, void *data, __u16 size); + #endif /* __USBAUDIO_QUIRKS_H */ From 904e56af97e43c45068a4a801eaf03fb04d122df Mon Sep 17 00:00:00 2001 From: Marko Friedemann Date: Mon, 3 Sep 2012 10:12:40 +0200 Subject: [PATCH 0130/1071] ALSA: USB: Support for (original) Xbox Communicator commit c05fce586d4da2dfe0309bef3795a8586e967bc3 upstream. Added support for Xbox Communicator to USB quirks. Signed-off-by: Marko Friedemann Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/quirks-table.h | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 79780fa57a4313..d73ac9bc427298 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2781,6 +2781,59 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* Microsoft XboxLive Headset/Xbox Communicator */ +{ + USB_DEVICE(0x045e, 0x0283), + .bInterfaceClass = USB_CLASS_PER_INTERFACE, + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Microsoft", + .product_name = "XboxLive Headset/Xbox Communicator", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = &(const struct snd_usb_audio_quirk[]) { + { + /* playback */ + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 0, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x04, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 22050, + .rate_max = 22050 + } + }, + { + /* capture */ + .ifnum = 1, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 1, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x85, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 16000, + .rate_max = 16000 + } + }, + { + .ifnum = -1 + } + } + } +}, + { /* * Some USB MIDI devices don't have an audio control interface, From 7bf3c0a63f177629f36106050cfc58000f12a235 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Mon, 17 Sep 2012 13:10:23 +0800 Subject: [PATCH 0131/1071] ALSA: hda - Add another pci id for Haswell board commit d279fae8a41690ec1b20c07be8c6f42f8af27a17 upstream. A new PCI id 0x0d0c for Haswell HDA Controller. [root@SKBM04SDP ~]# lspci |grep Audio 00:03.0 Audio device: Intel Corporation Device 0d0c (rev 02) 00:1b.0 Audio device: Intel Corporation Lynx Point HD Audio Controller Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c4763c52eaf64c..062447e7e49a24 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3285,6 +3285,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x0c0c), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + { PCI_DEVICE(0x8086, 0x0d0c), + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | From fbd15b54708f20d25e70d40c4035db37fa7c6c2a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 21 Sep 2012 18:39:06 -0500 Subject: [PATCH 0132/1071] ALSA: hda - use LPIB for delay estimation commit 90accc58a6946e7245993da6079f88d8c29cb731 upstream. DMA Position in Buffer (DPIB) should be used for ring buffer management, while LPIB register provides information on the number of samples transfered on the link. The difference between the two pieces of information corresponds to hardware/DMA buffering. This patch reports this difference in runtime->delay, and removes the use of the COMBO mode on recent Intel hardware. Credits to Takashi Iwai for an initial patch. [rebased to for-next branch and replaced snd_printk() with snd_printdd() by tiwai] Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 062447e7e49a24..12a9432359f7b6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -538,6 +538,7 @@ enum { #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ #define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ +#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -2120,6 +2121,27 @@ static unsigned int azx_get_position(struct azx *chip, if (pos >= azx_dev->bufsize) pos = 0; + + /* calculate runtime delay from LPIB */ + if (azx_dev->substream->runtime && + chip->position_fix[stream] == POS_FIX_POSBUF && + (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { + unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB); + int delay; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + delay = pos - lpib_pos; + else + delay = lpib_pos - pos; + if (delay < 0) + delay += azx_dev->bufsize; + if (delay >= azx_dev->period_bytes) { + snd_printdd("delay %d > period_bytes %d\n", + delay, azx_dev->period_bytes); + delay = 0; /* something is wrong */ + } + azx_dev->substream->runtime->delay = + bytes_to_frames(azx_dev->substream->runtime, delay); + } return pos; } @@ -3260,7 +3282,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, /* PBG */ { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | @@ -3268,26 +3290,26 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* Panther Point */ { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, /* Lynx Point */ { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, /* Lynx Point-LP */ { PCI_DEVICE(0x8086, 0x9c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, /* Lynx Point-LP */ { PCI_DEVICE(0x8086, 0x9c21), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0c0c), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, { PCI_DEVICE(0x8086, 0x0d0c), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | From 87b22644845862f54c657326d1da2484907db3b6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 28 Sep 2012 11:50:29 +1000 Subject: [PATCH 0133/1071] drm/nvc0/fence: restore pre-suspend fence buffer context on resume commit d6ba6d215a538a58f0f0026f0961b0b9125e8042 upstream. Fixes some unfortunate races on resume. The G84 version of the code doesn't need this as "gpuobj"s are automagically suspended/resumed by the core code whereas pinned buffer objects are not. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nvc0_fence.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c index 47ab388a606e83..8e5a2f407ed4d1 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/drivers/gpu/drm/nouveau/nvc0_fence.c @@ -32,6 +32,7 @@ struct nvc0_fence_priv { struct nouveau_fence_priv base; struct nouveau_bo *bo; + u32 *suspend; }; struct nvc0_fence_chan { @@ -125,12 +126,36 @@ nvc0_fence_context_new(struct nouveau_channel *chan, int engine) static int nvc0_fence_fini(struct drm_device *dev, int engine, bool suspend) { + struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nvc0_fence_priv *priv = nv_engine(dev, engine); + int i; + + if (suspend) { + priv->suspend = vmalloc(pfifo->channels * sizeof(u32)); + if (!priv->suspend) + return -ENOMEM; + + for (i = 0; i < pfifo->channels; i++) + priv->suspend[i] = nouveau_bo_rd32(priv->bo, i); + } + return 0; } static int nvc0_fence_init(struct drm_device *dev, int engine) { + struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO); + struct nvc0_fence_priv *priv = nv_engine(dev, engine); + int i; + + if (priv->suspend) { + for (i = 0; i < pfifo->channels; i++) + nouveau_bo_wr32(priv->bo, i, priv->suspend[i]); + vfree(priv->suspend); + priv->suspend = NULL; + } + return 0; } From 1d43ed629768ed28d3ae3131b5c64b2c5b6fc565 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 17 Sep 2012 09:38:03 +0000 Subject: [PATCH 0134/1071] drm: Destroy the planes prior to destroying the associated CRTC commit 3184009c36da413724f283e3c7ac9cc60c623bc4 upstream. As during the plane cleanup, we wish to disable the hardware and so may modify state on the associated CRTC, that CRTC must continue to exist until we are finished. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54101 Signed-off-by: Chris Wilson Cc: Jesse Barnes Reviewed-by: Jesse Barnes Tested-by: lu hua Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6fbfc244748fd9..af81f7775d302a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1034,15 +1034,15 @@ void drm_mode_config_cleanup(struct drm_device *dev) fb->funcs->destroy(fb); } - list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { - crtc->funcs->destroy(crtc); - } - list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, head) { plane->funcs->destroy(plane); } + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { + crtc->funcs->destroy(crtc); + } + idr_remove_all(&dev->mode_config.crtc_idr); idr_destroy(&dev->mode_config.crtc_idr); } From a364ac95d58cc2f64d596a298708a1429b60d5ac Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 14 Sep 2012 10:59:26 -0400 Subject: [PATCH 0135/1071] drm/radeon: only adjust default clocks on NI GPUs commit 2e3b3b105ab3bb5b6a37198da4f193cd13781d13 upstream. SI asics store voltage information differently so we don't have a way to deal with it properly yet. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_pm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 7ae60660010715..395d7e0dc48d86 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -547,7 +547,9 @@ void radeon_pm_suspend(struct radeon_device *rdev) void radeon_pm_resume(struct radeon_device *rdev) { /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); @@ -602,7 +604,9 @@ int radeon_pm_init(struct radeon_device *rdev) radeon_pm_print_states(rdev); radeon_pm_init_profile(rdev); /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); From bfe6102b77bd9a3925fa84517e047170befa75c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 25 Sep 2012 01:45:33 +0200 Subject: [PATCH 0136/1071] drm/radeon/kms: allow STRMOUT_BASE_UPDATE on RS780 and RS880 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 46fc8781bf428ce1094a5980ca2b92a49d33a8ca upstream. This is required to make streamout work there. Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600_cs.c | 3 ++- drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index f37676d7f217c5..dfa24480f1636a 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -2180,7 +2180,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p, } break; case PACKET3_STRMOUT_BASE_UPDATE: - if (p->family < CHIP_RV770) { + /* RS780 and RS880 also need this */ + if (p->family < CHIP_RS780) { DRM_ERROR("STRMOUT_BASE_UPDATE only supported on 7xx\n"); return -EINVAL; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 8c593ea82c412b..2c8b0f849e36e8 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -64,9 +64,10 @@ * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query * 2.21.0 - r600-r700: FMASK and CMASK * 2.22.0 - r600 only: RESOLVE_BOX allowed + * 2.23.0 - allow STRMOUT_BASE_UPDATE on RS780 and RS880 */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 22 +#define KMS_DRIVER_MINOR 23 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); From 4b9a37d406a64d169927c12aff51ba72c2b89311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 25 Sep 2012 03:34:01 +0200 Subject: [PATCH 0137/1071] drm/radeon: allow MIP_ADDRESS=0 for MSAA textures on Evergreen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 61051afd3540da71c1ac32f17ed663595a0f7ecb upstream. MIP_ADDRESS should point to the resolved FMASK for an MSAA texture. Setting MIP_ADDRESS to 0 means the FMASK pointer is invalid (the GPU won't read the memory then). The userspace has to set MIP_ADDRESS to 0 and *not* emit any relocation for it. Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen_cs.c | 59 +++++++++++++++++++++++---- drivers/gpu/drm/radeon/radeon_drv.c | 3 +- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index e44a62a07fe396..d883b20f45d2dd 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -846,6 +846,16 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, return -EINVAL; } + if (!mipmap) { + if (llevel) { + dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n", + __func__, __LINE__); + return -EINVAL; + } else { + return 0; /* everything's ok */ + } + } + /* check mipmap size */ for (i = 1; i <= llevel; i++) { unsigned w, h, d; @@ -1080,6 +1090,27 @@ static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, return 0; } +/** + * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP + * @p: structure holding the parser context. + * + * Check if the next packet is a relocation packet3. + **/ +static bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet p3reloc; + int r; + + r = evergreen_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return false; + } + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + return false; + } + return true; +} + /** * evergreen_cs_packet_next_vline() - parse userspace VLINE packet * @parser: parser structure holding parsing context. @@ -2330,7 +2361,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, for (i = 0; i < (pkt->count / 8); i++) { struct radeon_bo *texture, *mipmap; u32 toffset, moffset; - u32 size, offset; + u32 size, offset, mip_address, tex_dim; switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) { case SQ_TEX_VTX_VALID_TEXTURE: @@ -2359,14 +2390,28 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, } texture = reloc->robj; toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + /* tex mip base */ - r = evergreen_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("bad SET_RESOURCE (tex)\n"); - return -EINVAL; + tex_dim = ib[idx+1+(i*8)+0] & 0x7; + mip_address = ib[idx+1+(i*8)+3]; + + if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) && + !mip_address && + !evergreen_cs_packet_next_is_pkt3_nop(p)) { + /* MIP_ADDRESS should point to FMASK for an MSAA texture. + * It should be 0 if FMASK is disabled. */ + moffset = 0; + mipmap = NULL; + } else { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE (tex)\n"); + return -EINVAL; + } + moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + mipmap = reloc->robj; } - moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); - mipmap = reloc->robj; + r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8)); if (r) return r; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 2c8b0f849e36e8..27ece75b47890f 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -65,9 +65,10 @@ * 2.21.0 - r600-r700: FMASK and CMASK * 2.22.0 - r600 only: RESOLVE_BOX allowed * 2.23.0 - allow STRMOUT_BASE_UPDATE on RS780 and RS880 + * 2.24.0 - eg only: allow MIP_ADDRESS=0 for MSAA textures */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 23 +#define KMS_DRIVER_MINOR 24 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); From de6e1950e9455a350a174322137e55890ef2cf41 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Sep 2012 12:31:45 -0400 Subject: [PATCH 0138/1071] drm/radeon: Add MSI quirk for gateway RS690 commit 3a6d59df80897cc87812b6826d70085905bed013 upstream. Fixes another system on: https://bugs.freedesktop.org/show_bug.cgi?id=37679 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_irq_kms.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index afaa1727abd2dd..f4878b39ec9b94 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -204,6 +204,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev) (rdev->pdev->subsystem_device == 0x01fd)) return true; + /* Gateway RS690 only seems to work with MSIs. */ + if ((rdev->pdev->device == 0x791f) && + (rdev->pdev->subsystem_vendor == 0x107b) && + (rdev->pdev->subsystem_device == 0x0185)) + return true; + /* RV515 seems to have MSI issues where it loses * MSI rearms occasionally. This leads to lockups and freezes. * disable it by default. From 117262a8c47819ec502722159096b5dc90883a2b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Sep 2012 12:40:45 -0400 Subject: [PATCH 0139/1071] drm/radeon: force MSIs on RS690 asics commit fb6ca6d154cdcd53e7f27f8dbba513830372699b upstream. There are so many quirks, lets just try and force this for all RS690s. See: https://bugs.freedesktop.org/show_bug.cgi?id=37679 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_irq_kms.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index f4878b39ec9b94..443bd490615cc7 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -210,6 +210,10 @@ static bool radeon_msi_ok(struct radeon_device *rdev) (rdev->pdev->subsystem_device == 0x0185)) return true; + /* try and enable MSIs by default on all RS690s */ + if (rdev->family == CHIP_RS690) + return true; + /* RV515 seems to have MSI issues where it loses * MSI rearms occasionally. This leads to lockups and freezes. * disable it by default. From 57a38d925e665fcd729cd9ad4a75c84e11bd95c9 Mon Sep 17 00:00:00 2001 From: Ratan Nalumasu Date: Sat, 22 Sep 2012 11:46:30 -0700 Subject: [PATCH 0140/1071] HID: hidraw: don't deallocate memory when it is in use commit 4fe9f8e203fdad1524c04beb390f3c6099781ed9 upstream. When a device is unplugged, wait for all processes that have opened the device to close before deallocating the device. Signed-off-by: Ratan Nalumasu Signed-off-by: Jiri Kosina Cc: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hidraw.c | 69 +++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 3b6f7bf5a77e14..c46c5f1037f4bf 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -42,6 +42,7 @@ static struct cdev hidraw_cdev; static struct class *hidraw_class; static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DEFINE_MUTEX(minors_lock); +static void drop_ref(struct hidraw *hid, int exists_bit); static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { @@ -113,7 +114,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, __u8 *buf; int ret = 0; - if (!hidraw_table[minor]) { + if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { ret = -ENODEV; goto out; } @@ -261,7 +262,7 @@ static int hidraw_open(struct inode *inode, struct file *file) } mutex_lock(&minors_lock); - if (!hidraw_table[minor]) { + if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { err = -ENODEV; goto out_unlock; } @@ -298,36 +299,12 @@ static int hidraw_open(struct inode *inode, struct file *file) static int hidraw_release(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); - struct hidraw *dev; struct hidraw_list *list = file->private_data; - int ret; - int i; - - mutex_lock(&minors_lock); - if (!hidraw_table[minor]) { - ret = -ENODEV; - goto unlock; - } + drop_ref(hidraw_table[minor], 0); list_del(&list->node); - dev = hidraw_table[minor]; - if (!--dev->open) { - if (list->hidraw->exist) { - hid_hw_power(dev->hid, PM_HINT_NORMAL); - hid_hw_close(dev->hid); - } else { - kfree(list->hidraw); - } - } - - for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i) - kfree(list->buffer[i].value); kfree(list); - ret = 0; -unlock: - mutex_unlock(&minors_lock); - - return ret; + return 0; } static long hidraw_ioctl(struct file *file, unsigned int cmd, @@ -529,21 +506,7 @@ EXPORT_SYMBOL_GPL(hidraw_connect); void hidraw_disconnect(struct hid_device *hid) { struct hidraw *hidraw = hid->hidraw; - - mutex_lock(&minors_lock); - hidraw->exist = 0; - - device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); - - hidraw_table[hidraw->minor] = NULL; - - if (hidraw->open) { - hid_hw_close(hid); - wake_up_interruptible(&hidraw->wait); - } else { - kfree(hidraw); - } - mutex_unlock(&minors_lock); + drop_ref(hidraw, 1); } EXPORT_SYMBOL_GPL(hidraw_disconnect); @@ -585,3 +548,23 @@ void hidraw_exit(void) unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); } + +static void drop_ref(struct hidraw *hidraw, int exists_bit) +{ + mutex_lock(&minors_lock); + if (exists_bit) { + hid_hw_close(hidraw->hid); + hidraw->exist = 0; + if (hidraw->open) + wake_up_interruptible(&hidraw->wait); + } else { + --hidraw->open; + } + + if (!hidraw->open && !hidraw->exist) { + device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); + hidraw_table[hidraw->minor] = NULL; + kfree(hidraw); + } + mutex_unlock(&minors_lock); +} From 1a8f00d249b366be878ff40e2b520643a5637960 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 27 Sep 2012 21:25:58 +0100 Subject: [PATCH 0141/1071] drm/i915: Flush the pending flips on the CRTC before modification commit 5bb61643f6a70d48de9cfe91ad0fee0d618b6816 upstream. This was meant to be the purpose of the intel_crtc_wait_for_pending_flips() function which is called whilst preparing the CRTC for a modeset or before disabling. However, as Ville Syrjala pointed out, we set the pending flip notification on the old framebuffer that is no longer attached to the CRTC by the time we come to flush the pending operations. Instead, we can simply wait on the pending unpin work to be finished on this CRTC, knowning that the hardware has therefore finished modifying the registers, before proceeding with our direct access. Fixes i-g-t/flip_test on non-pch platforms. pch platforms simply schedule the flip immediately when the pipe is disabled, leading to other funny issues. Signed-off-by: Chris Wilson [danvet: Added i-g-t note and cc: stable] Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index df5570d67f890b..0c7f4aa3798a07 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2823,13 +2823,34 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) udelay(100); } +static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + bool pending; + + if (atomic_read(&dev_priv->mm.wedged)) + return false; + + spin_lock_irqsave(&dev->event_lock, flags); + pending = to_intel_crtc(crtc)->unpin_work != NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + + return pending; +} + static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; if (crtc->fb == NULL) return; + wait_event(dev_priv->pending_flip_queue, + !intel_crtc_has_pending_flip(crtc)); + mutex_lock(&dev->struct_mutex); intel_finish_fb(crtc->fb); mutex_unlock(&dev->struct_mutex); @@ -6149,9 +6170,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev, atomic_clear_mask(1 << intel_crtc->plane, &obj->pending_flip.counter); - if (atomic_read(&obj->pending_flip) == 0) - wake_up(&dev_priv->pending_flip_queue); + wake_up(&dev_priv->pending_flip_queue); schedule_work(&work->work); trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); From 2257e17ea4ff03c9d1d633a4cd1af4e2aa1f410e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 2 Oct 2012 17:54:35 +0200 Subject: [PATCH 0142/1071] drm/i915: call drm_handle_vblank before finish_page_flip commit 74d44445afb9f50126eba052adeb89827cee88f3 upstream. ... since finish_page_flip needs the vblank timestamp generated in drm_handle_vblank. Somehow all the gmch platforms get it right, but all the pch platform irq handlers get is wrong. Hooray for copy& pasting! Currently this gets papered over by a gross hack in finish_page_flip. A second patch will remove that. Note that without this, the new timestamp sanity checks in flip_test occasionally get tripped up, hence the cc: stable tag. Reviewed-by: mario.kleiner@tuebingen.mpg.de Tested-by: Imre Deak Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5249640cce1381..73fa3e146baf10 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -680,12 +680,12 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) intel_opregion_gse_intr(dev); for (i = 0; i < 3; i++) { + if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) + drm_handle_vblank(dev, i); if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) { intel_prepare_page_flip(dev, i); intel_finish_page_flip_plane(dev, i); } - if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) - drm_handle_vblank(dev, i); } /* check event from PCH */ @@ -767,6 +767,12 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_GSE) intel_opregion_gse_intr(dev); + if (de_iir & DE_PIPEA_VBLANK) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK) + drm_handle_vblank(dev, 1); + if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -777,12 +783,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } - if (de_iir & DE_PIPEA_VBLANK) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK) - drm_handle_vblank(dev, 1); - /* check event from PCH */ if (de_iir & DE_PCH_EVENT) { if (pch_iir & hotplug_mask) From 2a853d7062c3598e2fa68a6614cd953164dcaf3e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 3 Oct 2012 19:34:24 -0700 Subject: [PATCH 0143/1071] drm/i915: Fix GT_MODE default value commit f8f2ac9a76b0f80a6763ca316116a7bab8486997 upstream. I can't even find how I figured this might be needed anymore. But sure enough, the value I'm reading back on platforms doesn't match what the docs recommends. It seemed to fix Chris' GT1 in limited testing as well. Tested-by: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_pm.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a474a1ab1bc9fd..a3e53c52e41ec6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -519,6 +519,9 @@ # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 12) +#define GEN6_GT_MODE 0x20d0 +#define GEN6_GT_MODE_HI (1 << 9) + #define GFX_MODE 0x02520 #define GFX_MODE_GEN7 0x0229c #define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ba8a27b1757ad9..8c73faee8ded90 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3387,6 +3387,11 @@ static void gen6_init_clock_gating(struct drm_device *dev) DISPPLANE_TRICKLE_FEED_DISABLE); intel_flush_display_plane(dev_priv, pipe); } + + /* The default value should be 0x200 according to docs, but the two + * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */ + I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_DISABLE(0xffff)); + I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI)); } static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) From eeb8209162b3d61b4e3cddb9935f5c8dfe097fb4 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 24 Aug 2012 13:22:13 -0700 Subject: [PATCH 0144/1071] ia64: Add missing RCU idle APIs on idle loop commit 93482f4ef1093f5961a63359a34612183d6beea0 upstream. Traditionally, the entire idle task served as an RCU quiescent state. But when RCU read side critical sections started appearing within the idle loop, this traditional strategy became untenable. The fix was to create new RCU APIs named rcu_idle_enter() and rcu_idle_exit(), which must be called by each architecture's idle loop so that RCU can tell when it is safe to ignore a given idle CPU. Unfortunately, this fix was never applied to ia64, a shortcoming remedied by this commit. Reported by: Tony Luck Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested by: Tony Luck Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index dd6fc14497419d..3e316ec0b83507 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -279,6 +280,7 @@ cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); if (can_do_pal_halt) { current_thread_info()->status &= ~TS_POLLING; /* @@ -309,6 +311,7 @@ cpu_idle (void) normal_xtp(); #endif } + rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); if (cpu_is_offline(cpu)) From a9fd381af918001a9920a6ccc85b4775866c215e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0145/1071] h8300: Add missing RCU idle APIs on idle loop commit b2fe1430d4115c74d007c825cb9dc3317f28bb16 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the h8300's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Yoshinori Sato Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/h8300/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 0e9c315be1040c..f153ed1a4c080b 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -78,8 +79,10 @@ void (*idle)(void) = default_idle; void cpu_idle(void) { while (1) { + rcu_idle_enter(); while (!need_resched()) idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } From 88ea476abc56219b18bf096bdebfefc785b111ba Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0146/1071] parisc: Add missing RCU idle APIs on idle loop commit fbe752188d5589e7fcbb8e79824e560f77dccc92 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the parisc's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: James E.J. Bottomley Cc: Helge Deller Cc: Parisc Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 2c05a9292a81cb..8c6b6b6561f0de 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -69,8 +70,10 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) barrier(); + rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); } From d693bb06f86eb5f94ee9f42d91ce630f88a72445 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0147/1071] xtensa: Add missing RCU idle APIs on idle loop commit 11ad47a0edbd62bfc0547cfcdf227a911433f207 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the xtensa's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Chris Zankel Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 2c8d6a3d250afd..bc44311aa18cc7 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -110,8 +111,10 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) platform_idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } From d866531501b32ae2b3e4f69a31ef091774202e7e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0148/1071] frv: Add missing RCU idle APIs on idle loop commit 41d8fe5bb3cf91ce2716ac8f43e4b40d802a99c8 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the Frv's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: David Howells Acked-by: David Howells Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/frv/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index ff95f50efea5cf..2eb7fa5bf9d8d4 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -69,12 +70,14 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { check_pgt_cache(); if (!frv_dma_inprogress && idle) idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } From 0faba81b8678ef19ef509da34ec2a64ee27dfcba Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0149/1071] mn10300: Add missing RCU idle APIs on idle loop commit 5b0753a90b7a98bc613c3767e9263a1a76d4f900 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the mn10300's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: David Howells Cc: Koichi Yasutake Signed-off-by: Paul E. McKenney Acked-by: David Howells Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/mn10300/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 7dab0cd364663e..e9cceba193b651 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,7 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ for (;;) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); @@ -121,6 +123,7 @@ void cpu_idle(void) } idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } From 879d66835e7bec7fd8885febe67f7eea4885b196 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0150/1071] m68k: Add missing RCU idle APIs on idle loop commit 5b57ba37e82a15f345a6a2eb8c01a2b2d94c5eeb upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the m68k's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Acked-by: Geert Uytterhoeven Cc: m68k Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/m68k/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index c488e3cfab53ef..ac2892e49c7c91 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -75,8 +76,10 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } From 2b2e3e59d2482619b8b136a5053cb3842ae8d058 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0151/1071] alpha: Add missing RCU idle APIs on idle loop commit 4c94cada48f7c660eca582be6032427a5e367117 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the Alpha's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Tested-by: Michael Cree Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Cc: alpha Cc: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index d6fde98b74b38b..848ef4a51f9c10 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -54,8 +55,10 @@ cpu_idle(void) /* FIXME -- EV6 and LCA45 know how to power down the CPU. */ + rcu_idle_enter(); while (!need_resched()) cpu_relax(); + rcu_idle_exit(); schedule(); } } From ce47daf34ed6e95e6ae37ed20442e4c739af3edf Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0152/1071] cris: Add missing RCU idle APIs on idle loop commit c633f9e788928e91ad11f44df29b47bbbe9550b0 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the Cris's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Mikael Starvik Cc: Jesper Nilsson Cc: Cris Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/cris/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 66fd01728790b3..7f65be6f7f1774 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include //#define DEBUG @@ -74,6 +75,7 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); /* @@ -86,6 +88,7 @@ void cpu_idle (void) idle = default_idle; idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } } From ac1c02f167ece50c933392e6853f198003ddfd8a Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0153/1071] m32r: Add missing RCU idle APIs on idle loop commit 48ae077cfce72591b8fc80e1dcc87806f86fed7f upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the m32r's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Hirokazu Takata Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/m32r/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 3a4a32b2720802..384e63f3a4c4e9 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,7 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void) = pm_idle; @@ -90,6 +92,7 @@ void cpu_idle (void) idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } } From 297981522d6a1db819a9a44ceecf147c04083143 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0154/1071] score: Add missing RCU idle APIs on idle loop commit 0ee23fda59740767324b4340247ca41a2f498ca6 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in scores's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Chen Liqin Cc: Lennox Wu Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/score/kernel/process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index 2707023c75637f..637970cfd3f414 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c @@ -27,6 +27,7 @@ #include #include #include +#include void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); @@ -50,9 +51,10 @@ void __noreturn cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) barrier(); - + rcu_idle_exit(); schedule_preempt_disabled(); } } From 46482fa209172c262d3501146cb7c638a5ad359f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 22 Sep 2012 13:55:30 -0700 Subject: [PATCH 0155/1071] rcu: Fix day-one dyntick-idle stall-warning bug commit a10d206ef1a83121ab7430cb196e0376a7145b22 upstream. Each grace period is supposed to have at least one callback waiting for that grace period to complete. However, if CONFIG_NO_HZ=n, an extra callback-free grace period is no big problem -- it will chew up a tiny bit of CPU time, but it will complete normally. In contrast, CONFIG_NO_HZ=y kernels have the potential for all the CPUs to go to sleep indefinitely, in turn indefinitely delaying completion of the callback-free grace period. Given that nothing is waiting on this grace period, this is also not a problem. That is, unless RCU CPU stall warnings are also enabled, as they are in recent kernels. In this case, if a CPU wakes up after at least one minute of inactivity, an RCU CPU stall warning will result. The reason that no one noticed until quite recently is that most systems have enough OS noise that they will never remain absolutely idle for a full minute. But there are some embedded systems with cut-down userspace configurations that consistently get into this situation. All this begs the question of exactly how a callback-free grace period gets started in the first place. This can happen due to the fact that CPUs do not necessarily agree on which grace period is in progress. If a CPU still believes that the grace period that just completed is still ongoing, it will believe that it has callbacks that need to wait for another grace period, never mind the fact that the grace period that they were waiting for just completed. This CPU can therefore erroneously decide to start a new grace period. Note that this can happen in TREE_RCU and TREE_PREEMPT_RCU even on a single-CPU system: Deadlock considerations mean that the CPU that detected the end of the grace period is not necessarily officially informed of this fact for some time. Once this CPU notices that the earlier grace period completed, it will invoke its callbacks. It then won't have any callbacks left. If no other CPU has any callbacks, we now have a callback-free grace period. This commit therefore makes CPUs check more carefully before starting a new grace period. This new check relies on an array of tail pointers into each CPU's list of callbacks. If the CPU is up to date on which grace periods have completed, it checks to see if any callbacks follow the RCU_DONE_TAIL segment, otherwise it checks to see if any callbacks follow the RCU_WAIT_TAIL segment. The reason that this works is that the RCU_WAIT_TAIL segment will be promoted to the RCU_DONE_TAIL segment as soon as the CPU is officially notified that the old grace period has ended. This change is to cpu_needs_another_gp(), which is called in a number of places. The only one that really matters is in rcu_start_gp(), where the root rcu_node structure's ->lock is held, which prevents any other CPU from starting or completing a grace period, so that the comparison that determines whether the CPU is missing the completion of a grace period is stable. Reported-by: Becky Bruce Reported-by: Subodh Nijsure Reported-by: Paul Walmsley Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested-by: Paul Walmsley # OMAP3730, OMAP4430 Signed-off-by: Greg Kroah-Hartman --- kernel/rcutree.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index f280e542e3e9f5..f7bcd9e6c054ae 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -305,7 +305,9 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp) static int cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp) { - return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp); + return *rdp->nxttail[RCU_DONE_TAIL + + ACCESS_ONCE(rsp->completed) != rdp->completed] && + !rcu_gp_in_progress(rsp); } /* From bec0566d6d785490172cebd7180f2716c3483ad9 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 8 Oct 2012 16:29:14 -0700 Subject: [PATCH 0156/1071] revert "mm: mempolicy: Let vma_merge and vma_split handle vma->vm_policy linkages" commit 8d34694c1abf29df1f3c7317936b7e3e2e308d9b upstream. Commit 05f144a0d5c2 ("mm: mempolicy: Let vma_merge and vma_split handle vma->vm_policy linkages") removed vma->vm_policy updates code but it is the purpose of mbind_range(). Now, mbind_range() is virtually a no-op and while it does not allow memory corruption it is not the right fix. This patch is a revert. [mgorman@suse.de: Edited changelog] Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Cc: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 4ada3be6e25212..92daa267baf2e7 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -607,6 +607,27 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, return first; } +/* Apply policy to a single VMA */ +static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new) +{ + int err = 0; + struct mempolicy *old = vma->vm_policy; + + pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff, + vma->vm_ops, vma->vm_file, + vma->vm_ops ? vma->vm_ops->set_policy : NULL); + + if (vma->vm_ops && vma->vm_ops->set_policy) + err = vma->vm_ops->set_policy(vma, new); + if (!err) { + mpol_get(new); + vma->vm_policy = new; + mpol_put(old); + } + return err; +} + /* Step 2: apply policy to a range and do splits. */ static int mbind_range(struct mm_struct *mm, unsigned long start, unsigned long end, struct mempolicy *new_pol) @@ -655,23 +676,9 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, if (err) goto out; } - - /* - * Apply policy to a single VMA. The reference counting of - * policy for vma_policy linkages has already been handled by - * vma_merge and split_vma as necessary. If this is a shared - * policy then ->set_policy will increment the reference count - * for an sp node. - */ - pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", - vma->vm_start, vma->vm_end, vma->vm_pgoff, - vma->vm_ops, vma->vm_file, - vma->vm_ops ? vma->vm_ops->set_policy : NULL); - if (vma->vm_ops && vma->vm_ops->set_policy) { - err = vma->vm_ops->set_policy(vma, new_pol); - if (err) - goto out; - } + err = policy_vma(vma, new_pol); + if (err) + goto out; } out: From 3540dbf4f2e5bd61d05d59a2d62a2640af036361 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 8 Oct 2012 16:29:16 -0700 Subject: [PATCH 0157/1071] mempolicy: remove mempolicy sharing commit 869833f2c5c6e4dd09a5378cfc665ffb4615e5d2 upstream. Dave Jones' system call fuzz testing tool "trinity" triggered the following bug error with slab debugging enabled ============================================================================= BUG numa_policy (Not tainted): Poison overwritten ----------------------------------------------------------------------------- INFO: 0xffff880146498250-0xffff880146498250. First byte 0x6a instead of 0x6b INFO: Allocated in mpol_new+0xa3/0x140 age=46310 cpu=6 pid=32154 __slab_alloc+0x3d3/0x445 kmem_cache_alloc+0x29d/0x2b0 mpol_new+0xa3/0x140 sys_mbind+0x142/0x620 system_call_fastpath+0x16/0x1b INFO: Freed in __mpol_put+0x27/0x30 age=46268 cpu=6 pid=32154 __slab_free+0x2e/0x1de kmem_cache_free+0x25a/0x260 __mpol_put+0x27/0x30 remove_vma+0x68/0x90 exit_mmap+0x118/0x140 mmput+0x73/0x110 exit_mm+0x108/0x130 do_exit+0x162/0xb90 do_group_exit+0x4f/0xc0 sys_exit_group+0x17/0x20 system_call_fastpath+0x16/0x1b INFO: Slab 0xffffea0005192600 objects=27 used=27 fp=0x (null) flags=0x20000000004080 INFO: Object 0xffff880146498250 @offset=592 fp=0xffff88014649b9d0 The problem is that the structure is being prematurely freed due to a reference count imbalance. In the following case mbind(addr, len) should replace the memory policies of both vma1 and vma2 and thus they will become to share the same mempolicy and the new mempolicy will have the MPOL_F_SHARED flag. +-------------------+-------------------+ | vma1 | vma2(shmem) | +-------------------+-------------------+ | | addr addr+len alloc_pages_vma() uses get_vma_policy() and mpol_cond_put() pair for maintaining the mempolicy reference count. The current rule is that get_vma_policy() only increments refcount for shmem VMA and mpol_conf_put() only decrements refcount if the policy has MPOL_F_SHARED. In above case, vma1 is not shmem vma and vma->policy has MPOL_F_SHARED! The reference count will be decreased even though was not increased whenever alloc_page_vma() is called. This has been broken since commit [52cd3b07: mempolicy: rework mempolicy Reference Counting] in 2008. There is another serious bug with the sharing of memory policies. Currently, mempolicy rebind logic (it is called from cpuset rebinding) ignores a refcount of mempolicy and override it forcibly. Thus, any mempolicy sharing may cause mempolicy corruption. The bug was introduced by commit [68860ec1: cpusets: automatic numa mempolicy rebinding]. Ideally, the shared policy handling would be rewritten to either properly handle COW of the policy structures or at least reference count MPOL_F_SHARED based exclusively on information within the policy. However, this patch takes the easier approach of disabling any policy sharing between VMAs. Each new range allocated with sp_alloc will allocate a new policy, set the reference count to 1 and drop the reference count of the old policy. This increases the memory footprint but is not expected to be a major problem as mbind() is unlikely to be used for fine-grained ranges. It is also inefficient because it means we allocate a new policy even in cases where mbind_range() could use the new_policy passed to it. However, it is more straight-forward and the change should be invisible to the user. [mgorman@suse.de: Edited changelog] Reported-by: Dave Jones , Cc: Christoph Lameter , Reviewed-by: Christoph Lameter Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 52 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 92daa267baf2e7..f0728ae7467226 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -607,24 +607,39 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, return first; } -/* Apply policy to a single VMA */ -static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new) +/* + * Apply policy to a single VMA + * This must be called with the mmap_sem held for writing. + */ +static int vma_replace_policy(struct vm_area_struct *vma, + struct mempolicy *pol) { - int err = 0; - struct mempolicy *old = vma->vm_policy; + int err; + struct mempolicy *old; + struct mempolicy *new; pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_ops, vma->vm_file, vma->vm_ops ? vma->vm_ops->set_policy : NULL); - if (vma->vm_ops && vma->vm_ops->set_policy) + new = mpol_dup(pol); + if (IS_ERR(new)) + return PTR_ERR(new); + + if (vma->vm_ops && vma->vm_ops->set_policy) { err = vma->vm_ops->set_policy(vma, new); - if (!err) { - mpol_get(new); - vma->vm_policy = new; - mpol_put(old); + if (err) + goto err_out; } + + old = vma->vm_policy; + vma->vm_policy = new; /* protected by mmap_sem */ + mpol_put(old); + + return 0; + err_out: + mpol_put(new); return err; } @@ -676,7 +691,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, if (err) goto out; } - err = policy_vma(vma, new_pol); + err = vma_replace_policy(vma, new_pol); if (err) goto out; } @@ -2153,15 +2168,24 @@ static void sp_delete(struct shared_policy *sp, struct sp_node *n) static struct sp_node *sp_alloc(unsigned long start, unsigned long end, struct mempolicy *pol) { - struct sp_node *n = kmem_cache_alloc(sn_cache, GFP_KERNEL); + struct sp_node *n; + struct mempolicy *newpol; + n = kmem_cache_alloc(sn_cache, GFP_KERNEL); if (!n) return NULL; + + newpol = mpol_dup(pol); + if (IS_ERR(newpol)) { + kmem_cache_free(sn_cache, n); + return NULL; + } + newpol->flags |= MPOL_F_SHARED; + n->start = start; n->end = end; - mpol_get(pol); - pol->flags |= MPOL_F_SHARED; /* for unref */ - n->policy = pol; + n->policy = newpol; + return n; } From ea4be282d1ec21cd7515e9b75c37ce77c7227d9d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 8 Oct 2012 16:29:17 -0700 Subject: [PATCH 0158/1071] mempolicy: fix a race in shared_policy_replace() commit b22d127a39ddd10d93deee3d96e643657ad53a49 upstream. shared_policy_replace() use of sp_alloc() is unsafe. 1) sp_node cannot be dereferenced if sp->lock is not held and 2) another thread can modify sp_node between spin_unlock for allocating a new sp node and next spin_lock. The bug was introduced before 2.6.12-rc2. Kosaki's original patch for this problem was to allocate an sp node and policy within shared_policy_replace and initialise it when the lock is reacquired. I was not keen on this approach because it partially duplicates sp_alloc(). As the paths were sp->lock is taken are not that performance critical this patch converts sp->lock to sp->mutex so it can sleep when calling sp_alloc(). [kosaki.motohiro@jp.fujitsu.com: Original patch] Signed-off-by: Mel Gorman Acked-by: KOSAKI Motohiro Reviewed-by: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mempolicy.h | 2 +- mm/mempolicy.c | 37 ++++++++++++++++--------------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 95b738c7abff9a..df082549b1f8ea 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -188,7 +188,7 @@ struct sp_node { struct shared_policy { struct rb_root root; - spinlock_t lock; + struct mutex mutex; }; void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index f0728ae7467226..b2f12ecc1b3469 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2083,7 +2083,7 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b) */ /* lookup first element intersecting start-end */ -/* Caller holds sp->lock */ +/* Caller holds sp->mutex */ static struct sp_node * sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end) { @@ -2147,13 +2147,13 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) if (!sp->root.rb_node) return NULL; - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); sn = sp_lookup(sp, idx, idx+1); if (sn) { mpol_get(sn->policy); pol = sn->policy; } - spin_unlock(&sp->lock); + mutex_unlock(&sp->mutex); return pol; } @@ -2193,10 +2193,10 @@ static struct sp_node *sp_alloc(unsigned long start, unsigned long end, static int shared_policy_replace(struct shared_policy *sp, unsigned long start, unsigned long end, struct sp_node *new) { - struct sp_node *n, *new2 = NULL; + struct sp_node *n; + int ret = 0; -restart: - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); n = sp_lookup(sp, start, end); /* Take care of old policies in the same range. */ while (n && n->start < end) { @@ -2209,16 +2209,14 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start, } else { /* Old policy spanning whole new range. */ if (n->end > end) { + struct sp_node *new2; + new2 = sp_alloc(end, n->end, n->policy); if (!new2) { - spin_unlock(&sp->lock); - new2 = sp_alloc(end, n->end, n->policy); - if (!new2) - return -ENOMEM; - goto restart; + ret = -ENOMEM; + goto out; } n->end = start; sp_insert(sp, new2); - new2 = NULL; break; } else n->end = start; @@ -2229,12 +2227,9 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start, } if (new) sp_insert(sp, new); - spin_unlock(&sp->lock); - if (new2) { - mpol_put(new2->policy); - kmem_cache_free(sn_cache, new2); - } - return 0; +out: + mutex_unlock(&sp->mutex); + return ret; } /** @@ -2252,7 +2247,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol) int ret; sp->root = RB_ROOT; /* empty tree == default mempolicy */ - spin_lock_init(&sp->lock); + mutex_init(&sp->mutex); if (mpol) { struct vm_area_struct pvma; @@ -2318,7 +2313,7 @@ void mpol_free_shared_policy(struct shared_policy *p) if (!p->root.rb_node) return; - spin_lock(&p->lock); + mutex_lock(&p->mutex); next = rb_first(&p->root); while (next) { n = rb_entry(next, struct sp_node, nd); @@ -2327,7 +2322,7 @@ void mpol_free_shared_policy(struct shared_policy *p) mpol_put(n->policy); kmem_cache_free(sn_cache, n); } - spin_unlock(&p->lock); + mutex_unlock(&p->mutex); } /* assumes fs == KERNEL_DS */ From ee561403e9fb860fc917b1804de1a56eaa3b0796 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 8 Oct 2012 16:29:19 -0700 Subject: [PATCH 0159/1071] mempolicy: fix refcount leak in mpol_set_shared_policy() commit 63f74ca21f1fad36d075e063f06dcc6d39fe86b2 upstream. When shared_policy_replace() fails to allocate new->policy is not freed correctly by mpol_set_shared_policy(). The problem is that shared mempolicy code directly call kmem_cache_free() in multiple places where it is easy to make a mistake. This patch creates an sp_free wrapper function and uses it. The bug was introduced pre-git age (IOW, before 2.6.12-rc2). [mgorman@suse.de: Editted changelog] Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Reviewed-by: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b2f12ecc1b3469..1763418f1adad4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2157,12 +2157,17 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) return pol; } +static void sp_free(struct sp_node *n) +{ + mpol_put(n->policy); + kmem_cache_free(sn_cache, n); +} + static void sp_delete(struct shared_policy *sp, struct sp_node *n) { pr_debug("deleting %lx-l%lx\n", n->start, n->end); rb_erase(&n->nd, &sp->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_free(n); } static struct sp_node *sp_alloc(unsigned long start, unsigned long end, @@ -2301,7 +2306,7 @@ int mpol_set_shared_policy(struct shared_policy *info, } err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new); if (err && new) - kmem_cache_free(sn_cache, new); + sp_free(new); return err; } @@ -2318,9 +2323,7 @@ void mpol_free_shared_policy(struct shared_policy *p) while (next) { n = rb_entry(next, struct sp_node, nd); next = rb_next(&n->nd); - rb_erase(&n->nd, &p->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_delete(p, n); } mutex_unlock(&p->mutex); } From f66a52d6f1561fb601b0ad4e54ae3363b2af2486 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 8 Oct 2012 16:29:20 -0700 Subject: [PATCH 0160/1071] mempolicy: fix a memory corruption by refcount imbalance in alloc_pages_vma() commit 00442ad04a5eac08a98255697c510e708f6082e2 upstream. Commit cc9a6c877661 ("cpuset: mm: reduce large amounts of memory barrier related damage v3") introduced a potential memory corruption. shmem_alloc_page() uses a pseudo vma and it has one significant unique combination, vma->vm_ops=NULL and vma->policy->flags & MPOL_F_SHARED. get_vma_policy() does NOT increase a policy ref when vma->vm_ops=NULL and mpol_cond_put() DOES decrease a policy ref when a policy has MPOL_F_SHARED. Therefore, when a cpuset update race occurs, alloc_pages_vma() falls in 'goto retry_cpuset' path, decrements the reference count and frees the policy prematurely. Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Reviewed-by: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1763418f1adad4..3d64b369180d60 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1552,8 +1552,18 @@ struct mempolicy *get_vma_policy(struct task_struct *task, addr); if (vpol) pol = vpol; - } else if (vma->vm_policy) + } else if (vma->vm_policy) { pol = vma->vm_policy; + + /* + * shmem_alloc_page() passes MPOL_F_SHARED policy with + * a pseudo vma whose vma->vm_ops=NULL. Take a reference + * count on these policies which will be dropped by + * mpol_cond_put() later + */ + if (mpol_needs_cond_ref(pol)) + mpol_get(pol); + } } if (!pol) pol = &default_policy; From 470b2dd6130f9fe44a7ac9554931bf217108d9a9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Jul 2012 18:00:00 -0400 Subject: [PATCH 0161/1071] efi: Build EFI stub with EFI-appropriate options commit 9dead5bbb825d7c25c0400e61de83075046322d0 upstream. We can't assume the presence of the red zone while we're still in a boot services environment, so we should build with -fno-red-zone to avoid problems. Change the size of wchar at the same time to make string handling simpler. Signed-off-by: Matthew Garrett Signed-off-by: Matt Fleming Acked-by: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- arch/x86/boot/compressed/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index e398bb5d63bb26..8a84501acb1b96 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -28,6 +28,9 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ $(obj)/piggy.o +$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone +$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone + ifeq ($(CONFIG_EFI_STUB), y) VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o endif From b3ab8b31e8b3c1ff4971bd52d0c8ebde5cfbdb97 Mon Sep 17 00:00:00 2001 From: Seiji Aguchi Date: Tue, 24 Jul 2012 13:27:23 +0000 Subject: [PATCH 0162/1071] efi: initialize efi.runtime_version to make query_variable_info/update_capsule workable commit d6cf86d8f23253225fe2a763d627ecf7dfee9dae upstream. A value of efi.runtime_version is checked before calling update_capsule()/query_variable_info() as follows. But it isn't initialized anywhere. static efi_status_t virt_efi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space, u64 *max_variable_size) { if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) return EFI_UNSUPPORTED; This patch initializes a value of efi.runtime_version at boot time. Signed-off-by: Seiji Aguchi Acked-by: Matthew Garrett Signed-off-by: Matt Fleming Signed-off-by: Ivan Hu Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 92660edaa1e72d..f55a4ce6dc494d 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -890,6 +890,7 @@ void __init efi_enter_virtual_mode(void) * * Call EFI services through wrapper functions. */ + efi.runtime_version = efi_systab.fw_revision; efi.get_time = virt_efi_get_time; efi.set_time = virt_efi_set_time; efi.get_wakeup_time = virt_efi_get_wakeup_time; From 303990b92c02c16209f283b5fd8be431efcbb8b7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 2 Oct 2012 16:02:57 -0300 Subject: [PATCH 0163/1071] em28xx: regression fix: use DRX-K sync firmware requests on em28xx commit 2425bb3d4016ed95ce83a90b53bd92c7f31091e4 upstream. As em28xx-dvb will always be initialized asynchronously, there's no need anymore for a separate thread to load the DRX-K firmware. Fixes a known regression with kernel 3.6 with tda18271 driver and asynchronous DRX-K firmware load. Antti tested it with the following hardware: Hauppauge WinTV HVR 930C MaxMedia UB425-TC PCTV QuatroStick nano (520e) Tested-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/em28xx/em28xx-dvb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index a16531fa937a1e..7353143f18c3ed 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -316,6 +316,7 @@ static struct drxk_config terratec_h5_drxk = { .no_i2c_bridge = 1, .microcode_name = "dvb-usb-terratec-h5-drxk.fw", .qam_demod_parameter_count = 2, + .load_firmware_sync = true, }; static struct drxk_config hauppauge_930c_drxk = { @@ -325,6 +326,7 @@ static struct drxk_config hauppauge_930c_drxk = { .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", .chunk_size = 56, .qam_demod_parameter_count = 2, + .load_firmware_sync = true, }; struct drxk_config terratec_htc_stick_drxk = { @@ -338,12 +340,14 @@ struct drxk_config terratec_htc_stick_drxk = { .antenna_dvbt = true, /* The windows driver uses the same. This will disable LNA. */ .antenna_gpio = 0x6, + .load_firmware_sync = true, }; static struct drxk_config maxmedia_ub425_tc_drxk = { .adr = 0x29, .single_master = 1, .no_i2c_bridge = 1, + .load_firmware_sync = true, }; static struct drxk_config pctv_520e_drxk = { @@ -354,6 +358,7 @@ static struct drxk_config pctv_520e_drxk = { .chunk_size = 58, .antenna_dvbt = true, /* disable LNA */ .antenna_gpio = (1 << 2), /* disable LNA */ + .load_firmware_sync = true, }; static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) From df953f991735380b44bdc995c6b4c7bef3618b66 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 6 Sep 2012 00:03:50 +0200 Subject: [PATCH 0164/1071] sched: Fix load avg vs. cpu-hotplug commit 08bedae1d0acd8c9baf514fb69fa199d0c8345f6 upstream. Commit f319da0c68 ("sched: Fix load avg vs cpu-hotplug") was an incomplete fix: In particular, the problem is that at the point it calls calc_load_migrate() nr_running := 1 (the stopper thread), so move the call to CPU_DEAD where we're sure that nr_running := 0. Also note that we can call calc_load_migrate() without serialization, we know the state of rq is stable since its cpu is dead, and we modify the global state using appropriate atomic ops. Suggested-by: Paul E. McKenney Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1346882630.2600.59.camel@twins Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 649c9f876cb164..1a48cdbc863146 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5604,7 +5604,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) migrate_tasks(cpu); BUG_ON(rq->nr_running != 1); /* the migration thread */ raw_spin_unlock_irqrestore(&rq->lock, flags); + break; + case CPU_DEAD: calc_load_migrate(rq); break; #endif From 93bfa6e4dade09e6b92a84990f479c3d59a69e14 Mon Sep 17 00:00:00 2001 From: Quinlan Pfiffer Date: Fri, 28 Sep 2012 19:58:44 +0000 Subject: [PATCH 0165/1071] asix: Adds support for Lenovo 10/100 USB dongle. commit 66dc81ecd71332783c92fb170950d5ddb43da461 upstream. This dongle ships with the X1 Carbon, and has an AX88772B usb to ethernet chip in it. Signed-off-by: Quinlan Pfiffer Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/asix_devices.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 32e31c5c5dc6bf..f778aa073ecc6e 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -929,6 +929,10 @@ static const struct usb_device_id products [] = { // JVC MP-PRX1 Port Replicator USB_DEVICE (0x04f1, 0x3008), .driver_info = (unsigned long) &ax8817x_info, +}, { + // Lenovo U2L100P 10/100 + USB_DEVICE (0x17ef, 0x7203), + .driver_info = (unsigned long) &ax88772_info, }, { // ASIX AX88772B 10/100 USB_DEVICE (0x0b95, 0x772b), From 22e22876160b6b19e4aa52d8e562149840945e9b Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Fri, 28 Sep 2012 15:57:01 -0700 Subject: [PATCH 0166/1071] ALSA: hda - Fix hang caused by race during suspend. commit d17344b3547669f5b6ee4fda993d03737a141bd6 upstream. There was a race condition when the system suspends while hda_power_work is running in the work queue. If system suspend (snd_hda_suspend) happens after the work queue releases power_lock but before it calls hda_call_codec_suspend, codec_suspend runs with power_on=0, causing the codec to power up for register reads, and hanging when it calls cancel_delayed_work_sync from the running work queue. The call chain from the work queue will look like this: hda_power_work <<- power_on = 1, unlock, then power_on cleard by suspend hda_call_codec_suspend hda_set_power_state snd_hda_codec_read codec_exec_verb snd_hda_power_up snd_hda_power_save __snd_hda_power_up cancel_delayed_work_sync <<-- cancelling executing wq Fix this by waiting for the work queue to finish before starting suspend if suspend is not happening on the work queue. Signed-off-by: Dylan Reid Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_codec.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 1c65cc5e3a3110..38fdefc9b0ee68 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3580,7 +3580,7 @@ static inline void hda_exec_init_verbs(struct hda_codec *codec) {} /* * call suspend and power-down; used both from PM and power-save */ -static void hda_call_codec_suspend(struct hda_codec *codec) +static void hda_call_codec_suspend(struct hda_codec *codec, bool in_wq) { if (codec->patch_ops.suspend) codec->patch_ops.suspend(codec); @@ -3589,7 +3589,9 @@ static void hda_call_codec_suspend(struct hda_codec *codec) codec->afg ? codec->afg : codec->mfg, AC_PWRST_D3); #ifdef CONFIG_SND_HDA_POWER_SAVE - cancel_delayed_work(&codec->power_work); + /* Cancel delayed work if we aren't currently running from it. */ + if (!in_wq) + cancel_delayed_work_sync(&codec->power_work); spin_lock(&codec->power_lock); snd_hda_update_power_acct(codec); trace_hda_power_down(codec); @@ -4410,7 +4412,7 @@ static void hda_power_work(struct work_struct *work) } spin_unlock(&codec->power_lock); - hda_call_codec_suspend(codec); + hda_call_codec_suspend(codec, true); if (bus->ops.pm_notify) bus->ops.pm_notify(bus); } @@ -5076,7 +5078,7 @@ int snd_hda_suspend(struct hda_bus *bus) list_for_each_entry(codec, &bus->codec_list, list) { if (hda_codec_is_power_on(codec)) - hda_call_codec_suspend(codec); + hda_call_codec_suspend(codec, false); } return 0; } From d7cced49961655a90d61148ce8fd4aaa8c44cd9f Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Sat, 18 Aug 2012 13:07:41 -0400 Subject: [PATCH 0167/1071] mtd: mtdpart: break it as soon as we parse out the partitions commit c51803ddba10d80d9f246066802c6e359cf1d44c upstream. We may cause a memory leak when the @types has more then one parser. Take the `default_mtd_part_types` for example. The default_mtd_part_types has two parsers now: `cmdlinepart` and `ofpart`. Assume the following case: The kernel command line sets the partitions like: #gpmi-nand:20m(boot),20m(kernel),1g(rootfs),-(user) But the devicetree file(such as arch/arm/boot/dts/imx28-evk.dts) also sets the same partitions as the kernel command line does. In the current code, the partitions parsed out by the `ofpart` will overwrite the @pparts which has already set by the `cmdlinepart` parser, and the the partitions parsed out by the `cmdlinepart` is missed. A memory leak occurs. So we should break the code as soon as we parse out the partitions, In actually, this patch makes a priority order between the parsers. If one parser has already parsed out the partitions successfully, it's no need to use another parser anymore. Signed-off-by: Huang Shijie Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdpart.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index d518e4db8a0bf8..f8c08ec65febb1 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -711,6 +711,8 @@ static const char *default_mtd_part_types[] = { * partition parsers, specified in @types. However, if @types is %NULL, then * the default list of parsers is used. The default list contains only the * "cmdlinepart" and "ofpart" parsers ATM. + * Note: If there are more then one parser in @types, the kernel only takes the + * partitions parsed out by the first parser. * * This function may return: * o a negative error code in case of failure @@ -735,11 +737,12 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, if (!parser) continue; ret = (*parser->parse_fn)(master, pparts, data); + put_partition_parser(parser); if (ret > 0) { printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); + break; } - put_partition_parser(parser); } return ret; } From d419593c0d5309892b3bcdac4ddac20c5d3f99e5 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 15 Aug 2012 20:28:05 +0400 Subject: [PATCH 0168/1071] mtd: autcpu12-nvram: Fix compile breakage commit d1f55c680e5d021e7066f4461dd678d42af18898 upstream. Update driver autcpu12-nvram.c so it compiles; map_read32/map_write32 no longer exist in the kernel so the driver is totally broken. Additionally, map_info name passed to simple_map_init is incorrect. Signed-off-by: Alexander Shiyan Acked-by: Arnd Bergmann Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/maps/autcpu12-nvram.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index e5bfd0e093bb1e..0598d52eaf9f98 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -43,7 +43,8 @@ struct map_info autcpu12_sram_map = { static int __init init_autcpu12_sram (void) { - int err, save0, save1; + map_word tmp, save0, save1; + int err; autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K); if (!autcpu12_sram_map.virt) { @@ -51,7 +52,7 @@ static int __init init_autcpu12_sram (void) err = -EIO; goto out; } - simple_map_init(&autcpu_sram_map); + simple_map_init(&autcpu12_sram_map); /* * Check for 32K/128K @@ -61,20 +62,22 @@ static int __init init_autcpu12_sram (void) * Read and check result on ofs 0x0 * Restore contents */ - save0 = map_read32(&autcpu12_sram_map,0); - save1 = map_read32(&autcpu12_sram_map,0x10000); - map_write32(&autcpu12_sram_map,~save0,0x10000); + save0 = map_read(&autcpu12_sram_map, 0); + save1 = map_read(&autcpu12_sram_map, 0x10000); + tmp.x[0] = ~save0.x[0]; + map_write(&autcpu12_sram_map, tmp, 0x10000); /* if we find this pattern on 0x0, we have 32K size * restore contents and exit */ - if ( map_read32(&autcpu12_sram_map,0) != save0) { - map_write32(&autcpu12_sram_map,save0,0x0); + tmp = map_read(&autcpu12_sram_map, 0); + if (!map_word_equal(&autcpu12_sram_map, tmp, save0)) { + map_write(&autcpu12_sram_map, save0, 0x0); goto map; } /* We have a 128K found, restore 0x10000 and set size * to 128K */ - map_write32(&autcpu12_sram_map,save1,0x10000); + map_write(&autcpu12_sram_map, save1, 0x10000); autcpu12_sram_map.size = SZ_128K; map: From 4e180af39587eed3d2ec27afd6df8e45e1594495 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Wed, 12 Sep 2012 14:26:26 +0200 Subject: [PATCH 0169/1071] mtd: nandsim: bugfix: fail if overridesize is too big commit bb0a13a13411c4ce24c48c8ff3cdf7b48d237240 upstream. If override size is too big, the module was actually loaded instead of failing, because retval was not set. This lead to memory corruption with the use of the freed structs nandsim and nand_chip. Signed-off-by: Richard Genoud Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nandsim.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index cf0cd3146817f9..5d8811809752e8 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -2333,6 +2333,7 @@ static int __init ns_init_module(void) uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize; if (new_size >> overridesize != nsmtd->erasesize) { NS_ERR("overridesize is too big\n"); + retval = -EINVAL; goto err_exit; } /* N.B. This relies on nand_scan not doing anything with the size before we change it */ From 9d674ea4d62df55d4f7f225143d27fa93e500b08 Mon Sep 17 00:00:00 2001 From: Shmulik Ladkani Date: Sun, 10 Jun 2012 13:58:12 +0300 Subject: [PATCH 0170/1071] mtd: nand: Use the mirror BBT descriptor when reading its version commit 7bb9c75436212813b38700c34df4bbb6eb82debe upstream. The code responsible for reading the version of the mirror bbt was incorrectly using the descriptor of the main bbt. Pass the mirror bbt descriptor to 'scan_read_raw' when reading the version of the mirror bbt. Signed-off-by: Shmulik Ladkani Acked-by: Sebastian Andrzej Siewior Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nand_bbt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 30d1319ff0657c..c126469b06457d 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -390,7 +390,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, /* Read the mirror version, if available */ if (md && (md->options & NAND_BBT_VERSION)) { scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, - mtd->writesize, td); + mtd->writesize, md); md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; pr_info("Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); From ee9be6a8ac6ca6b37f228cde4ee2b56b1090dd0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Fri, 31 Aug 2012 13:35:41 +0200 Subject: [PATCH 0171/1071] mtd: omap2: fix omap_nand_remove segfault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7d9b110269253b1d5858cfa57d68dfc7bf50dd77 upstream. Do not kfree() the mtd_info; it is handled in the mtd subsystem and already freed by nand_release(). Instead kfree() the struct omap_nand_info allocated in omap_nand_probe which was not freed before. This patch fixes following error when unloading the omap2 module: ---8<--- ~ $ rmmod omap2 ------------[ cut here ]------------ kernel BUG at mm/slab.c:3126! Internal error: Oops - BUG: 0 [#1] PREEMPT ARM Modules linked in: omap2(-) CPU: 0 Not tainted (3.6.0-rc3-00230-g155e36d-dirty #3) PC is at cache_free_debugcheck+0x2d4/0x36c LR is at kfree+0xc8/0x2ac pc : [] lr : [] psr: 200d0193 sp : c521fe08 ip : c0e8ef90 fp : c521fe5c r10: bf0001fc r9 : c521e000 r8 : c0d99c8c r7 : c661ebc0 r6 : c065d5a4 r5 : c65c4060 r4 : c78005c0 r3 : 00000000 r2 : 00001000 r1 : c65c4000 r0 : 00000001 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 86694019 DAC: 00000015 Process rmmod (pid: 549, stack limit = 0xc521e2f0) Stack: (0xc521fe08 to 0xc5220000) fe00: c008a874 c00bf44c c515c6d0 200d0193 c65c4860 c515c240 fe20: c521fe3c c521fe30 c008a9c0 c008a854 c521fe5c c65c4860 c78005c0 bf0001fc fe40: c780ff40 a00d0113 c521e000 00000000 c521fe84 c521fe60 c0112efc c01122d8 fe60: c65c4860 c0673778 c06737ac 00000000 00070013 00000000 c521fe9c c521fe88 fe80: bf0001fc c0112e40 c0673778 bf001ca8 c521feac c521fea0 c02ca11c bf0001ac fea0: c521fec4 c521feb0 c02c82c4 c02ca100 c0673778 bf001ca8 c521fee4 c521fec8 fec0: c02c8dd8 c02c8250 00000000 bf001ca8 bf001ca8 c0804ee0 c521ff04 c521fee8 fee0: c02c804c c02c8d20 bf001924 00000000 bf001ca8 c521e000 c521ff1c c521ff08 ff00: c02c950c c02c7fbc bf001d48 00000000 c521ff2c c521ff20 c02ca3a4 c02c94b8 ff20: c521ff3c c521ff30 bf001938 c02ca394 c521ffa4 c521ff40 c009beb4 bf001930 ff40: c521ff6c 70616d6f b6fe0032 c0014f84 70616d6f b6fe0032 00000081 60070010 ff60: c521ff84 c521ff70 c008e1f4 c00bf328 0001a004 70616d6f c521ff94 0021ff88 ff80: c008e368 0001a004 70616d6f b6fe0032 00000081 c0015028 00000000 c521ffa8 ffa0: c0014dc0 c009bcd0 0001a004 70616d6f bec2ab38 00000880 bec2ab38 00000880 ffc0: 0001a004 70616d6f b6fe0032 00000081 00000319 00000000 b6fe1000 00000000 ffe0: bec2ab30 bec2ab20 00019f00 b6f539c0 60070010 bec2ab38 aaaaaaaa aaaaaaaa Backtrace: [] (cache_free_debugcheck+0x0/0x36c) from [] (kfree+0xc8/0x2ac) [] (kfree+0x0/0x2ac) from [] (omap_nand_remove+0x5c/0x64 [omap2]) [] (omap_nand_remove+0x0/0x64 [omap2]) from [] (platform_drv_remove+0x28/0x2c) r5:bf001ca8 r4:c0673778 [] (platform_drv_remove+0x0/0x2c) from [] (__device_release_driver+0x80/0xdc) [] (__device_release_driver+0x0/0xdc) from [] (driver_detach+0xc4/0xc8) r5:bf001ca8 r4:c0673778 [] (driver_detach+0x0/0xc8) from [] (bus_remove_driver+0x9c/0x104) r6:c0804ee0 r5:bf001ca8 r4:bf001ca8 r3:00000000 [] (bus_remove_driver+0x0/0x104) from [] (driver_unregister+0x60/0x80) r6:c521e000 r5:bf001ca8 r4:00000000 r3:bf001924 [] (driver_unregister+0x0/0x80) from [] (platform_driver_unregister+0x1c/0x20) r5:00000000 r4:bf001d48 [] (platform_driver_unregister+0x0/0x20) from [] (omap_nand_driver_exit+0x14/0x1c [omap2]) [] (omap_nand_driver_exit+0x0/0x1c [omap2]) from [] (sys_delete_module+0x1f0/0x2ec) [] (sys_delete_module+0x0/0x2ec) from [] (ret_fast_syscall+0x0/0x48) r8:c0015028 r7:00000081 r6:b6fe0032 r5:70616d6f r4:0001a004 Code: e1a00005 eb0d9172 e7f001f2 e7f001f2 (e7f001f2) ---[ end trace 6a30b24d8c0cc2ee ]--- Segmentation fault --->8--- This error was introduced in 67ce04bf2746f8a1f8c2a104b313d20c63f68378 which was the first commit of this driver. Signed-off-by: Andreas Bießmann Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/omap2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ac4fd756eda375..4cd7ac09017f0e 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1387,7 +1387,7 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); - kfree(&info->mtd); + kfree(info); return 0; } From ccf5af221ef1f5d59f10f74ae1f08f9b289d0e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Fri, 31 Aug 2012 13:35:42 +0200 Subject: [PATCH 0172/1071] mtd: omap2: fix module loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4d3d688da8e7016f15483e9319b41311e1db9515 upstream. Unloading the omap2 nand driver missed to release the memory region which will result in not being able to request it again if one want to load the driver later on. This patch fixes following error when loading omap2 module after unloading: ---8<--- ~ $ rmmod omap2 ~ $ modprobe omap2 [ 37.420928] omap2-nand: probe of omap2-nand.0 failed with error -16 ~ $ --->8--- This error was introduced in 67ce04bf2746f8a1f8c2a104b313d20c63f68378 which was the first commit of this driver. Signed-off-by: Andreas Bießmann Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/omap2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 4cd7ac09017f0e..48f1d4ede35cd2 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1387,6 +1387,7 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); + release_mem_region(info->phys_base, NAND_IO_SIZE); kfree(info); return 0; } From 07c0544659b0d75a7b649b37ab5641fa0a3eec2c Mon Sep 17 00:00:00 2001 From: Vaibhav Bedia Date: Thu, 13 Sep 2012 06:31:03 +0000 Subject: [PATCH 0173/1071] mmc: omap_hsmmc: Pass on the suspend failure to the PM core commit c4c8eeb4df00aabb641553d6fbcd46f458e56cd9 upstream. In some cases mmc_suspend_host() is not able to claim the host and proceed with the suspend process. The core returns -EBUSY to the host controller driver. Unfortunately, the host controller driver does not pass on this information to the PM core and hence the system suspend process continues. ret = mmc_suspend_host(host->mmc); if (ret) { host->suspended = 0; if (host->pdata->resume) { ret = host->pdata->resume(dev, host->slot_id); The return status from mmc_suspend_host() is overwritten by return status from host->pdata->resume. So the original return status is lost. In these cases the MMC core gets to an unexpected state during resume and multiple issues related to MMC crop up. 1. Host controller driver starts accessing the device registers before the clocks are enabled which leads to a prefetch abort. 2. A file copy thread which was launched before suspend gets stuck due to the host not being reclaimed during resume. To avoid such problems pass on the -EBUSY status to the PM core from the host controller driver. With this change, MMC core suspend might still fail but it does not end up making the system unusable. Suspend gets aborted and the user can try suspending the system again. Signed-off-by: Vaibhav Bedia Signed-off-by: Hebbar, Gururaja Acked-by: Venkatraman S Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/omap_hsmmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 3a09f93cc3b6f8..ed4945c3ddf4d8 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2106,8 +2106,7 @@ static int omap_hsmmc_suspend(struct device *dev) if (ret) { host->suspended = 0; if (host->pdata->resume) { - ret = host->pdata->resume(dev, host->slot_id); - if (ret) + if (host->pdata->resume(dev, host->slot_id)) dev_dbg(dev, "Unmask interrupt failed\n"); } goto err; From 25356be596603e72329799728cbe494652ccdaab Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Sun, 9 Sep 2012 22:56:48 -0400 Subject: [PATCH 0174/1071] mmc: slot-gpio: Fix missing assignment to ctx->ro_gpio commit 15e8a8e42966162c207bb97ed55c803bc437eeae upstream. mmc_gpio_request_ro() doesn't store the requested gpio in ctx->ro_gpio. As a result, subsequent calls to mmc_gpio_get_ro() will always fail with -ENOSYS because the gpio number isn't available to that function. Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/core/slot-gpio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 058242916cef10..08c6b3dfe08049 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -100,7 +100,13 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) ctx = host->slot.handler_priv; - return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); + ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); + if (ret < 0) + return ret; + + ctx->ro_gpio = gpio; + + return 0; } EXPORT_SYMBOL(mmc_gpio_request_ro); From 8c63c3bf3e32a13c22edff2a9cc7310a46092e70 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 18 Sep 2012 06:42:42 +0000 Subject: [PATCH 0175/1071] mmc: sh-mmcif: avoid oops on spurious interrupts commit 8464dd52d3198dd05cafb005371d76e5339eb842 upstream. On some systems, e.g., kzm9g, MMCIF interfaces can produce spurious interrupts without any active request. To prevent the Oops, that results in such cases, don't dereference the mmc request pointer until we make sure, that we are indeed processing such a request. Reported-by: Tetsuyuki Kobayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sh_mmcif.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5d8142773fac07..ba0e493ad0c603 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1229,6 +1229,10 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) host->sd_error = true; dev_dbg(&host->pd->dev, "int err state = %08x\n", state); } + if (host->state == STATE_IDLE) { + dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state); + return IRQ_HANDLED; + } if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { if (!host->dma_active) return IRQ_WAKE_THREAD; From f6140a8820b12af81b7d346d0c75e4523d5338eb Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 23 Aug 2012 10:10:07 +0300 Subject: [PATCH 0176/1071] JFFS2: fix unmount regression commit a445f784ae5558a3da680aa6b39ed53c95a551c1 upstream. This patch fixes regression introduced by "8bdc81c jffs2: get rid of jffs2_sync_super". We submit a delayed work in order to make sure the write-buffer is synchronized at some point. But we do not flush it when we unmount, which causes an oops when we unmount the file-system and then the delayed work is executed. This patch fixes the issue by adding a "cancel_delayed_work_sync()" infocation in the '->sync_fs()' handler. This will make sure the delayed work is canceled on sync, unmount and re-mount. And because VFS always callse 'sync_fs()' before unmounting or remounting, this fixes the issue. Reported-by: Ludovic Desroches Signed-off-by: Artem Bityutskiy Tested-by: Ludovic Desroches Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- fs/jffs2/super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 61ea41389f90d9..1224d6b48e7e52 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -100,6 +100,10 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) { struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); +#ifdef CONFIG_JFFS2_FS_WRITEBUFFER + cancel_delayed_work_sync(&c->wbuf_dwork); +#endif + mutex_lock(&c->alloc_sem); jffs2_flush_wbuf_pad(c); mutex_unlock(&c->alloc_sem); From 4f0f3fedbb68f71b9b3048d1b59b37aad41ad6a1 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 31 Aug 2012 15:01:19 -0700 Subject: [PATCH 0177/1071] JFFS2: don't fail on bitflips in OOB commit 74d83beaa229aac7d126ac1ed9414658ff1a89d2 upstream. JFFS2 was designed without thought for OOB bitflips, it seems, but they can occur and will be reported to JFFS2 via mtd_read_oob()[1]. We don't want to fail on these transactions, since the data was corrected. [1] Few drivers report bitflips for OOB-only transactions. With such drivers, this patch should have no effect. Signed-off-by: Brian Norris Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- fs/jffs2/wbuf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 6f4529d3697fd3..a6597d60d76de7 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1044,10 +1044,10 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, ops.datbuf = NULL; ret = mtd_read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen != ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) { pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret = -EIO; return ret; } @@ -1086,10 +1086,10 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, ops.datbuf = NULL; ret = mtd_read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen != ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) { pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret = -EIO; return ret; } From b034312000118d88ddb6027c262bf898440448ae Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 3 Oct 2012 16:02:36 -0400 Subject: [PATCH 0178/1071] cifs: reinstate the forcegid option commit 72bd481f860f0125c810bb43d878ce5f9c060c58 upstream. Apparently this was lost when we converted to the standard option parser in 8830d7e07a5e38bc47650a7554b7c1cfd49902bf Reported-by: Gregory Lee Bartholomew Cc: Sachin Prabhu Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/connect.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6df6fa14cba8e9..b39bb4a06b6f93 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -67,6 +67,7 @@ enum { /* Mount options that take no arguments */ Opt_user_xattr, Opt_nouser_xattr, Opt_forceuid, Opt_noforceuid, + Opt_forcegid, Opt_noforcegid, Opt_noblocksend, Opt_noautotune, Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_mapchars, Opt_nomapchars, Opt_sfu, @@ -118,6 +119,8 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_nouser_xattr, "nouser_xattr" }, { Opt_forceuid, "forceuid" }, { Opt_noforceuid, "noforceuid" }, + { Opt_forcegid, "forcegid" }, + { Opt_noforcegid, "noforcegid" }, { Opt_noblocksend, "noblocksend" }, { Opt_noautotune, "noautotune" }, { Opt_hard, "hard" }, @@ -1190,6 +1193,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, case Opt_noforceuid: override_uid = 0; break; + case Opt_forcegid: + override_gid = 1; + break; + case Opt_noforcegid: + override_gid = 0; + break; case Opt_noblocksend: vol->noblocksnd = 1; break; From 049917d4843acf4b024f1721d83fbe2875cdd937 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Tue, 7 Aug 2012 04:33:03 -0500 Subject: [PATCH 0179/1071] Convert properly UTF-8 to UTF-16 commit fd3ba42c76d3d4b776120c2b24c1791e7bb3deb1 upstream. wchar_t is currently 16bit so converting a utf8 encoded characters not in plane 0 (>= 0x10000) to wchar_t (that is calling char2uni) lead to a -EINVAL return. This patch detect utf8 in cifs_strtoUTF16 and add special code calling utf8s_to_utf16s. Signed-off-by: Frediano Ziglio Acked-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifs_unicode.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 53cf2aabce877c..71d5d0a5f6b2fc 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -203,6 +203,27 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, int i; wchar_t wchar_to; /* needed to quiet sparse */ + /* special case for utf8 to handle no plane0 chars */ + if (!strcmp(codepage->charset, "utf8")) { + /* + * convert utf8 -> utf16, we assume we have enough space + * as caller should have assumed conversion does not overflow + * in destination len is length in wchar_t units (16bits) + */ + i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN, + (wchar_t *) to, len); + + /* if success terminate and exit */ + if (i >= 0) + goto success; + /* + * if fails fall back to UCS encoding as this + * function should not return negative values + * currently can fail only if source contains + * invalid encoded characters + */ + } + for (i = 0; len && *from; i++, from += charlen, len -= charlen) { charlen = codepage->char2uni(from, len, &wchar_to); if (charlen < 1) { @@ -215,6 +236,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, put_unaligned_le16(wchar_to, &to[i]); } +success: put_unaligned_le16(0, &to[i]); return i; } From cb4115ad44ce05fa8d2eee30857dc10d3a854507 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Oct 2012 05:50:59 +0900 Subject: [PATCH 0180/1071] Linux 3.6.2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9ed5898e0e61b6..af5d6a9023f0ac 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 1 +SUBLEVEL = 2 EXTRAVERSION = NAME = Terrified Chipmunk From e99bc7155de4a2598f853001720228d728d5ad1f Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Oct 2012 11:13:26 +0100 Subject: [PATCH 0181/1071] ARM: vfp: fix saving d16-d31 vfp registers on v6+ kernels commit 846a136881b8f73c1f74250bf6acfaa309cab1f2 upstream. Michael Olbrich reported that his test program fails when built with -O2 -mcpu=cortex-a8 -mfpu=neon, and a kernel which supports v6 and v7 CPUs: volatile int x = 2; volatile int64_t y = 2; int main() { volatile int a = 0; volatile int64_t b = 0; while (1) { a = (a + x) % (1 << 30); b = (b + y) % (1 << 30); assert(a == b); } } and two instances are run. When built for just v7 CPUs, this program works fine. It uses the "vadd.i64 d19, d18, d16" VFP instruction. It appears that we do not save the high-16 double VFP registers across context switches when the kernel is built for v6 CPUs. Fix that. Tested-By: Michael Olbrich Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/vfpmacros.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 3d5fc41ae8d38a..bf5304797c76d0 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -28,7 +28,7 @@ ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] tst \tmp, #HWCAP_VFPv3D16 - ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} addne \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 @@ -52,7 +52,7 @@ ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] tst \tmp, #HWCAP_VFPv3D16 - stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} addne \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 From fda45cc12ebb7060131111442844f977555e3b9b Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 24 Aug 2012 00:27:51 +0800 Subject: [PATCH 0182/1071] pnfsblock: fix partial page buffer wirte commit fe6e1e8d9fad86873eb74a26e80a8f91f9e870b5 upstream. If applications use flock to protect its write range, generic NFS will not do read-modify-write cycle at page cache level. Therefore LD should know how to handle non-sector aligned writes. Otherwise there will be data corruption. Signed-off-by: Peng Tao Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/blocklayout/blocklayout.c | 177 ++++++++++++++++++++++++++++--- fs/nfs/blocklayout/blocklayout.h | 1 + 2 files changed, 166 insertions(+), 12 deletions(-) diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index dd392ed5f2e28e..f3d16adc832c7d 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -162,25 +162,39 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect, return bio; } -static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, +static struct bio *do_add_page_to_bio(struct bio *bio, int npg, int rw, sector_t isect, struct page *page, struct pnfs_block_extent *be, void (*end_io)(struct bio *, int err), - struct parallel_io *par) + struct parallel_io *par, + unsigned int offset, int len) { + isect = isect + (offset >> SECTOR_SHIFT); + dprintk("%s: npg %d rw %d isect %llu offset %u len %d\n", __func__, + npg, rw, (unsigned long long)isect, offset, len); retry: if (!bio) { bio = bl_alloc_init_bio(npg, isect, be, end_io, par); if (!bio) return ERR_PTR(-ENOMEM); } - if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { + if (bio_add_page(bio, page, len, offset) < len) { bio = bl_submit_bio(rw, bio); goto retry; } return bio; } +static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, + sector_t isect, struct page *page, + struct pnfs_block_extent *be, + void (*end_io)(struct bio *, int err), + struct parallel_io *par) +{ + return do_add_page_to_bio(bio, npg, rw, isect, page, be, + end_io, par, 0, PAGE_CACHE_SIZE); +} + /* This is basically copied from mpage_end_io_read */ static void bl_end_io_read(struct bio *bio, int err) { @@ -461,6 +475,106 @@ map_block(struct buffer_head *bh, sector_t isect, struct pnfs_block_extent *be) return; } +static void +bl_read_single_end_io(struct bio *bio, int error) +{ + struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; + struct page *page = bvec->bv_page; + + /* Only one page in bvec */ + unlock_page(page); +} + +static int +bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int offset, unsigned int len) +{ + struct bio *bio; + struct page *shadow_page; + sector_t isect; + char *kaddr, *kshadow_addr; + int ret = 0; + + dprintk("%s: offset %u len %u\n", __func__, offset, len); + + shadow_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); + if (shadow_page == NULL) + return -ENOMEM; + + bio = bio_alloc(GFP_NOIO, 1); + if (bio == NULL) + return -ENOMEM; + + isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) + + (offset / SECTOR_SIZE); + + bio->bi_sector = isect - be->be_f_offset + be->be_v_offset; + bio->bi_bdev = be->be_mdev; + bio->bi_end_io = bl_read_single_end_io; + + lock_page(shadow_page); + if (bio_add_page(bio, shadow_page, + SECTOR_SIZE, round_down(offset, SECTOR_SIZE)) == 0) { + unlock_page(shadow_page); + bio_put(bio); + return -EIO; + } + + submit_bio(READ, bio); + wait_on_page_locked(shadow_page); + if (unlikely(!test_bit(BIO_UPTODATE, &bio->bi_flags))) { + ret = -EIO; + } else { + kaddr = kmap_atomic(page); + kshadow_addr = kmap_atomic(shadow_page); + memcpy(kaddr + offset, kshadow_addr + offset, len); + kunmap_atomic(kshadow_addr); + kunmap_atomic(kaddr); + } + __free_page(shadow_page); + bio_put(bio); + + return ret; +} + +static int +bl_read_partial_page_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int dirty_offset, unsigned int dirty_len, + bool full_page) +{ + int ret = 0; + unsigned int start, end; + + if (full_page) { + start = 0; + end = PAGE_CACHE_SIZE; + } else { + start = round_down(dirty_offset, SECTOR_SIZE); + end = round_up(dirty_offset + dirty_len, SECTOR_SIZE); + } + + dprintk("%s: offset %u len %d\n", __func__, dirty_offset, dirty_len); + if (!be) { + zero_user_segments(page, start, dirty_offset, + dirty_offset + dirty_len, end); + if (start == 0 && end == PAGE_CACHE_SIZE && + trylock_page(page)) { + SetPageUptodate(page); + unlock_page(page); + } + return ret; + } + + if (start != dirty_offset) + ret = bl_do_readpage_sync(page, be, start, dirty_offset - start); + + if (!ret && (dirty_offset + dirty_len < end)) + ret = bl_do_readpage_sync(page, be, dirty_offset + dirty_len, + end - dirty_offset - dirty_len); + + return ret; +} + /* Given an unmapped page, zero it or read in page for COW, page is locked * by caller. */ @@ -494,7 +608,6 @@ init_page_for_write(struct page *page, struct pnfs_block_extent *cow_read) SetPageUptodate(page); cleanup: - bl_put_extent(cow_read); if (bh) free_buffer_head(bh); if (ret) { @@ -566,6 +679,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) struct parallel_io *par = NULL; loff_t offset = wdata->args.offset; size_t count = wdata->args.count; + unsigned int pg_offset, pg_len, saved_len; struct page **pages = wdata->args.pages; struct page *page; pgoff_t index; @@ -674,10 +788,11 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) if (!extent_length) { /* We've used up the previous extent */ bl_put_extent(be); + bl_put_extent(cow_read); bio = bl_submit_bio(WRITE, bio); /* Get the next one */ be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg), - isect, NULL); + isect, &cow_read); if (!be || !is_writable(be, isect)) { header->pnfs_error = -EINVAL; goto out; @@ -694,7 +809,26 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) extent_length = be->be_length - (isect - be->be_f_offset); } - if (be->be_state == PNFS_BLOCK_INVALID_DATA) { + + dprintk("%s offset %lld count %Zu\n", __func__, offset, count); + pg_offset = offset & ~PAGE_CACHE_MASK; + if (pg_offset + count > PAGE_CACHE_SIZE) + pg_len = PAGE_CACHE_SIZE - pg_offset; + else + pg_len = count; + + saved_len = pg_len; + if (be->be_state == PNFS_BLOCK_INVALID_DATA && + !bl_is_sector_init(be->be_inval, isect)) { + ret = bl_read_partial_page_sync(pages[i], cow_read, + pg_offset, pg_len, true); + if (ret) { + dprintk("%s bl_read_partial_page_sync fail %d\n", + __func__, ret); + header->pnfs_error = ret; + goto out; + } + ret = bl_mark_sectors_init(be->be_inval, isect, PAGE_CACHE_SECTORS); if (unlikely(ret)) { @@ -703,15 +837,35 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) header->pnfs_error = ret; goto out; } + + /* Expand to full page write */ + pg_offset = 0; + pg_len = PAGE_CACHE_SIZE; + } else if ((pg_offset & (SECTOR_SIZE - 1)) || + (pg_len & (SECTOR_SIZE - 1))){ + /* ahh, nasty case. We have to do sync full sector + * read-modify-write cycles. + */ + unsigned int saved_offset = pg_offset; + ret = bl_read_partial_page_sync(pages[i], be, pg_offset, + pg_len, false); + pg_offset = round_down(pg_offset, SECTOR_SIZE); + pg_len = round_up(saved_offset + pg_len, SECTOR_SIZE) + - pg_offset; } - bio = bl_add_page_to_bio(bio, wdata->pages.npages - i, WRITE, + + + bio = do_add_page_to_bio(bio, wdata->pages.npages - i, WRITE, isect, pages[i], be, - bl_end_io_write, par); + bl_end_io_write, par, + pg_offset, pg_len); if (IS_ERR(bio)) { header->pnfs_error = PTR_ERR(bio); bio = NULL; goto out; } + offset += saved_len; + count -= saved_len; isect += PAGE_CACHE_SECTORS; last_isect = isect; extent_length -= PAGE_CACHE_SECTORS; @@ -729,17 +883,16 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) } write_done: - wdata->res.count = (last_isect << SECTOR_SHIFT) - (offset); - if (count < wdata->res.count) { - wdata->res.count = count; - } + wdata->res.count = wdata->args.count; out: bl_put_extent(be); + bl_put_extent(cow_read); bl_submit_bio(WRITE, bio); put_parallel(par); return PNFS_ATTEMPTED; out_mds: bl_put_extent(be); + bl_put_extent(cow_read); kfree(par); return PNFS_NOT_ATTEMPTED; } diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index 03350690118e23..39bb51a8dd1890 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h @@ -41,6 +41,7 @@ #define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT) #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT) +#define SECTOR_SIZE (1 << SECTOR_SHIFT) struct block_mount_id { spinlock_t bm_lock; /* protects list */ From 15adf810741b2e7c300932083d43b74188a05548 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 24 Aug 2012 00:27:49 +0800 Subject: [PATCH 0183/1071] NFS41: fix error of setting blocklayoutdriver commit dc182549d439f60c332bf74d7f220a1bccf37da6 upstream. After commit e38eb650 (NFS: set_pnfs_layoutdriver() from nfs4_proc_fsinfo()), set_pnfs_layoutdriver() is called inside nfs4_proc_fsinfo(), but pnfs_blksize is not set. It causes setting blocklayoutdriver failure and pnfsblock mount failure. Signed-off-by: Peng Tao Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/client.c | 1 - fs/nfs/nfs4proc.c | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 99694442b93f6d..0e7cd89562b213 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -855,7 +855,6 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, if (server->wsize > NFS_MAX_FILE_IO_SIZE) server->wsize = NFS_MAX_FILE_IO_SIZE; server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - server->pnfs_blksize = fsinfo->blksize; server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1e50326d00ddd1..1f0c4bf4de573e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3362,8 +3362,11 @@ static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, s nfs_fattr_init(fsinfo->fattr); error = nfs4_do_fsinfo(server, fhandle, fsinfo); - if (error == 0) + if (error == 0) { + /* block layout checks this! */ + server->pnfs_blksize = fsinfo->blksize; set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype); + } return error; } From 9fa2b82e5592a7aa7a63b7f6a32c5aa9e580643a Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Wed, 26 Sep 2012 15:25:52 -0400 Subject: [PATCH 0184/1071] NFS: Remove bad delegations during open recovery commit 6938867edba929a65a167a97581231e76aeb10b4 upstream. I put the client into an open recovery loop by: Client: Open file read half Server: Expire client (echo 0 > /sys/kernel/debug/nfsd/forget_clients) Client: Drop vm cache (echo 3 > /proc/sys/vm/drop_caches) finish reading file This causes a loop because the client never updates the nfs4_state after discovering that the delegation is invalid. This means it will keep trying to read using the bad delegation rather than attempting to re-open the file. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1f0c4bf4de573e..d5a0cf15d3cbde 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1774,7 +1774,11 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) * informs us the stateid is unrecognized. */ if (status != -NFS4ERR_BAD_STATEID) nfs41_free_stateid(server, stateid); + nfs_remove_bad_delegation(state->inode); + write_seqlock(&state->seqlock); + nfs4_stateid_copy(&state->stateid, &state->open_stateid); + write_sequnlock(&state->seqlock); clear_bit(NFS_DELEGATED_STATE, &state->flags); } } From 55db1c6363a84f7dcf9479ec791e390c0758aa05 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 21 Aug 2012 12:48:30 -0400 Subject: [PATCH 0185/1071] nfsd4: don't pin clientids to pseudoflavors commit 68eb35081e297b37db49d854cda144c6a3397699 upstream. I added cr_flavor to the data compared in same_creds without any justification, in d5497fc693a446ce9100fcf4117c3f795ddfd0d2 "nfsd4: move rq_flavor into svc_cred". Recent client changes then started making mount -osec=krb5 server:/export /mnt/ echo "hello" >/mnt/TMP umount /mnt/ mount -osec=krb5i server:/export /mnt/ echo "hello" >/mnt/TMP to fail due to a clid_inuse on the second open. Mounting sequentially like this with different flavors probably isn't that common outside artificial tests. Also, the real bug here may be that the server isn't just destroying the former clientid in this case (because it isn't good enough at recognizing when the old state is gone). But it prompted some discussion and a look back at the spec, and I think the check was probably wrong. Fix and document. Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4state.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index cc894eda385a48..8318cc61ce79ba 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1223,10 +1223,26 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2) return true; } +/* + * RFC 3530 language requires clid_inuse be returned when the + * "principal" associated with a requests differs from that previously + * used. We use uid, gid's, and gss principal string as our best + * approximation. We also don't want to allow non-gss use of a client + * established using gss: in theory cr_principal should catch that + * change, but in practice cr_principal can be null even in the gss case + * since gssd doesn't always pass down a principal string. + */ +static bool is_gss_cred(struct svc_cred *cr) +{ + /* Is cr_flavor one of the gss "pseudoflavors"?: */ + return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR); +} + + static bool same_creds(struct svc_cred *cr1, struct svc_cred *cr2) { - if ((cr1->cr_flavor != cr2->cr_flavor) + if ((is_gss_cred(cr1) != is_gss_cred(cr2)) || (cr1->cr_uid != cr2->cr_uid) || (cr1->cr_gid != cr2->cr_gid) || !groups_equal(cr1->cr_group_info, cr2->cr_group_info)) From 977469fff176739539ac78e2977d50214e2bdcf6 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 29 Aug 2012 15:21:58 -0700 Subject: [PATCH 0186/1071] nfsd4: fix nfs4 stateid leak commit cf9182e90b2af04245ac4fae497fe73fc71285b4 upstream. Processes that open and close multiple files may end up setting this oo_last_closed_stid without freeing what was previously pointed to. This can result in a major leak, visible for example by watching the nfsd4_stateids line of /proc/slabinfo. Reported-by: Cyril B. Tested-by: Cyril B. Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 8318cc61ce79ba..5b3224ce82eb5d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3782,6 +3782,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); nfsd4_close_open_stateid(stp); + release_last_closed_stateid(oo); oo->oo_last_closed_stid = stp; if (list_empty(&oo->oo_owner.so_stateids)) { From 13a34f1542a04f7165c1b41dd6faff85a9ebf061 Mon Sep 17 00:00:00 2001 From: Malahal Naineni Date: Sun, 9 Sep 2012 10:25:47 -0500 Subject: [PATCH 0187/1071] NFSD: pass null terminated buf to kstrtouint() commit 9959ba0c241a71c7ed8133401cfbbee2720da0b5 upstream. The 'buf' is prepared with null termination with intention of using it for this purpose, but 'name' is passed instead! Signed-off-by: Malahal Naineni Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index fdc91a6fc9c4e3..ccfe0d0e7228f8 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -598,7 +598,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel /* Just to make sure it's null-terminated: */ memcpy(buf, name, namelen); buf[namelen] = '\0'; - ret = kstrtouint(name, 10, id); + ret = kstrtouint(buf, 10, id); return ret == 0; } From 3a2ff25dc8d8e167fb3a09eea9cdb7426f6bb114 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 18 Sep 2012 13:37:12 +0400 Subject: [PATCH 0188/1071] lockd: per-net NSM client creation and destruction helpers introduced commit e9406db20fecbfcab646bad157b4cfdc7cadddfb upstream. NSM RPC client can be required on NFSv3 umount, when child reaper is dying (and destroying it's mount namespace). It means, that current nsproxy is set to NULL already, but creation of RPC client requires UTS namespace for gaining hostname string. This patch introduces reference counted NFS RPC clients creation and destruction helpers (similar to RPCBIND RPC clients). Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/lockd/mon.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-- fs/lockd/netns.h | 4 ++++ fs/lockd/svc.c | 1 + 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 7ef14b3c5bee94..38f240e104ce4f 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -19,6 +19,8 @@ #include +#include "netns.h" + #define NLMDBG_FACILITY NLMDBG_MONITOR #define NSM_PROGRAM 100024 #define NSM_VERSION 1 @@ -70,7 +72,7 @@ static struct rpc_clnt *nsm_create(struct net *net) }; struct rpc_create_args args = { .net = net, - .protocol = XPRT_TRANSPORT_UDP, + .protocol = XPRT_TRANSPORT_TCP, .address = (struct sockaddr *)&sin, .addrsize = sizeof(sin), .servername = "rpc.statd", @@ -83,6 +85,51 @@ static struct rpc_clnt *nsm_create(struct net *net) return rpc_create(&args); } +__maybe_unused static struct rpc_clnt *nsm_client_get(struct net *net) +{ + static DEFINE_MUTEX(nsm_create_mutex); + struct rpc_clnt *clnt; + struct lockd_net *ln = net_generic(net, lockd_net_id); + + spin_lock(&ln->nsm_clnt_lock); + if (ln->nsm_users) { + ln->nsm_users++; + clnt = ln->nsm_clnt; + spin_unlock(&ln->nsm_clnt_lock); + goto out; + } + spin_unlock(&ln->nsm_clnt_lock); + + mutex_lock(&nsm_create_mutex); + clnt = nsm_create(net); + if (!IS_ERR(clnt)) { + ln->nsm_clnt = clnt; + smp_wmb(); + ln->nsm_users = 1; + } + mutex_unlock(&nsm_create_mutex); +out: + return clnt; +} + +__maybe_unused static void nsm_client_put(struct net *net) +{ + struct lockd_net *ln = net_generic(net, lockd_net_id); + struct rpc_clnt *clnt = ln->nsm_clnt; + int shutdown = 0; + + spin_lock(&ln->nsm_clnt_lock); + if (ln->nsm_users) { + if (--ln->nsm_users) + ln->nsm_clnt = NULL; + shutdown = !ln->nsm_users; + } + spin_unlock(&ln->nsm_clnt_lock); + + if (shutdown) + rpc_shutdown_client(clnt); +} + static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, struct net *net) { @@ -111,7 +158,7 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, memset(res, 0, sizeof(*res)); msg.rpc_proc = &clnt->cl_procinfo[proc]; - status = rpc_call_sync(clnt, &msg, 0); + status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN); if (status < 0) dprintk("lockd: NSM upcall RPC failed, status=%d\n", status); diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h index 4eee248ba96e44..5010b55628b475 100644 --- a/fs/lockd/netns.h +++ b/fs/lockd/netns.h @@ -12,6 +12,10 @@ struct lockd_net { struct delayed_work grace_period_end; struct lock_manager lockd_manager; struct list_head grace_list; + + spinlock_t nsm_clnt_lock; + unsigned int nsm_users; + struct rpc_clnt *nsm_clnt; }; extern int lockd_net_id; diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 31a63f87b80602..7e355870d5190b 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -596,6 +596,7 @@ static int lockd_init_net(struct net *net) INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender); INIT_LIST_HEAD(&ln->grace_list); + spin_lock_init(&ln->nsm_clnt_lock); return 0; } From 66fad5377c6b06e24512035bb81095dc4787bc02 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 18 Sep 2012 13:37:18 +0400 Subject: [PATCH 0189/1071] lockd: use rpc client's cl_nodename for id encoding commit 303a7ce92064c285a04c870f2dc0192fdb2968cb upstream. Taking hostname from uts namespace if not safe, because this cuold be performind during umount operation on child reaper death. And in this case current->nsproxy is NULL already. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/lockd/mon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 38f240e104ce4f..e0bc36e74ceb6f 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -42,6 +42,7 @@ struct nsm_args { u32 proc; char *mon_name; + char *nodename; }; struct nsm_res { @@ -141,6 +142,7 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, .vers = 3, .proc = NLMPROC_NSM_NOTIFY, .mon_name = nsm->sm_mon_name, + .nodename = utsname()->nodename, }; struct rpc_message msg = { .rpc_argp = &args, @@ -477,7 +479,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp) { __be32 *p; - encode_nsm_string(xdr, utsname()->nodename); + encode_nsm_string(xdr, argp->nodename); p = xdr_reserve_space(xdr, 4 + 4 + 4); *p++ = cpu_to_be32(argp->prog); *p++ = cpu_to_be32(argp->vers); From 4f7ae03ec5e40b8755a1ea3080cf1bca388d4ded Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 18 Sep 2012 13:37:23 +0400 Subject: [PATCH 0190/1071] lockd: create and use per-net NSM RPC clients on MON/UNMON requests commit cb7323fffa85df37161f4d3be45e1f787808309c upstream. NSM RPC client can be required on NFSv3 umount, when child reaper is dying (and destroying it's mount namespace). It means, that current nsproxy is set to NULL already, but creation of RPC client requires UTS namespace for gaining hostname string. This patch creates reference-counted per-net NSM client on first monitor request and destroys it after last unmonitor request. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/lockd/mon.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index e0bc36e74ceb6f..e4fb3ba5a58a3d 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -86,7 +85,7 @@ static struct rpc_clnt *nsm_create(struct net *net) return rpc_create(&args); } -__maybe_unused static struct rpc_clnt *nsm_client_get(struct net *net) +static struct rpc_clnt *nsm_client_get(struct net *net) { static DEFINE_MUTEX(nsm_create_mutex); struct rpc_clnt *clnt; @@ -113,7 +112,7 @@ __maybe_unused static struct rpc_clnt *nsm_client_get(struct net *net) return clnt; } -__maybe_unused static void nsm_client_put(struct net *net) +static void nsm_client_put(struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); struct rpc_clnt *clnt = ln->nsm_clnt; @@ -132,9 +131,8 @@ __maybe_unused static void nsm_client_put(struct net *net) } static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, - struct net *net) + struct rpc_clnt *clnt) { - struct rpc_clnt *clnt; int status; struct nsm_args args = { .priv = &nsm->sm_priv, @@ -142,20 +140,14 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, .vers = 3, .proc = NLMPROC_NSM_NOTIFY, .mon_name = nsm->sm_mon_name, - .nodename = utsname()->nodename, + .nodename = clnt->cl_nodename, }; struct rpc_message msg = { .rpc_argp = &args, .rpc_resp = res, }; - clnt = nsm_create(net); - if (IS_ERR(clnt)) { - status = PTR_ERR(clnt); - dprintk("lockd: failed to create NSM upcall transport, " - "status=%d\n", status); - goto out; - } + BUG_ON(clnt == NULL); memset(res, 0, sizeof(*res)); @@ -166,8 +158,6 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, status); else status = 0; - rpc_shutdown_client(clnt); - out: return status; } @@ -187,6 +177,7 @@ int nsm_monitor(const struct nlm_host *host) struct nsm_handle *nsm = host->h_nsmhandle; struct nsm_res res; int status; + struct rpc_clnt *clnt; dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); @@ -199,7 +190,15 @@ int nsm_monitor(const struct nlm_host *host) */ nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; - status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net); + clnt = nsm_client_get(host->net); + if (IS_ERR(clnt)) { + status = PTR_ERR(clnt); + dprintk("lockd: failed to create NSM upcall transport, " + "status=%d, net=%p\n", status, host->net); + return status; + } + + status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt); if (unlikely(res.status != 0)) status = -EIO; if (unlikely(status < 0)) { @@ -231,9 +230,11 @@ void nsm_unmonitor(const struct nlm_host *host) if (atomic_read(&nsm->sm_count) == 1 && nsm->sm_monitored && !nsm->sm_sticky) { + struct lockd_net *ln = net_generic(host->net, lockd_net_id); + dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); - status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net); + status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt); if (res.status != 0) status = -EIO; if (status < 0) @@ -241,6 +242,8 @@ void nsm_unmonitor(const struct nlm_host *host) nsm->sm_name); else nsm->sm_monitored = 0; + + nsm_client_put(host->net); } } From 0bde288a5df7e108b40a4aa615c80652299a7f00 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Fri, 28 Sep 2012 15:22:00 +0800 Subject: [PATCH 0191/1071] ACPI: EC: Make the GPE storm threshold a module parameter commit a520d52e99b14ba7db135e916348f12f2a6e09be upstream. The Linux EC driver includes a mechanism to detect GPE storms, and switch from interrupt-mode to polling mode. However, polling mode sometimes doesn't work, so the workaround is problematic. Also, different systems seem to need the threshold for detecting the GPE storm at different levels. ACPI_EC_STORM_THRESHOLD was initially 20 when it's created, and was changed to 8 in 2.6.28 commit 06cf7d3c7 "ACPI: EC: lower interrupt storm threshold" to fix kernel bug 11892 by forcing the laptop in that bug to work in polling mode. However in bug 45151, it works fine in interrupt mode if we lift the threshold back to 20. This patch makes the threshold a module parameter so that user has a flexible option to debug/workaround this issue. The default is unchanged. This is also a preparation patch to fix specific systems: https://bugzilla.kernel.org/show_bug.cgi?id=45151 Signed-off-by: Feng Tang Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7edaccce66402b..615264c89c3151 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -71,9 +71,6 @@ enum ec_command { #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ -#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts - per one transaction */ - enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_STORM, /* GPE storm detected */ @@ -87,6 +84,15 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; module_param(ec_delay, uint, 0644); MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); +/* + * If the number of false interrupts per one transaction exceeds + * this threshold, will think there is a GPE storm happened and + * will disable the GPE for normal transaction. + */ +static unsigned int ec_storm_threshold __read_mostly = 8; +module_param(ec_storm_threshold, uint, 0644); +MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); + /* If we find an EC via the ECDT, we need to keep a ptr to its context */ /* External interfaces use first EC only, so remember */ typedef int (*acpi_ec_query_func) (void *data); @@ -319,7 +325,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) msleep(1); /* It is safe to enable the GPE outside of the transaction. */ acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + } else if (t->irq_count > ec_storm_threshold) { pr_info(PREFIX "GPE storm detected, " "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); From c347faa6f02f368679661b4fe475625c58a077d7 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Fri, 28 Sep 2012 15:22:01 +0800 Subject: [PATCH 0192/1071] ACPI: EC: Add a quirk for CLEVO M720T/M730T laptop commit 67bfa9b60bd689601554526d144b21d529f78a09 upstream. By enlarging the GPE storm threshold back to 20, that laptop's EC works fine with interrupt mode instead of polling mode. https://bugzilla.kernel.org/show_bug.cgi?id=45151 Reported-and-Tested-by: Francesco Signed-off-by: Feng Tang Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 615264c89c3151..a51df968131989 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -930,6 +930,17 @@ static int ec_flag_msi(const struct dmi_system_id *id) return 0; } +/* + * Clevo M720 notebook actually works ok with IRQ mode, if we lifted + * the GPE storm threshold back to 20 + */ +static int ec_enlarge_storm_threshold(const struct dmi_system_id *id) +{ + pr_debug("Setting the EC GPE storm threshold to 20\n"); + ec_storm_threshold = 20; + return 0; +} + static struct dmi_system_id __initdata ec_dmi_table[] = { { ec_skip_dsdt_scan, "Compal JFL92", { @@ -961,10 +972,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL}, + { + ec_enlarge_storm_threshold, "CLEVO hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."), + DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL}, {}, }; - int __init acpi_ec_ecdt_probe(void) { acpi_status status; From ad505f023d46dd51a3c5344e395b703ede9cd0a4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Oct 2012 08:41:42 +0200 Subject: [PATCH 0193/1071] ALSA: hda - Add missing hda_gen_spec to struct via_spec commit 7819d1c70eb6a57e43554d86e10b39d1e106ed65 upstream. The commit [4b527b65 ALSA: hda - limit internal mic boost for Asus X202E] introduced the use of auto-parser code, but it forgot to add struct hda_gen_spec at the head of codec->spec which the auto-parser assumes silently. Without this record, it may result in memory corruption. This patch adds the missing piece. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 4b4072fcec517e..4c404a0c644046 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -118,6 +118,8 @@ enum { }; struct via_spec { + struct hda_gen_spec gen; + /* codec parameterization */ const struct snd_kcontrol_new *mixers[6]; unsigned int num_mixers; @@ -246,6 +248,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec) /* VT1708BCE & VT1708S are almost same */ if (spec->codec_type == VT1708BCE) spec->codec_type = VT1708S; + snd_hda_gen_init(&spec->gen); return spec; } @@ -1628,6 +1631,7 @@ static void via_free(struct hda_codec *codec) vt1708_stop_hp_work(spec); kfree(spec->bind_cap_vol); kfree(spec->bind_cap_sw); + snd_hda_gen_free(&spec->gen); kfree(spec); } From 1cddab0141470e2661d87625580206f24804badd Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 10 Oct 2012 16:32:09 +0200 Subject: [PATCH 0194/1071] ALSA: hda - do not detect jack on internal speakers for Realtek commit f7f4b2322bf7b8c5929b7eb5a667091f32592580 upstream. This caused the internal speaker to mute itself because it was present, which happened after powersave. It was found on Dell XPS 15 (L502x), ALC665. Reported-by: Da Fox Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 56a3eefd3033ed..b5d7850c3846b9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -611,6 +611,8 @@ static void alc_line_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) + return; /* check LO jack only when it's different from HP */ if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0]) return; From 725b68f854c09d84dea31e896ebd56ef61157ae6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Oct 2012 08:50:35 +0200 Subject: [PATCH 0195/1071] ALSA: hda - Fix memory leaks at error path in patch_cirrus.c commit c5e0b6dbad9b4d18c561af90b384d02373f1c994 upstream. The proper destructor should be called at the error path. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 0c4c1a61b3789f..cc31346ce9b443 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1417,7 +1417,7 @@ static int patch_cs420x(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -1974,7 +1974,7 @@ static int patch_cs4210(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -1999,7 +1999,7 @@ static int patch_cs4213(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } From 5224f4e0e077c6c6336dc9640c81ea9799e620a6 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 10 Aug 2012 12:21:15 -0500 Subject: [PATCH 0196/1071] mips,kgdb: fix recursive page fault with CONFIG_KPROBES commit f0a996eeeda214f4293e234df33b29bec003b536 upstream. This fault was detected using the kgdb test suite on boot and it crashes recursively due to the fact that CONFIG_KPROBES on mips adds an extra die notifier in the page fault handler. The crash signature looks like this: kgdbts:RUN bad memory access test KGDB: re-enter exception: ALL breakpoints killed Call Trace: [<807b7548>] dump_stack+0x20/0x54 [<807b7548>] dump_stack+0x20/0x54 The fix for now is to have kgdb return immediately if the fault type is DIE_PAGE_FAULT and allow the kprobe code to decide what is supposed to happen. Signed-off-by: Jason Wessel Cc: Masami Hiramatsu Cc: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/kgdb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index f4546e97c60db1..23817a6e32b606 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, struct pt_regs *regs = args->regs; int trap = (regs->cp0_cause & 0x7c) >> 2; +#ifdef CONFIG_KPROBES + /* + * Return immediately if the kprobes fault notifier has set + * DIE_PAGE_FAULT. + */ + if (cmd == DIE_PAGE_FAULT) + return NOTIFY_DONE; +#endif /* CONFIG_KPROBES */ + /* Userspace events, ignore. */ if (user_mode(regs)) return NOTIFY_DONE; From b080b7e727de8abc0c883de3d6a85a7ac3da31a5 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sun, 7 Oct 2012 20:32:51 -0700 Subject: [PATCH 0197/1071] tmpfs,ceph,gfs2,isofs,reiserfs,xfs: fix fh_len checking commit 35c2a7f4908d404c9124c2efc6ada4640ca4d5d5 upstream. Fuzzing with trinity oopsed on the 1st instruction of shmem_fh_to_dentry(), u64 inum = fid->raw[2]; which is unhelpfully reported as at the end of shmem_alloc_inode(): BUG: unable to handle kernel paging request at ffff880061cd3000 IP: [] shmem_alloc_inode+0x40/0x40 Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC Call Trace: [] ? exportfs_decode_fh+0x79/0x2d0 [] do_handle_open+0x163/0x2c0 [] sys_open_by_handle_at+0xc/0x10 [] tracesys+0xe1/0xe6 Right, tmpfs is being stupid to access fid->raw[2] before validating that fh_len includes it: the buffer kmalloc'ed by do_sys_name_to_handle() may fall at the end of a page, and the next page not be present. But some other filesystems (ceph, gfs2, isofs, reiserfs, xfs) are being careless about fh_len too, in fh_to_dentry() and/or fh_to_parent(), and could oops in the same way: add the missing fh_len checks to those. Reported-by: Sasha Levin Signed-off-by: Hugh Dickins Cc: Al Viro Cc: Sage Weil Cc: Steven Whitehouse Cc: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/ceph/export.c | 18 ++++++++++++++---- fs/gfs2/export.c | 4 ++++ fs/isofs/export.c | 2 +- fs/reiserfs/inode.c | 6 +++++- fs/xfs/xfs_export.c | 3 +++ mm/shmem.c | 6 ++++-- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 8e1b60e557b65b..02ce90972d81ca 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -99,7 +99,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, * FIXME: we should try harder by querying the mds for the ino. */ static struct dentry *__fh_to_dentry(struct super_block *sb, - struct ceph_nfs_fh *fh) + struct ceph_nfs_fh *fh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; @@ -107,6 +107,9 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, struct ceph_vino vino; int err; + if (fh_len < sizeof(*fh) / 4) + return ERR_PTR(-ESTALE); + dout("__fh_to_dentry %llx\n", fh->ino); vino.ino = fh->ino; vino.snap = CEPH_NOSNAP; @@ -150,7 +153,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, * convert connectable fh to dentry */ static struct dentry *__cfh_to_dentry(struct super_block *sb, - struct ceph_nfs_confh *cfh) + struct ceph_nfs_confh *cfh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; @@ -158,6 +161,9 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb, struct ceph_vino vino; int err; + if (fh_len < sizeof(*cfh) / 4) + return ERR_PTR(-ESTALE); + dout("__cfh_to_dentry %llx (%llx/%x)\n", cfh->ino, cfh->parent_ino, cfh->parent_name_hash); @@ -207,9 +213,11 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { if (fh_type == 1) - return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw); + return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw, + fh_len); else - return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw); + return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw, + fh_len); } /* @@ -230,6 +238,8 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, if (fh_type == 1) return ERR_PTR(-ESTALE); + if (fh_len < sizeof(*cfh) / 4) + return ERR_PTR(-ESTALE); pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino, cfh->parent_name_hash); diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index e8ed6d4a618113..4767774a5f3e7d 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c @@ -161,6 +161,8 @@ static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, case GFS2_SMALL_FH_SIZE: case GFS2_LARGE_FH_SIZE: case GFS2_OLD_FH_SIZE: + if (fh_len < GFS2_SMALL_FH_SIZE) + return NULL; this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; this.no_formal_ino |= be32_to_cpu(fh[1]); this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; @@ -180,6 +182,8 @@ static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, switch (fh_type) { case GFS2_LARGE_FH_SIZE: case GFS2_OLD_FH_SIZE: + if (fh_len < GFS2_LARGE_FH_SIZE) + return NULL; parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; parent.no_formal_ino |= be32_to_cpu(fh[5]); parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 1d3804492aa77d..2b4f2358eadbb0 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -175,7 +175,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb, { struct isofs_fid *ifid = (struct isofs_fid *)fid; - if (fh_type != 2) + if (fh_len < 2 || fh_type != 2) return NULL; return isofs_export_iget(sb, diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 855da58db1456b..63ce6be94c4ad7 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1573,8 +1573,10 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, reiserfs_warning(sb, "reiserfs-13077", "nfsd/reiserfs, fhtype=%d, len=%d - odd", fh_type, fh_len); - fh_type = 5; + fh_type = fh_len; } + if (fh_len < 2) + return NULL; return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); @@ -1583,6 +1585,8 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { + if (fh_type > fh_len) + fh_type = fh_len; if (fh_type < 4) return NULL; diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 42679223a0fde6..8c6d1d70278cc6 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -189,6 +189,9 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; struct inode *inode = NULL; + if (fh_len < xfs_fileid_length(fileid_type)) + return NULL; + switch (fileid_type) { case FILEID_INO32_GEN_PARENT: inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, diff --git a/mm/shmem.c b/mm/shmem.c index d4e184e2a38ea5..d2eeca18e2cfdc 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2366,12 +2366,14 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb, { struct inode *inode; struct dentry *dentry = NULL; - u64 inum = fid->raw[2]; - inum = (inum << 32) | fid->raw[1]; + u64 inum; if (fh_len < 3) return NULL; + inum = fid->raw[2]; + inum = (inum << 32) | fid->raw[1]; + inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]), shmem_match, fid->raw); if (inode) { From 6386543caae11034a29c2af89793a076745c0eb4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 22 Sep 2012 17:21:06 -0700 Subject: [PATCH 0198/1071] iscsi-target: Correctly set 0xffffffff field within ISCSI_OP_REJECT PDU commit f25590f39d543272f7ae7b00d533359c8d7ff331 upstream. This patch adds a missing iscsi_reject->ffffffff assignment within iscsit_send_reject() code to properly follow RFC-3720 Section 10.17 Bytes 16 -> 19 for the PDU format definition of ISCSI_OP_REJECT. We've not seen any initiators care about this bytes in practice, but as Ronnie reported this was causing trouble with wireshark packet decoding lets go ahead and fix this up now. Reported-by: Ronnie Sahlberg Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 97c0f78c3c9ca8..68ca17d04ab19a 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3424,6 +3424,7 @@ static int iscsit_send_reject( hdr->opcode = ISCSI_OP_REJECT; hdr->flags |= ISCSI_FLAG_CMD_FINAL; hton24(hdr->dlength, ISCSI_HDR_LEN); + hdr->ffffffff = 0xffffffff; cmd->stat_sn = conn->stat_sn++; hdr->statsn = cpu_to_be32(cmd->stat_sn); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); From 521af6701599c0e9aea335228675f07ea65fd0d4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 26 Sep 2012 08:00:37 -0400 Subject: [PATCH 0199/1071] iscsit: remove incorrect unlock in iscsit_build_sendtargets_resp commit 904753da183566c71211d23c169a80184648c121 upstream. Fix a potential multiple spin-unlock -> deadlock scenario during the overflow check within iscsit_build_sendtargets_resp() as found by sparse static checking. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 68ca17d04ab19a..dd4fce20ea886c 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3271,7 +3271,6 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) len += 1; if ((len + payload_len) > buffer_len) { - spin_unlock(&tiqn->tiqn_tpg_lock); end_of_buf = 1; goto eob; } From 331ddcc26a40ba6313c66b29a4305dbbfabb9f87 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 30 Sep 2012 12:20:02 -0700 Subject: [PATCH 0200/1071] iscsi-target: Add explicit set of cache_dynamic_acls=1 for TPG demo-mode commit 38b11bae6ba02da352340aff12ee25755977b222 upstream. We've had reports in the past about this specific case, so it's time to go ahead and explicitly set cache_dynamic_acls=1 for generate_node_acls=1 (TPG demo-mode) operation. During normal generate_node_acls=0 operation with explicit NodeACLs -> se_node_acl memory is persistent to the configfs group located at /sys/kernel/config/target/$TARGETNAME/$TPGT/acls/$INITIATORNAME, so in the generate_node_acls=1 case we want the reservation logic to reference existing per initiator IQN se_node_acl memory (not to generate a new se_node_acl), so go ahead and always set cache_dynamic_acls=1 when TPG demo-mode is enabled. Reported-by: Ronnie Sahlberg Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target_tpg.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index a38a3f8ab0d923..de9ea32b610462 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -677,6 +677,12 @@ int iscsit_ta_generate_node_acls( pr_debug("iSCSI_TPG[%hu] - Generate Initiator Portal Group ACLs: %s\n", tpg->tpgt, (a->generate_node_acls) ? "Enabled" : "Disabled"); + if (flag == 1 && a->cache_dynamic_acls == 0) { + pr_debug("Explicitly setting cache_dynamic_acls=1 when " + "generate_node_acls=1\n"); + a->cache_dynamic_acls = 1; + } + return 0; } @@ -716,6 +722,12 @@ int iscsit_ta_cache_dynamic_acls( return -EINVAL; } + if (a->generate_node_acls == 1 && flag == 0) { + pr_debug("Skipping cache_dynamic_acls=0 when" + " generate_node_acls=1\n"); + return 0; + } + a->cache_dynamic_acls = flag; pr_debug("iSCSI_TPG[%hu] - Cache Dynamic Initiator Portal Group" " ACLs %s\n", tpg->tpgt, (a->cache_dynamic_acls) ? From 12fe0605dcdf67072d37be195938c3c0d90bb3c6 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 3 Oct 2012 15:42:48 -0700 Subject: [PATCH 0201/1071] iscsi-target: Bump defaults for nopin_timeout + nopin_response_timeout values commit cf0eb28d3ba60098865bf7dbcbfdd6b1cc483e3b upstream. This patch increases the default for nopin_timeout to 15 seconds (wait between sending a new NopIN ping) and nopin_response_timeout to 30 seconds (wait for NopOUT response before failing the connection) in order to avoid false positives by iSCSI Initiators who are not always able (under load) to respond to NopIN echo PING requests within the current 5 second window. False positives have been observed recently using Open-iSCSI code on v3.3.x with heavy large-block READ workloads over small MTU 1 Gb/sec ports, and increasing these values to more reasonable defaults significantly reduces the possibility of false positive NopIN response timeout events under this specific workload. Historically these have been set low to initiate connection recovery as soon as possible if we don't hear a ping back, but for modern v3.x code on 1 -> 10 Gb/sec ports these new defaults make alot more sense. Signed-off-by: Nicholas Bellinger Cc: Christoph Hellwig Cc: Andy Grover Cc: Mike Christie Cc: Hannes Reinecke Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 8a908b28d8b2b1..a90294f8498cc3 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -25,10 +25,10 @@ #define NA_DATAOUT_TIMEOUT_RETRIES 5 #define NA_DATAOUT_TIMEOUT_RETRIES_MAX 15 #define NA_DATAOUT_TIMEOUT_RETRIES_MIN 1 -#define NA_NOPIN_TIMEOUT 5 +#define NA_NOPIN_TIMEOUT 15 #define NA_NOPIN_TIMEOUT_MAX 60 #define NA_NOPIN_TIMEOUT_MIN 3 -#define NA_NOPIN_RESPONSE_TIMEOUT 5 +#define NA_NOPIN_RESPONSE_TIMEOUT 30 #define NA_NOPIN_RESPONSE_TIMEOUT_MAX 60 #define NA_NOPIN_RESPONSE_TIMEOUT_MIN 3 #define NA_RANDOM_DATAIN_PDU_OFFSETS 0 From 54acbe4085b9c629e0164c90211d55e54e0ec6c0 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 2 Oct 2012 11:03:31 -0700 Subject: [PATCH 0202/1071] SCSI: storvsc: Account for in-transit packets in the RESET path commit 5c1b10ab7f93d24f29b5630286e323d1c5802d5c upstream. Properly account for I/O in transit before returning from the RESET call. In the absense of this patch, we could have a situation where the host may respond to a command that was issued prior to the issuance of the RESET command at some arbitrary time after responding to the RESET command. Currently, the host does not do anything with the RESET command. Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/storvsc_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 528d52beaa1ca6..01440782feb205 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1221,7 +1221,12 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) /* * At this point, all outstanding requests in the adapter * should have been flushed out and return to us + * There is a potential race here where the host may be in + * the process of responding when we return from here. + * Just wait for all in-transit packets to be accounted for + * before we return from here. */ + storvsc_wait_to_drain(stor_device); return SUCCESS; } From 22273f50017471428d85e3e6c6d04020fcaec97d Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Thu, 16 Aug 2012 16:38:45 +0200 Subject: [PATCH 0203/1071] SCSI: scsi_debug: Fix off-by-one bug when unmapping region commit bc977749e967daa56de1922cf4cb38525631c51c upstream. Currently it is possible to unmap one more block than user requested to due to the off-by-one error in unmap_region(). This is probably due to the fact that the end variable despite its name actually points to the last block to unmap + 1. However in the condition it is handled as the last block of the region to unmap. The bug was not previously spotted probably due to the fact that the region was not zeroed, which has changed with commit be1dd78de5686c062bb3103f9e86d444a10ed783. With that commit we were able to corrupt the ext4 file system on 256M scsi_debug device with LBPRZ enabled using fstrim. Since the 'end' semantic is the same in several functions there this commit just fixes the condition to use the 'end' variable correctly in that context. Reported-by: Paolo Bonzini Signed-off-by: Lukas Czerner Reviewed-by: Martin K. Petersen Acked-by: Douglas Gilbert Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 182d5a57ab7468..f4cc4139ada8aa 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2054,7 +2054,7 @@ static void unmap_region(sector_t lba, unsigned int len) block = lba + alignment; rem = do_div(block, granularity); - if (rem == 0 && lba + granularity <= end && block < map_size) { + if (rem == 0 && lba + granularity < end && block < map_size) { clear_bit(block, map_storep); if (scsi_debug_lbprz) memset(fake_storep + From 6eac60584d2030cc4d47ef3fc2738012416d8c4f Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 2 Oct 2012 17:25:46 +0200 Subject: [PATCH 0204/1071] SCSI: virtio-scsi: initialize scatterlist structure commit 2e9c9dfde00a6466441e93033cf2c37f720bdacf upstream. The sg struct is used without being initialized, which breaks when CONFIG_DEBUG_SG is enabled. Signed-off-by: Richard W.M. Jones Signed-off-by: Paolo Bonzini Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/virtio_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 3e79a2f0004279..7554d78564348c 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -219,7 +219,7 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi, struct scatterlist sg; unsigned long flags; - sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); + sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); From 9d03830aa8319e80d33e021f6a3f8ffe1adbe780 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 28 Sep 2012 02:12:45 +0100 Subject: [PATCH 0205/1071] ARM: 7541/1: Add ARM ERRATA 775420 workaround commit 7253b85cc62d6ff84143d96fe6cd54f73736f4d7 upstream. arm: Add ARM ERRATA 775420 workaround Workaround for the 775420 Cortex-A9 (r2p2, r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance operation aborts with MMU exception, it might cause the processor to deadlock. This workaround puts DSB before executing ISB if an abort may occur on cache maintenance. Based on work by Kouei Abe and feedback from Catalin Marinas. Signed-off-by: Kouei Abe [ horms@verge.net.au: Changed to implementation suggested by catalin.marinas@arm.com ] Acked-by: Catalin Marinas Signed-off-by: Simon Horman Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 10 ++++++++++ arch/arm/mm/cache-v7.S | 3 +++ 2 files changed, 13 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2f88d8d9770116..48c19d44be9a4a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1413,6 +1413,16 @@ config PL310_ERRATA_769419 on systems with an outer cache, the store buffer is drained explicitly. +config ARM_ERRATA_775420 + bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock" + depends on CPU_V7 + help + This option enables the workaround for the 775420 Cortex-A9 (r2p2, + r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance + operation aborts with MMU exception, it might cause the processor + to deadlock. This workaround puts DSB before executing ISB if + an abort may occur on cache maintenance. + endmenu source "arch/arm/common/Kconfig" diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 39e3fb3db80123..3b172275262e2c 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -211,6 +211,9 @@ ENTRY(v7_coherent_user_range) * isn't mapped, fail with -EFAULT. */ 9001: +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif mov r0, #-EFAULT mov pc, lr UNWIND(.fnend ) From d16325665f213bfb893c978f54d43b142a0daecd Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 8 Oct 2012 14:01:12 -0700 Subject: [PATCH 0206/1071] ARM: OMAP: counter: add locking to read_persistent_clock commit 9d7d6e363b06934221b81a859d509844c97380df upstream. read_persistent_clock uses a global variable, use a spinlock to ensure non-atomic updates to the variable don't overlap and cause time to move backwards. Signed-off-by: Colin Cross Signed-off-by: R Sricharan Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/counter_32k.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index dbf1e03029a570..2bc51fb1f7177d 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -55,22 +55,29 @@ static u32 notrace omap_32k_read_sched_clock(void) * nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles; static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK(read_persistent_clock_lock); + static void omap_read_persistent_clock(struct timespec *ts) { unsigned long long nsecs; - cycles_t delta; - struct timespec *tsp = &persistent_ts; + cycles_t last_cycles; + unsigned long flags; + + spin_lock_irqsave(&read_persistent_clock_lock, flags); last_cycles = cycles; cycles = sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0; - delta = cycles - last_cycles; - nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift); + nsecs = clocksource_cyc2ns(cycles - last_cycles, + persistent_mult, persistent_shift); + + timespec_add_ns(&persistent_ts, nsecs); + + *ts = persistent_ts; - timespec_add_ns(tsp, nsecs); - *ts = *tsp; + spin_unlock_irqrestore(&read_persistent_clock_lock, flags); } /** From eba428c5ad1614ae139610d3becb504ce2637187 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 6 Oct 2012 14:12:56 +0200 Subject: [PATCH 0207/1071] firewire: cdev: fix user memory corruption (i386 userland on amd64 kernel) commit 790198f74c9d1b46b6a89504361b1a844670d050 upstream. Fix two bugs of the /dev/fw* character device concerning the FW_CDEV_IOC_GET_INFO ioctl with nonzero fw_cdev_get_info.bus_reset. (Practically all /dev/fw* clients issue this ioctl right after opening the device.) Both bugs are caused by sizeof(struct fw_cdev_event_bus_reset) being 36 without natural alignment and 40 with natural alignment. 1) Memory corruption, affecting i386 userland on amd64 kernel: Userland reserves a 36 bytes large buffer, kernel writes 40 bytes. This has been first found and reported against libraw1394 if compiled with gcc 4.7 which happens to order libraw1394's stack such that the bug became visible as data corruption. 2) Information leak, affecting all kernel architectures except i386: 4 bytes of random kernel stack data were leaked to userspace. Hence limit the respective copy_to_user() to the 32-bit aligned size of struct fw_cdev_event_bus_reset. Reported-by: Simon Kirby Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/core-cdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2783f69dada644..f8d22872d75324 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -473,8 +473,8 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) client->bus_reset_closure = a->bus_reset_closure; if (a->bus_reset != 0) { fill_bus_reset_event(&bus_reset, client); - ret = copy_to_user(u64_to_uptr(a->bus_reset), - &bus_reset, sizeof(bus_reset)); + /* unaligned size of bus_reset is 36 bytes */ + ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36); } if (ret == 0 && list_empty(&client->link)) list_add_tail(&client->link, &client->device->client_list); From 6324a752e0113df97f8a59902fcb22c38eede27f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 12 Sep 2012 16:49:15 -0400 Subject: [PATCH 0208/1071] SUNRPC: Ensure that the TCP socket is closed when in CLOSE_WAIT commit a519fc7a70d1a918574bb826cc6905b87b482eb9 upstream. Instead of doing a shutdown() call, we need to do an actual close(). Ditto if/when the server is sending us junk RPC headers. Signed-off-by: Trond Myklebust Tested-by: Simon Kirby Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index a35b8e52e551d4..d1988cf8bf3322 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1025,6 +1025,16 @@ static void xs_udp_data_ready(struct sock *sk, int len) read_unlock_bh(&sk->sk_callback_lock); } +/* + * Helper function to force a TCP close if the server is sending + * junk and/or it has put us in CLOSE_WAIT + */ +static void xs_tcp_force_close(struct rpc_xprt *xprt) +{ + set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); + xprt_force_disconnect(xprt); +} + static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) { struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); @@ -1051,7 +1061,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea /* Sanity check of the record length */ if (unlikely(transport->tcp_reclen < 8)) { dprintk("RPC: invalid TCP record fragment length\n"); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); return; } dprintk("RPC: reading TCP record fragment of length %d\n", @@ -1132,7 +1142,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, break; default: dprintk("RPC: invalid request message type\n"); - xprt_force_disconnect(&transport->xprt); + xs_tcp_force_close(&transport->xprt); } xs_tcp_check_fraghdr(transport); } @@ -1455,6 +1465,8 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) static void xs_sock_mark_closed(struct rpc_xprt *xprt) { smp_mb__before_clear_bit(); + clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); + clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); @@ -1512,8 +1524,8 @@ static void xs_tcp_state_change(struct sock *sk) break; case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ - xprt_force_disconnect(xprt); xprt->connect_cookie++; + xs_tcp_force_close(xprt); case TCP_CLOSING: /* * If the server closed down the connection, make sure that @@ -2199,8 +2211,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) /* We're probably in TIME_WAIT. Get rid of existing socket, * and retry */ - set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); break; case -ECONNREFUSED: case -ECONNRESET: From ac71b560d2d821de7f623fc9d1831981433a9ff3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:38 +0200 Subject: [PATCH 0209/1071] target: support zero allocation length in INQUIRY commit ffe7b0e9326d9c68f5688bef691dd49f1e0d3651 upstream. INQUIRY processing already uses an on-heap bounce buffer for loopback, but not for other fabrics. Switch this to a cheaper on-stack bounce buffer, similar to the one used by MODE SENSE and REQUEST SENSE, and use it unconditionally. With this in place, zero allocation length is handled simply by checking the return address of transport_kmap_data_sg. Testcase: sg_raw /dev/sdb 12 00 83 00 00 00 should fail with ILLEGAL REQUEST / INVALID FIELD IN CDB sense does not fail without the patch fails correctly with the series Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_spc.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 388a922c8f6de8..b3d8fd260374f5 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -600,30 +600,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; - unsigned char *buf, *map_buf; + unsigned char *rbuf; unsigned char *cdb = cmd->t_task_cdb; + unsigned char buf[SE_INQUIRY_BUF]; int p, ret; - map_buf = transport_kmap_data_sg(cmd); - /* - * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we - * know we actually allocated a full page. Otherwise, if the - * data buffer is too small, allocate a temporary buffer so we - * don't have to worry about overruns in all our INQUIRY - * emulation handling. - */ - if (cmd->data_length < SE_INQUIRY_BUF && - (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { - buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); - if (!buf) { - transport_kunmap_data_sg(cmd); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; - } - } else { - buf = map_buf; - } - if (dev == tpg->tpg_virt_lun0.lun_se_dev) buf[0] = 0x3f; /* Not connected */ else @@ -655,11 +636,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) ret = -EINVAL; out: - if (buf != map_buf) { - memcpy(map_buf, buf, cmd->data_length); - kfree(buf); + rbuf = transport_kmap_data_sg(cmd); + if (rbuf) { + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); } - transport_kunmap_data_sg(cmd); if (!ret) target_complete_cmd(cmd, GOOD); From d53872319140a8b04b5a20a71d63004fa15f7534 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:39 +0200 Subject: [PATCH 0210/1071] target: fix truncation of mode data, support zero allocation length commit 7a3f369ce31694017996524a1cdb08208a839077 upstream. The offset was not bumped back to the full size after writing the header of the MODE SENSE response, so the last 1 or 2 bytes were not copied. On top of this, support zero-length requests by checking for the return value of transport_kmap_data_sg. Testcase: sg_raw -r20 /dev/sdb 5a 00 0a 00 00 00 00 00 14 00 last byte should be 0x1e it is 0x00 without the patch it is correct with the patch Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_spc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index b3d8fd260374f5..9229bd9ad61b3d 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -784,7 +784,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd) unsigned char *rbuf; int type = dev->transport->get_device_type(dev); int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); - int offset = ten ? 8 : 4; + u32 offset = ten ? 8 : 4; int length = 0; unsigned char buf[SE_MODE_PAGE_BUF]; @@ -817,6 +817,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd) offset -= 2; buf[0] = (offset >> 8) & 0xff; buf[1] = offset & 0xff; + offset += 2; if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || (cmd->se_deve && @@ -826,13 +827,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd) if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) spc_modesense_dpofua(&buf[3], type); - - if ((offset + 2) > cmd->data_length) - offset = cmd->data_length; - } else { offset -= 1; buf[0] = offset & 0xff; + offset += 1; if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || (cmd->se_deve && @@ -842,14 +840,13 @@ static int spc_emulate_modesense(struct se_cmd *cmd) if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) spc_modesense_dpofua(&buf[2], type); - - if ((offset + 1) > cmd->data_length) - offset = cmd->data_length; } rbuf = transport_kmap_data_sg(cmd); - memcpy(rbuf, buf, offset); - transport_kunmap_data_sg(cmd); + if (rbuf) { + memcpy(rbuf, buf, min(offset, cmd->data_length)); + transport_kunmap_data_sg(cmd); + } target_complete_cmd(cmd, GOOD); return 0; From 6b84f5da1a2bb47910c79c193fbfb90ac79daf51 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Mon, 17 Sep 2012 20:05:33 +0200 Subject: [PATCH 0211/1071] target: fix return code in target_core_init_configfs error path commit 37bb7899ca366dc212b71b150e78566d04808cc0 upstream. This patch fixes error cases within target_core_init_configfs() to properly set ret = -ENOMEM before jumping to the out_global exception path. This was originally discovered with the following Coccinelle semantic match information: Convert a nonnegative error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Peter Senna Tschudin Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_configfs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 801efa89204646..06aca11a94f220 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3132,6 +3132,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!target_cg->default_groups) { pr_err("Unable to allocate target_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3147,6 +3148,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!hba_cg->default_groups) { pr_err("Unable to allocate hba_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } config_group_init_type_name(&alua_group, @@ -3162,6 +3164,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!alua_cg->default_groups) { pr_err("Unable to allocate alua_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3173,14 +3176,17 @@ static int __init target_core_init_configfs(void) * Add core/alua/lu_gps/default_lu_gp */ lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1); - if (IS_ERR(lu_gp)) + if (IS_ERR(lu_gp)) { + ret = -ENOMEM; goto out_global; + } lu_gp_cg = &alua_lu_gps_group; lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, GFP_KERNEL); if (!lu_gp_cg->default_groups) { pr_err("Unable to allocate lu_gp_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } From f73ce26cefaf7ea6ccb5df0db704211d0b8d0b89 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 29 Sep 2012 17:15:37 -0700 Subject: [PATCH 0212/1071] target/file: Re-enable optional fd_buffered_io=1 operation commit b32f4c7ed85c5cee2a21a55c9f59ebc9d57a2463 upstream. This patch re-adds the ability to optionally run in buffered FILEIO mode (eg: w/o O_DSYNC) for device backends in order to once again use the Linux buffered cache as a write-back storage mechanism. This logic was originally dropped with mainline v3.5-rc commit: commit a4dff3043c231d57f982af635c9d2192ee40e5ae Author: Nicholas Bellinger Date: Wed May 30 16:25:41 2012 -0700 target/file: Use O_DSYNC by default for FILEIO backends This difference with this patch is that fd_create_virtdevice() now forces the explicit setting of emulate_write_cache=1 when buffered FILEIO operation has been enabled. (v2: Switch to FDBD_HAS_BUFFERED_IO_WCE + add more detailed comment as requested by hch) Reported-by: Ferry Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_file.c | 41 ++++++++++++++++++++++++++++--- drivers/target/target_core_file.h | 1 + 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index cbb5aaf3e567f5..5c5ed7ac183f91 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -125,6 +125,19 @@ static struct se_device *fd_create_virtdevice( * of pure timestamp updates. */ flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; + /* + * Optionally allow fd_buffered_io=1 to be enabled for people + * who want use the fs buffer cache as an WriteCache mechanism. + * + * This means that in event of a hard failure, there is a risk + * of silent data-loss if the SCSI client has *not* performed a + * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE + * to write-out the entire device cache. + */ + if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { + pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n"); + flags &= ~O_DSYNC; + } file = filp_open(fd_dev->fd_dev_name, flags, 0600); if (IS_ERR(file)) { @@ -188,6 +201,12 @@ static struct se_device *fd_create_virtdevice( if (!dev) goto fail; + if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { + pr_debug("FILEIO: Forcing setting of emulate_write_cache=1" + " with FDBD_HAS_BUFFERED_IO_WCE\n"); + dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1; + } + fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; fd_dev->fd_queue_depth = dev->queue_depth; @@ -407,6 +426,7 @@ enum { static match_table_t tokens = { {Opt_fd_dev_name, "fd_dev_name=%s"}, {Opt_fd_dev_size, "fd_dev_size=%s"}, + {Opt_fd_buffered_io, "fd_buffered_io=%d"}, {Opt_err, NULL} }; @@ -418,7 +438,7 @@ static ssize_t fd_set_configfs_dev_params( struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; char *orig, *ptr, *arg_p, *opts; substring_t args[MAX_OPT_ARGS]; - int ret = 0, token; + int ret = 0, arg, token; opts = kstrdup(page, GFP_KERNEL); if (!opts) @@ -459,6 +479,19 @@ static ssize_t fd_set_configfs_dev_params( " bytes\n", fd_dev->fd_dev_size); fd_dev->fbd_flags |= FBDF_HAS_SIZE; break; + case Opt_fd_buffered_io: + match_int(args, &arg); + if (arg != 1) { + pr_err("bogus fd_buffered_io=%d value\n", arg); + ret = -EINVAL; + goto out; + } + + pr_debug("FILEIO: Using buffered I/O" + " operations for struct fd_dev\n"); + + fd_dev->fbd_flags |= FDBD_HAS_BUFFERED_IO_WCE; + break; default: break; } @@ -490,8 +523,10 @@ static ssize_t fd_show_configfs_dev_params( ssize_t bl = 0; bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); - bl += sprintf(b + bl, " File: %s Size: %llu Mode: O_DSYNC\n", - fd_dev->fd_dev_name, fd_dev->fd_dev_size); + bl += sprintf(b + bl, " File: %s Size: %llu Mode: %s\n", + fd_dev->fd_dev_name, fd_dev->fd_dev_size, + (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ? + "Buffered-WCE" : "O_DSYNC"); return bl; } diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h index 70ce7fd7111dd8..876ae53ef5b8bc 100644 --- a/drivers/target/target_core_file.h +++ b/drivers/target/target_core_file.h @@ -14,6 +14,7 @@ #define FBDF_HAS_PATH 0x01 #define FBDF_HAS_SIZE 0x02 +#define FDBD_HAS_BUFFERED_IO_WCE 0x04 struct fd_dev { u32 fbd_flags; From 1a5392619baf037a0aab6689ece7f4b9368d81be Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 18 Sep 2012 15:10:56 -0700 Subject: [PATCH 0213/1071] qla2xxx: Fix endianness of task management response code commit e4b11b89f9039ca97b2ed1b6efeb6749fbdeb252 upstream. The qla2xxx firmware actually expects the task management response code in a CTIO IOCB with SCSI status mode 1 to be in little-endian byte order, ie the response code should be the first byte in the sense_data[] array. The old code erroneously byte-swapped the response code, which puts it in the wrong place on the wire and leads to initiators thinking every task management request succeeds (since they see 0 in the byte where they look for the response code). Signed-off-by: Roland Dreier Cc: Chad Dupuis Cc: Arun Easi Acked-by: Saurav Kashyap Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 5b30132960c790..41b74ba8d4e584 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1403,7 +1403,7 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, ctio->u.status1.scsi_status = __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID); ctio->u.status1.response_len = __constant_cpu_to_le16(8); - ((uint32_t *)ctio->u.status1.sense_data)[0] = cpu_to_be32(resp_code); + ctio->u.status1.sense_data[0] = resp_code; qla2x00_start_iocbs(ha, ha->req); } From 7c1af9af57eafaad181505ef594d0214d0724647 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 10 Oct 2012 09:10:32 -0600 Subject: [PATCH 0214/1071] vfio: Move PCI INTx eventfd setting earlier commit 9dbdfd23b7638d054f3b0e70c64dfb9f297f2a9f upstream. We need to be ready to recieve an interrupt as soon as we call request_irq, so our eventfd context setting needs to be moved earlier. Without this, an interrupt from our device or one sharing the interrupt line can pass a NULL into eventfd_signal and oops. Signed-off-by: Alex Williamson Signed-off-by: Greg Kroah-Hartman --- drivers/vfio/pci/vfio_pci_intrs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index d8dedc7d3910c7..c8139a598f8469 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -400,19 +400,20 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd) return PTR_ERR(trigger); } + vdev->ctx[0].trigger = trigger; + if (!vdev->pci_2_3) irqflags = 0; ret = request_irq(pdev->irq, vfio_intx_handler, irqflags, vdev->ctx[0].name, vdev); if (ret) { + vdev->ctx[0].trigger = NULL; kfree(vdev->ctx[0].name); eventfd_ctx_put(trigger); return ret; } - vdev->ctx[0].trigger = trigger; - /* * INTx disable will stick across the new irq setup, * disable_irq won't. From 69c7c6695e93be50b4984a28b838a8dea0fd143b Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 10 Oct 2012 09:10:32 -0600 Subject: [PATCH 0215/1071] vfio: Fix PCI INTx disable consistency commit 899649b7d4ead76c19e39251ca886eebe3f811a8 upstream. The virq_disabled flag tracks the userspace view of INTx masking across interrupt mode changes, but we're not consistently applying this to the interrupt and masking handler notion of the device. Currently if the user sets DisINTx while in MSI or MSIX mode, then returns to INTx mode (ex. rebooting a qemu guest), the hardware has DisINTx+, but the management of INTx thinks it's enabled, making it impossible to actually clear DisINTx. Fix this by updating the handler state when INTx is re-enabled. Signed-off-by: Alex Williamson Signed-off-by: Greg Kroah-Hartman --- drivers/vfio/pci/vfio_pci_intrs.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index c8139a598f8469..3639371fa697e6 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -366,6 +366,17 @@ static int vfio_intx_enable(struct vfio_pci_device *vdev) return -ENOMEM; vdev->num_ctx = 1; + + /* + * If the virtual interrupt is masked, restore it. Devices + * supporting DisINTx can be masked at the hardware level + * here, non-PCI-2.3 devices will have to wait until the + * interrupt is enabled. + */ + vdev->ctx[0].masked = vdev->virq_disabled; + if (vdev->pci_2_3) + pci_intx(vdev->pdev, !vdev->ctx[0].masked); + vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX; return 0; @@ -419,7 +430,7 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd) * disable_irq won't. */ spin_lock_irqsave(&vdev->irqlock, flags); - if (!vdev->pci_2_3 && (vdev->ctx[0].masked || vdev->virq_disabled)) + if (!vdev->pci_2_3 && vdev->ctx[0].masked) disable_irq_nosync(pdev->irq); spin_unlock_irqrestore(&vdev->irqlock, flags); From 95983a8f8297917edd1b149980722a9a55de4979 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 10 Oct 2012 13:23:36 -0400 Subject: [PATCH 0216/1071] xen/pv-on-hvm kexec: add quirk for Xen 3.4 and shutdown watches. commit cb6b6df111e46b9d0f79eb971575fd50555f43f4 upstream. The commit 254d1a3f02ebc10ccc6e4903394d8d3f484f715e, titled "xen/pv-on-hvm kexec: shutdown watches from old kernel" assumes that the XenBus backend can deal with reading of values from: "control/platform-feature-xs_reset_watches": ... a patch for xenstored is required so that it accepts the XS_RESET_WATCHES request from a client (see changeset 23839:42a45baf037d in xen-unstable.hg). Without the patch for xenstored the registration of watches will fail and some features of a PVonHVM guest are not available. The guest is still able to boot, but repeated kexec boots will fail." Sadly this is not true when using a Xen 3.4 hypervisor and booting a PVHVM guest. We end up hanging at: err = xenbus_scanf(XBT_NIL, "control", "platform-feature-xs_reset_watches", "%d", &supported); This can easily be seen with guests hanging at xenbus_init: NX (Execute Disable) protection: active SMBIOS 2.4 present. DMI: Xen HVM domU, BIOS 3.4.0 05/13/2011 Hypervisor detected: Xen HVM Xen version 3.4. Xen Platform PCI: I/O protocol version 1 ... snip .. calling xenbus_init+0x0/0x27e @ 1 Reverting the commit or using the attached patch fixes the issue. This fix checks whether the hypervisor is older than 4.0 and if so does not try to perform the read. Fixes-Oracle-Bug: 14708233 Acked-by: Olaf Hering [v2: Added a comment in the source code] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenbus/xenbus_xs.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index bce15cf4a8df17..ca373d16a77dd0 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -47,6 +47,7 @@ #include #include #include "xenbus_comms.h" +#include struct xs_stored_msg { struct list_head list; @@ -617,7 +618,24 @@ static struct xenbus_watch *find_watch(const char *token) return NULL; } +/* + * Certain older XenBus toolstack cannot handle reading values that are + * not populated. Some Xen 3.4 installation are incapable of doing this + * so if we are running on anything older than 4 do not attempt to read + * control/platform-feature-xs_reset_watches. + */ +static bool xen_strict_xenbus_quirk() +{ + uint32_t eax, ebx, ecx, edx, base; + + base = xen_cpuid_base(); + cpuid(base + 1, &eax, &ebx, &ecx, &edx); + if ((eax >> 16) < 4) + return true; + return false; + +} static void xs_reset_watches(void) { int err, supported = 0; @@ -625,6 +643,9 @@ static void xs_reset_watches(void) if (!xen_hvm_domain()) return; + if (xen_strict_xenbus_quirk()) + return; + err = xenbus_scanf(XBT_NIL, "control", "platform-feature-xs_reset_watches", "%d", &supported); if (err != 1 || !supported) From 0afcf7b25f746c2cc7d97123133372eed58d9a9c Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 10 Oct 2012 13:25:48 -0400 Subject: [PATCH 0217/1071] xen/bootup: allow {read|write}_cr8 pvops call. commit 1a7bbda5b1ab0e02622761305a32dc38735b90b2 upstream. We actually do not do anything about it. Just return a default value of zero and if the kernel tries to write anything but 0 we BUG_ON. This fixes the case when an user tries to suspend the machine and it blows up in save_processor_state b/c 'read_cr8' is set to NULL and we get: kernel BUG at /home/konrad/ssd/linux/arch/x86/include/asm/paravirt.h:100! invalid opcode: 0000 [#1] SMP Pid: 2687, comm: init.late Tainted: G O 3.6.0upstream-00002-gac264ac-dirty #4 Bochs Bochs RIP: e030:[] [] save_processor_state+0x212/0x270 .. snip.. Call Trace: [] do_suspend_lowlevel+0xf/0xac [] ? x86_acpi_suspend_lowlevel+0x10c/0x150 [] acpi_suspend_enter+0x57/0xd5 Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 1fbe75a95f1595..e1e4636b08691a 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -984,7 +984,16 @@ static void xen_write_cr4(unsigned long cr4) native_write_cr4(cr4); } - +#ifdef CONFIG_X86_64 +static inline unsigned long xen_read_cr8(void) +{ + return 0; +} +static inline void xen_write_cr8(unsigned long val) +{ + BUG_ON(val); +} +#endif static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) { int ret; @@ -1153,6 +1162,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .read_cr4_safe = native_read_cr4_safe, .write_cr4 = xen_write_cr4, +#ifdef CONFIG_X86_64 + .read_cr8 = xen_read_cr8, + .write_cr8 = xen_write_cr8, +#endif + .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, From 90bc64b0e24471e1dc84c1bf4154c9b4cef3e43e Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 10 Oct 2012 13:30:47 -0400 Subject: [PATCH 0218/1071] xen/bootup: allow read_tscp call for Xen PV guests. commit cd0608e71e9757f4dae35bcfb4e88f4d1a03a8ab upstream. The hypervisor will trap it. However without this patch, we would crash as the .read_tscp is set to NULL. This patch fixes it and sets it to the native_read_tscp call. Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e1e4636b08691a..c1461de20408c2 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1175,6 +1175,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, + .read_tscp = native_read_tscp, + .iret = xen_iret, .irq_enable_sysexit = xen_sysexit, #ifdef CONFIG_X86_64 From e68aa412d98d72b8096f93f6c02999c8a40df3ac Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2012 14:09:30 -0700 Subject: [PATCH 0219/1071] block: fix request_queue->flags initialization commit 60ea8226cbd5c8301f9a39edc574ddabcb8150e0 upstream. A queue newly allocated with blk_alloc_queue_node() has only QUEUE_FLAG_BYPASS set. For request-based drivers, blk_init_allocated_queue() is called and q->queue_flags is overwritten with QUEUE_FLAG_DEFAULT which doesn't include BYPASS even though the initial bypass is still in effect. In blk_init_allocated_queue(), or QUEUE_FLAG_DEFAULT to q->queue_flags instead of overwriting. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index ee3cb3a5e27822..8471fb70248d52 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -696,7 +696,7 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, q->request_fn = rfn; q->prep_rq_fn = NULL; q->unprep_rq_fn = NULL; - q->queue_flags = QUEUE_FLAG_DEFAULT; + q->queue_flags |= QUEUE_FLAG_DEFAULT; /* Override internal queue lock with supplied lock pointer */ if (lock) From da1e481fd9ce08caf46bacb5a0e29e9007e3b59c Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Thu, 11 Oct 2012 08:00:33 +0800 Subject: [PATCH 0220/1071] autofs4 - fix reset pending flag on mount fail commit 49999ab27eab6289a8e4f450e148bdab521361b2 upstream. In autofs4_d_automount(), if a mount fail occurs the AUTOFS_INF_PENDING mount pending flag is not cleared. One effect of this is when using the "browse" option, directory entry attributes show up with all "?"s due to the incorrect callback and subsequent failure return (when in fact no callback should be made). Signed-off-by: Ian Kent Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/autofs4/root.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index e7396cfdb10999..91b11650722e51 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -392,10 +392,12 @@ static struct vfsmount *autofs4_d_automount(struct path *path) ino->flags |= AUTOFS_INF_PENDING; spin_unlock(&sbi->fs_lock); status = autofs4_mount_wait(dentry); - if (status) - return ERR_PTR(status); spin_lock(&sbi->fs_lock); ino->flags &= ~AUTOFS_INF_PENDING; + if (status) { + spin_unlock(&sbi->fs_lock); + return ERR_PTR(status); + } } done: if (!(ino->flags & AUTOFS_INF_EXPIRING)) { From 1c40e1c8d1e50dca33dc3f3f9dbb046f4996c2be Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 22 Jun 2012 13:49:31 -0400 Subject: [PATCH 0221/1071] module: taint kernel when lve module is loaded commit c99af3752bb52ba3aece5315279a57a477edfaf1 upstream. Cloudlinux have a product called lve that includes a kernel module. This was previously GPLed but is now under a proprietary license, but the module continues to declare MODULE_LICENSE("GPL") and makes use of some EXPORT_SYMBOL_GPL symbols. Forcibly taint it in order to avoid this. Signed-off-by: Matthew Garrett Cc: Alex Lyashkov Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index 4edbd9c11aca35..9ad9ee9406d64d 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2730,6 +2730,10 @@ static int check_module_license_and_versions(struct module *mod) if (strcmp(mod->name, "driverloader") == 0) add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + /* lve claims to be GPL but upstream won't provide source */ + if (strcmp(mod->name, "lve") == 0) + add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + #ifdef CONFIG_MODVERSIONS if ((mod->num_syms && !mod->crcs) || (mod->num_gpl_syms && !mod->gpl_crcs) From c3588050e41a77f043295a21b2e845420063be1c Mon Sep 17 00:00:00 2001 From: Alexander Holler Date: Tue, 14 Aug 2012 09:11:09 +0200 Subject: [PATCH 0222/1071] video/udlfb: fix line counting in fb_write commit b8c4321f3d194469007f5f5f2b34ec278c264a04 upstream. Line 0 and 1 were both written to line 0 (on the display) and all subsequent lines had an offset of -1. The result was that the last line on the display was never overwritten by writes to /dev/fbN. Signed-off-by: Alexander Holler Acked-by: Bernie Thompson Signed-off-by: Florian Tobias Schandinat Signed-off-by: Greg Kroah-Hartman --- drivers/video/udlfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 8af64148294b88..38fcfff3c911bd 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -647,7 +647,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf, result = fb_sys_write(info, buf, count, ppos); if (result > 0) { - int start = max((int)(offset / info->fix.line_length) - 1, 0); + int start = max((int)(offset / info->fix.line_length), 0); int lines = min((u32)((result / info->fix.line_length) + 1), (u32)info->var.yres); From f7bc7a25988f7761deb5b5f17289ac58a3fb2811 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 4 Sep 2012 11:45:32 -0400 Subject: [PATCH 0223/1071] viafb: don't touch clock state on OLPC XO-1.5 commit 012a1211845eab69a5488d59eb87d24cc518c627 upstream. As detailed in the thread titled "viafb PLL/clock tweaking causes XO-1.5 instability," enabling or disabling the IGA1/IGA2 clocks causes occasional stability problems during suspend/resume cycles on this platform. This is rather odd, as the documentation suggests that clocks have two states (on/off) and the default (stable) configuration is configured to enable the clock only when it is needed. However, explicitly enabling *or* disabling the clock triggers this system instability, suggesting that there is a 3rd state at play here. Leaving the clock enable/disable registers alone solves this problem. This fixes spurious reboots during suspend/resume behaviour introduced by commit b692a63a. Signed-off-by: Daniel Drake Signed-off-by: Florian Tobias Schandinat Signed-off-by: Greg Kroah-Hartman --- drivers/video/via/via_clock.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c index af8f26b643c15c..db1e39277e321f 100644 --- a/drivers/video/via/via_clock.c +++ b/drivers/video/via/via_clock.c @@ -25,6 +25,7 @@ #include #include +#include #include "via_clock.h" #include "global.h" #include "debug.h" @@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config) printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap); } +static void noop_set_clock_state(u8 state) +{ +} + void via_clock_init(struct via_clock *clock, int gfx_chip) { switch (gfx_chip) { @@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip) break; } + + if (machine_is_olpc()) { + /* The OLPC XO-1.5 cannot suspend/resume reliably if the + * IGA1/IGA2 clocks are set as on or off (memory rot + * occasionally happens during suspend under such + * configurations). + * + * The only known stable scenario is to leave this bits as-is, + * which in their default states are documented to enable the + * clock only when it is needed. + */ + clock->set_primary_clock_state = noop_set_clock_state; + clock->set_secondary_clock_state = noop_set_clock_state; + } } From d6168c18c127871be6a54c63f9d54c87d74dcfbc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 9 Oct 2012 10:18:23 +0300 Subject: [PATCH 0224/1071] timekeeping: Cast raw_interval to u64 to avoid shift overflow commit 5b3900cd409466c0070b234d941650685ad0c791 upstream. We fixed a bunch of integer overflows in timekeeping code during the 3.6 cycle. I did an audit based on that and found this potential overflow. Signed-off-by: Dan Carpenter Acked-by: John Stultz Link: http://lkml.kernel.org/r/20121009071823.GA19159@elgon.mountain Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d3b91e75cecd0d..f791637597e165 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1111,7 +1111,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, accumulate_nsecs_to_secs(tk); /* Accumulate raw time */ - raw_nsecs = tk->raw_interval << shift; + raw_nsecs = (u64)tk->raw_interval << shift; raw_nsecs += tk->raw_time.tv_nsec; if (raw_nsecs >= NSEC_PER_SEC) { u64 raw_secs = raw_nsecs; From 88f3373714366d54bc72e73919b6ef66b74bd6f8 Mon Sep 17 00:00:00 2001 From: "Hildner, Christian" Date: Mon, 8 Oct 2012 15:49:03 +0200 Subject: [PATCH 0225/1071] timers: Fix endless looping between cascade() and internal_add_timer() commit 26cff4e2aa4d666dc6a120ea34336b5057e3e187 upstream. Adding two (or more) timers with large values for "expires" (they have to reside within tv5 in the same list) leads to endless looping between cascade() and internal_add_timer() in case CONFIG_BASE_SMALL is one and jiffies are crossing the value 1 << 18. The bug was introduced between 2.6.11 and 2.6.12 (and survived for quite some time). This patch ensures that when cascade() is called timers within tv5 are not added endlessly to their own list again, instead they are added to the next lower tv level tv4 (as expected). Signed-off-by: Christian Hildner Reviewed-by: Jan Kiszka Link: http://lkml.kernel.org/r/98673C87CB31274881CFFE0B65ECC87B0F5FC1963E@DEFTHW99EA4MSX.ww902.siemens.net Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/timer.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/timer.c b/kernel/timer.c index 8c5e7b908c6814..46ef2b114bcbfa 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -63,6 +63,7 @@ EXPORT_SYMBOL(jiffies_64); #define TVR_SIZE (1 << TVR_BITS) #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) +#define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4*TVN_BITS)) - 1)) struct tvec { struct list_head vec[TVN_SIZE]; @@ -358,11 +359,12 @@ __internal_add_timer(struct tvec_base *base, struct timer_list *timer) vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK); } else { int i; - /* If the timeout is larger than 0xffffffff on 64-bit - * architectures then we use the maximum timeout: + /* If the timeout is larger than MAX_TVAL (on 64-bit + * architectures or with CONFIG_BASE_SMALL=1) then we + * use the maximum timeout. */ - if (idx > 0xffffffffUL) { - idx = 0xffffffffUL; + if (idx > MAX_TVAL) { + idx = MAX_TVAL; expires = idx + base->timer_jiffies; } i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; From ddf93ad023c6c334d9fae3d8a34989da286c8e4f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 4 Oct 2012 01:46:44 +0200 Subject: [PATCH 0226/1071] nohz: Fix one jiffy count too far in idle cputime commit 2b17c545a4cdbbbadcd7f1e9684c2d7db8f085a6 upstream. When we stop the tick in idle, we save the current jiffies value in ts->idle_jiffies. This snapshot is substracted from the later value of jiffies when the tick is restarted and the resulting delta is accounted as idle cputime. This is how we handle the idle cputime accounting without the tick. But sometimes we need to schedule the next tick to some time in the future instead of completely stopping it. In this case, a tick may happen before we restart the periodic behaviour and from that tick we account one jiffy to idle cputime as usual but we also increment the ts->idle_jiffies snapshot by one so that when we compute the delta to account, we substract the one jiffy we just accounted. To prepare for stopping the tick outside idle, we introduced a check that prevents from fixing up that ts->idle_jiffies if we are not running the idle task. But we use idle_cpu() for that and this is a problem if we run the tick while another CPU remotely enqueues a ttwu to our runqueue: CPU 0: CPU 1: tick_sched_timer() { ttwu_queue_remote() if (idle_cpu(CPU 0)) ts->idle_jiffies++; } Here, idle_cpu() notes that &rq->wake_list is not empty and hence won't consider the CPU as idle. As a result, ts->idle_jiffies won't be incremented. But this is wrong because we actually account the current jiffy to idle cputime. And that jiffy won't get substracted from the nohz time delta. So in the end, this jiffy is accounted twice. Fix this by changing idle_cpu(smp_processor_id()) with is_idle_task(current). This way the jiffy is substracted correctly even if a ttwu operation is enqueued on the CPU. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1349308004-3482-1-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/time/tick-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 3a9e5d5c10916a..e430b97438dc13 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -835,7 +835,7 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) */ if (ts->tick_stopped) { touch_softlockup_watchdog(); - if (idle_cpu(cpu)) + if (is_idle_task(current)) ts->idle_jiffies++; } update_process_times(user_mode(regs)); From e36434d7c5606b6e16d1851cc99c0325cff91447 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 3 Oct 2012 21:07:52 +0200 Subject: [PATCH 0227/1071] ath9k: use ieee80211_free_txskb commit 249ee72249140fe5b9adc988f97298f0aa5db2fc upstream. Using ieee80211_free_txskb for tx frames is required, since mac80211 clones skbs for which socket tx status is requested. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/beacon.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 53 ++++++++++++++----------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 76f07d8c272d1d..1b48414dca95d9 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -120,7 +120,7 @@ static void ath9k_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) if (ath_tx_start(hw, skb, &txctl) != 0) { ath_dbg(common, XMIT, "CABQ TX failed\n"); - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a22df749b8db3d..61e08e6c8585e7 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -767,7 +767,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return; exit: - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } static void ath9k_stop(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 0d4155aec48d72..423a9f375d1d42 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -66,8 +66,7 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb, - bool dequeue); + struct sk_buff *skb); enum { MCS_HT20, @@ -176,7 +175,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) fi = get_frame_info(skb); bf = fi->bf; - if (bf && fi->retries) { + if (!bf) { + bf = ath_tx_setup_buffer(sc, txq, tid, skb); + if (!bf) { + ieee80211_free_txskb(sc->hw, skb); + continue; + } + } + + if (fi->retries) { list_add_tail(&bf->list, &bf_head); ath_tx_update_baw(sc, tid, bf->bf_state.seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); @@ -785,10 +792,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, fi = get_frame_info(skb); bf = fi->bf; if (!fi->bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb, true); + bf = ath_tx_setup_buffer(sc, txq, tid, skb); - if (!bf) + if (!bf) { + __skb_unlink(skb, &tid->buf_q); + ieee80211_free_txskb(sc->hw, skb); continue; + } bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; seqno = bf->bf_state.seqno; @@ -1731,9 +1741,11 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, return; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); - if (!bf) + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) { + ieee80211_free_txskb(sc->hw, skb); return; + } bf->bf_state.bf_type = BUF_AMPDU; INIT_LIST_HEAD(&bf_head); @@ -1757,11 +1769,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf; bf = fi->bf; - if (!bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb, false); - - if (!bf) - return; INIT_LIST_HEAD(&bf_head); list_add_tail(&bf->list, &bf_head); @@ -1834,8 +1841,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb, - bool dequeue) + struct sk_buff *skb) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_frame_info *fi = get_frame_info(skb); @@ -1847,7 +1853,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, bf = ath_tx_get_buffer(sc); if (!bf) { ath_dbg(common, XMIT, "TX buffers are full\n"); - goto error; + return NULL; } ATH_TXBUF_RESET(bf); @@ -1876,18 +1882,12 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, ath_err(ath9k_hw_common(sc->sc_ah), "dma_mapping_error() on TX\n"); ath_tx_return_buffer(sc, bf); - goto error; + return NULL; } fi->bf = bf; return bf; - -error: - if (dequeue) - __skb_unlink(skb, &tid->buf_q); - dev_kfree_skb_any(skb); - return NULL; } /* FIXME: tx power */ @@ -1916,9 +1916,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, */ ath_tx_send_ampdu(sc, tid, skb, txctl); } else { - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); - if (!bf) + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) { + if (txctl->paprd) + dev_kfree_skb_any(skb); + else + ieee80211_free_txskb(sc->hw, skb); return; + } bf->bf_state.bfs_paprd = txctl->paprd; From fd39be7ff6f81f2dc91ba6e5f87944abef5b4802 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 8 Oct 2012 14:39:33 +0200 Subject: [PATCH 0228/1071] mac80211: use ieee80211_free_txskb to fix possible skb leaks commit c3e7724b6bc2f25e46c38dbe68f09d71fafeafb8 upstream. A few places free skbs using dev_kfree_skb even though they're called after ieee80211_subif_start_xmit might have cloned it for tracking tx status. Use ieee80211_free_txskb here to prevent skb leaks. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/status.c | 4 ++-- net/mac80211/tx.c | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 8cd72914cdaf2f..118329a2c84b96 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -34,7 +34,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, skb_queue_len(&local->skb_queue_unreliable); while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && (skb = skb_dequeue(&local->skb_queue_unreliable))) { - dev_kfree_skb_irq(skb); + ieee80211_free_txskb(hw, skb); tmp--; I802_DEBUG_INC(local->tx_status_drop); } @@ -159,7 +159,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", skb_queue_len(&sta->tx_filtered[ac]), !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies); - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); } static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c5e8c9c31f7687..362c418a9c34a3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -354,7 +354,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) total += skb_queue_len(&sta->ps_tx_buf[ac]); if (skb) { purged++; - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); break; } } @@ -466,7 +466,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ps_dbg(tx->sdata, "STA %pM TX buffer for AC %d full - dropping oldest frame\n", sta->sta.addr, ac); - dev_kfree_skb(old); + ieee80211_free_txskb(&local->hw, old); } else tx->local->total_ps_buffered++; @@ -1103,7 +1103,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, spin_unlock(&tx->sta->lock); if (purge_skb) - dev_kfree_skb(purge_skb); + ieee80211_free_txskb(&tx->local->hw, purge_skb); } /* reset session timer */ @@ -1214,7 +1214,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (WARN_ON_ONCE(q >= local->hw.queues)) { __skb_unlink(skb, skbs); - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); continue; } #endif @@ -1356,7 +1356,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) if (unlikely(res == TX_DROP)) { I802_DEBUG_INC(tx->local->tx_handlers_drop); if (tx->skb) - dev_kfree_skb(tx->skb); + ieee80211_free_txskb(&tx->local->hw, tx->skb); else __skb_queue_purge(&tx->skbs); return -1; @@ -1393,7 +1393,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); if (unlikely(res_prepare == TX_DROP)) { - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); goto out; } else if (unlikely(res_prepare == TX_QUEUED)) { goto out; @@ -1466,7 +1466,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) headroom = max_t(int, 0, headroom); if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); rcu_read_unlock(); return; } @@ -2060,8 +2060,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, head_need += IEEE80211_ENCRYPT_HEADROOM; head_need += local->tx_headroom; head_need = max_t(int, 0, head_need); - if (ieee80211_skb_resize(sdata, skb, head_need, true)) - goto fail; + if (ieee80211_skb_resize(sdata, skb, head_need, true)) { + ieee80211_free_txskb(&local->hw, skb); + return NETDEV_TX_OK; + } } if (encaps_data) { @@ -2196,7 +2198,7 @@ void ieee80211_tx_pending(unsigned long data) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (WARN_ON(!info->control.vif)) { - kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); continue; } From 774cb096b98e8af73bd9f3b9b82abe8786289929 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 11 Oct 2012 14:20:58 +1100 Subject: [PATCH 0229/1071] md/raid10: use correct limit variable commit 91502f099dfc5a1e8812898e26ee280713e1d002 upstream. Clang complains that we are assigning a variable to itself. This should be using bad_sectors like the similar earlier check does. Bug has been present since 3.1-rc1. It is minor but could conceivably cause corruption or other bad behaviour. Signed-off-by: Dan Carpenter Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 0138a727c1f3c2..a48c215f1262e7 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3158,7 +3158,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, else { bad_sectors -= (sector - first_bad); if (max_sync > bad_sectors) - max_sync = max_sync; + max_sync = bad_sectors; continue; } } From a150793f1f0866effaba2521fdf06130aab60d35 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 26 Aug 2012 22:37:03 -0500 Subject: [PATCH 0230/1071] kdb,vt_console: Fix missed data due to pager overruns commit 17b572e82032bc246324ce136696656b66d4e3f1 upstream. It is possible to miss data when using the kdb pager. The kdb pager does not pay attention to the maximum column constraint of the screen or serial terminal. This result is not incrementing the shown lines correctly and the pager will print more lines that fit on the screen. Obviously that is less than useful when using a VGA console where you cannot scroll back. The pager will now look at the kdb_buffer string to see how many characters are printed. It might not be perfect considering you can output ASCII that might move the cursor position, but it is a substantially better approximation for viewing dmesg and trace logs. This also means that the vt screen needs to set the kdb COLUMNS variable. Signed-off-by: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 13 +++++++++++++ kernel/debug/kdb/kdb_io.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 84cbf298c0947c..a13f7e158c5b49 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3475,6 +3475,19 @@ int con_debug_enter(struct vc_data *vc) kdb_set(2, setargs); } } + if (vc->vc_cols < 999) { + int colcount; + char cols[4]; + const char *setargs[3] = { + "set", + "COLUMNS", + cols, + }; + if (kdbgetintenv(setargs[0], &colcount)) { + snprintf(cols, 4, "%i", vc->vc_cols); + kdb_set(2, setargs); + } + } #endif /* CONFIG_KGDB_KDB */ return ret; } diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 0a69d2adc4f3cb..14ff4849262c0c 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -552,6 +552,7 @@ int vkdb_printf(const char *fmt, va_list ap) { int diag; int linecount; + int colcount; int logging, saved_loglevel = 0; int saved_trap_printk; int got_printf_lock = 0; @@ -584,6 +585,10 @@ int vkdb_printf(const char *fmt, va_list ap) if (diag || linecount <= 1) linecount = 24; + diag = kdbgetintenv("COLUMNS", &colcount); + if (diag || colcount <= 1) + colcount = 80; + diag = kdbgetintenv("LOGGING", &logging); if (diag) logging = 0; @@ -690,7 +695,7 @@ int vkdb_printf(const char *fmt, va_list ap) gdbstub_msg_write(kdb_buffer, retlen); } else { if (dbg_io_ops && !dbg_io_ops->is_console) { - len = strlen(kdb_buffer); + len = retlen; cp = kdb_buffer; while (len--) { dbg_io_ops->write_char(*cp); @@ -709,11 +714,29 @@ int vkdb_printf(const char *fmt, va_list ap) printk(KERN_INFO "%s", kdb_buffer); } - if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) - kdb_nextline++; + if (KDB_STATE(PAGER)) { + /* + * Check printed string to decide how to bump the + * kdb_nextline to control when the more prompt should + * show up. + */ + int got = 0; + len = retlen; + while (len--) { + if (kdb_buffer[len] == '\n') { + kdb_nextline++; + got = 0; + } else if (kdb_buffer[len] == '\r') { + got = 0; + } else { + got++; + } + } + kdb_nextline += got / (colcount + 1); + } /* check for having reached the LINES number of printed lines */ - if (kdb_nextline == linecount) { + if (kdb_nextline >= linecount) { char buf1[16] = ""; /* Watch out for recursion here. Any routine that calls @@ -765,7 +788,7 @@ int vkdb_printf(const char *fmt, va_list ap) kdb_grepping_flag = 0; kdb_printf("\n"); } else if (buf1[0] == ' ') { - kdb_printf("\n"); + kdb_printf("\r"); suspend_grep = 1; /* for this recursion */ } else if (buf1[0] == '\n') { kdb_nextline = linecount - 1; From ac43c058283e037c5acdee95ada41075e0e2dde5 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Tue, 9 Oct 2012 17:48:16 +0000 Subject: [PATCH 0231/1071] pktgen: fix crash when generating IPv6 packets commit 5aa8b572007c4bca1e6d3dd4c4820f1ae49d6bb2 upstream. For IPv6, sizeof(struct ipv6hdr) = 40, thus the following expression will result negative: datalen = pkt_dev->cur_pkt_size - 14 - sizeof(struct ipv6hdr) - sizeof(struct udphdr) - pkt_dev->pkt_overhead; And, the check "if (datalen < sizeof(struct pktgen_hdr))" will be passed as "datalen" is promoted to unsigned, therefore will cause a crash later. This is a quick fix by checking if "datalen" is negative. The following patch will increase the default value of 'min_pkt_size' for IPv6. This bug should exist for a long time, so Cc -stable too. Signed-off-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/pktgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 148e73d2c4515d..e356b8d52bad12 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2927,7 +2927,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, sizeof(struct ipv6hdr) - sizeof(struct udphdr) - pkt_dev->pkt_overhead; - if (datalen < sizeof(struct pktgen_hdr)) { + if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) { datalen = sizeof(struct pktgen_hdr); net_info_ratelimited("increased datalen to %d\n", datalen); } From c71964b93fde02f9607e49191d55bd430767892c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 8 Sep 2012 14:02:21 +0200 Subject: [PATCH 0232/1071] MIPS: ath79: Fix CPU/DDR frequency calculation for SRIF PLLs commit 97541ccfb9db2bb9cd1dde6344d5834438d14bda upstream. Besides the CPU and DDR PLLs, the CPU and DDR frequencies can be derived from other PLLs in the SRIF block on the AR934x SoCs. The current code does not checks if the SRIF PLLs are used and this can lead to incorrectly calculated CPU/DDR frequencies. Fix it by calculating the frequencies from SRIF PLLs if those are used on a given board. Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4324/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/ath79/clock.c | 109 +++++++++++++----- .../mips/include/asm/mach-ath79/ar71xx_regs.h | 23 ++++ 2 files changed, 104 insertions(+), 28 deletions(-) diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index d2728573e9fc78..579f452c0b456e 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -17,6 +17,8 @@ #include #include +#include + #include #include #include "common.h" @@ -166,11 +168,34 @@ static void __init ar933x_clocks_init(void) ath79_uart_clk.rate = ath79_ref_clk.rate; } +static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, + u32 frac, u32 out_div) +{ + u64 t; + u32 ret; + + t = ath79_ref_clk.rate; + t *= nint; + do_div(t, ref_div); + ret = t; + + t = ath79_ref_clk.rate; + t *= nfrac; + do_div(t, ref_div * frac); + ret += t; + + ret /= (1 << out_div); + return ret; +} + static void __init ar934x_clocks_init(void) { - u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; + u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; u32 cpu_pll, ddr_pll; u32 bootstrap; + void __iomem *dpll_base; + + dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) @@ -178,33 +203,59 @@ static void __init ar934x_clocks_init(void) else ath79_ref_clk.rate = 25 * 1000 * 1000; - pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); - out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & - AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; - ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & - AR934X_PLL_CPU_CONFIG_REFDIV_MASK; - nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & - AR934X_PLL_CPU_CONFIG_NINT_MASK; - frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & - AR934X_PLL_CPU_CONFIG_NFRAC_MASK; - - cpu_pll = nint * ath79_ref_clk.rate / ref_div; - cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); - cpu_pll /= (1 << out_div); - - pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); - out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & - AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; - ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & - AR934X_PLL_DDR_CONFIG_REFDIV_MASK; - nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & - AR934X_PLL_DDR_CONFIG_NINT_MASK; - frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & - AR934X_PLL_DDR_CONFIG_NFRAC_MASK; - - ddr_pll = nint * ath79_ref_clk.rate / ref_div; - ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); - ddr_pll /= (1 << out_div); + pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); + if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { + out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & + AR934X_SRIF_DPLL2_OUTDIV_MASK; + pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); + nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & + AR934X_SRIF_DPLL1_NINT_MASK; + nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; + ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & + AR934X_SRIF_DPLL1_REFDIV_MASK; + frac = 1 << 18; + } else { + pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); + out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; + ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + AR934X_PLL_CPU_CONFIG_REFDIV_MASK; + nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & + AR934X_PLL_CPU_CONFIG_NINT_MASK; + nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & + AR934X_PLL_CPU_CONFIG_NFRAC_MASK; + frac = 1 << 6; + } + + cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, + nfrac, frac, out_div); + + pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); + if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { + out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & + AR934X_SRIF_DPLL2_OUTDIV_MASK; + pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); + nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & + AR934X_SRIF_DPLL1_NINT_MASK; + nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; + ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & + AR934X_SRIF_DPLL1_REFDIV_MASK; + frac = 1 << 18; + } else { + pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); + out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; + ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + AR934X_PLL_DDR_CONFIG_REFDIV_MASK; + nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & + AR934X_PLL_DDR_CONFIG_NINT_MASK; + nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & + AR934X_PLL_DDR_CONFIG_NFRAC_MASK; + frac = 1 << 10; + } + + ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, + nfrac, frac, out_div); clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); @@ -240,6 +291,8 @@ static void __init ar934x_clocks_init(void) ath79_wdt_clk.rate = ath79_ref_clk.rate; ath79_uart_clk.rate = ath79_ref_clk.rate; + + iounmap(dpll_base); } void __init ath79_clocks_init(void) diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h index dde504477fac15..31a9a7cc532c93 100644 --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h @@ -63,6 +63,8 @@ #define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) #define AR934X_WMAC_SIZE 0x20000 +#define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) +#define AR934X_SRIF_SIZE 0x1000 /* * DDR_CTRL block @@ -399,4 +401,25 @@ #define AR933X_GPIO_COUNT 30 #define AR934X_GPIO_COUNT 23 +/* + * SRIF block + */ +#define AR934X_SRIF_CPU_DPLL1_REG 0x1c0 +#define AR934X_SRIF_CPU_DPLL2_REG 0x1c4 +#define AR934X_SRIF_CPU_DPLL3_REG 0x1c8 + +#define AR934X_SRIF_DDR_DPLL1_REG 0x240 +#define AR934X_SRIF_DDR_DPLL2_REG 0x244 +#define AR934X_SRIF_DDR_DPLL3_REG 0x248 + +#define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27 +#define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f +#define AR934X_SRIF_DPLL1_NINT_SHIFT 18 +#define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff +#define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff + +#define AR934X_SRIF_DPLL2_LOCAL_PLL BIT(30) +#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 +#define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 + #endif /* __ASM_MACH_AR71XX_REGS_H */ From 0a7f602a2129426e10f2c5a02f864804bf0c8fb5 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 15 Oct 2012 21:16:56 +0200 Subject: [PATCH 0233/1071] kbuild: Fix accidental revert in commit fe04ddf commit 3ce9e53e788881da0d5f3912f80e0dd6b501f304 upstream. Commit fe04ddf7c291 ("kbuild: Do not package /boot and /lib in make tar-pkg") accidentally reverted two previous kbuild commits. I don't know what I was thinking. This brings back changes made by commits 24cc7fb69a5b ("x86/kbuild: archscripts depends on scripts_basic") and c1c1a59e37da ("firmware: fix directory creation rule matching with make 3.80") Reported-by: Jan Beulich Signed-off-by: Michal Marek Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/Makefile | 2 +- scripts/Makefile.fwinst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 58790bd85c1d38..05afcca66de68c 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) -archscripts: +archscripts: scripts_basic $(Q)$(MAKE) $(build)=arch/x86/tools relocs ### diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index c3f69ae275d1f7..4d908d16c035c4 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst @@ -27,7 +27,7 @@ endif installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) -installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. +installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./ # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs @@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@) $(installed-fw-dirs): $(call cmd,mkdir) -$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%) +$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %) $(call cmd,install) PHONY += __fw_install __fw_modinst FORCE From 47b401b98b81ae1495a84f00f1d6b88316310da9 Mon Sep 17 00:00:00 2001 From: Jean-Christian de Rivaz Date: Wed, 10 Oct 2012 12:49:02 +0000 Subject: [PATCH 0234/1071] Add CDC-ACM support for the CX93010-2x UCMxx USB Modem commit e7d491a19d3e3aac544070293891a2542ae0c565 upstream. This USB V.92/V.32bis Controllered Modem have the USB vendor ID 0x0572 and device ID 0x1340. It need the NO_UNION_NORMAL quirk to be recognized. Reference: http://www.conexant.com/servlets/DownloadServlet/DSH-201723-005.pdf?docid=1725&revid=5 See idVendor and idProduct in table 6-1. Device Descriptors Signed-off-by: Jean-Christian de Rivaz Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index f763ed7ba91ea0..e8007b8ed94673 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1551,6 +1551,9 @@ static const struct usb_device_id acm_ids[] = { Maybe we should define a new quirk for this. */ }, + { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ + .driver_info = NO_UNION_NORMAL, + }, { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, From 724373bd489eb02e1999e2714fcc00658e081a9b Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 4 Oct 2012 19:57:31 -0400 Subject: [PATCH 0235/1071] fs: handle failed audit_log_start properly commit d1c7d97ad58836affde6e39980b96527510b572e upstream. audit_log_start() may return NULL, this is unchecked by the caller in audit_log_link_denied() and could cause a NULL ptr deref. Introduced by commit a51d9eaa ("fs: add link restriction audit reporting"). Signed-off-by: Sasha Levin Signed-off-by: Al Viro Cc: Dave Jones Signed-off-by: Greg Kroah-Hartman --- kernel/audit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index ea3b7b6191c7af..a8c84be9b9ea0c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1466,6 +1466,8 @@ void audit_log_link_denied(const char *operation, struct path *link) ab = audit_log_start(current->audit_context, GFP_KERNEL, AUDIT_ANOM_LINK); + if (!ab) + return; audit_log_format(ab, "op=%s action=denied", operation); audit_log_format(ab, " pid=%d comm=", current->pid); audit_log_untrustedstring(ab, current->comm); From cd7700b6aa48cc94b83ad54eb3cb1fea38c0d2c8 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 4 Oct 2012 19:56:40 -0400 Subject: [PATCH 0236/1071] fs: prevent use after free in auditing when symlink following was denied commit ffd8d101a3a7d3f2e79deee1e342801703b6dc70 upstream. Commit "fs: add link restriction audit reporting" has added auditing of failed attempts to follow symlinks. Unfortunately, the auditing was being done after the struct path structure was released earlier. Signed-off-by: Sasha Levin Signed-off-by: Al Viro Cc: Dave Jones Signed-off-by: Greg Kroah-Hartman --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index dd1ed1b8e98efe..81bd5463d908df 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -692,9 +692,9 @@ static inline int may_follow_link(struct path *link, struct nameidata *nd) if (parent->i_uid == inode->i_uid) return 0; + audit_log_link_denied("follow_link", link); path_put_conditional(link, nd); path_put(&nd->path); - audit_log_link_denied("follow_link", link); return -EACCES; } From b567aa019fe3d2b9d341650b95c7afcc04a3c812 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Mon, 15 Oct 2012 08:21:39 +0200 Subject: [PATCH 0237/1071] drm/radeon: Don't destroy I2C Bus Rec in radeon_ext_tmds_enc_destroy(). commit 082918471139b07964967cfe5f70230909c82ae1 upstream. radeon_i2c_fini() walks thru the list of I2C bus recs rdev->i2c_bus[] to destroy each of them. radeon_ext_tmds_enc_destroy() however also has code to destroy it's associated I2C bus rec which has been obtained by radeon_i2c_lookup() and is therefore also in the i2c_bus[] list. This causes a double free resulting in a kernel panic when unloading the radeon driver. Removing destroy code from radeon_ext_tmds_enc_destroy() fixes this problem. agd5f: fix compiler warning Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 670e9910f869ed..d16f50f696d937 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -974,11 +974,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; - if (tmds) { - if (tmds->i2c_bus) - radeon_i2c_destroy(tmds->i2c_bus); - } + /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */ kfree(radeon_encoder->enc_priv); drm_encoder_cleanup(encoder); kfree(radeon_encoder); From 673c45ace878af19df61f240bddc44938c47d11d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sat, 6 Oct 2012 10:20:16 +0200 Subject: [PATCH 0238/1071] drm/i915: remove useless BUG_ON which caused a regression in 3.5. commit c77d7162a7ae451c2e895d7ef7fbeb0906107472 upstream. starting an old X server causes a kernel BUG since commit 1b50247a8d: ------------[ cut here ]------------ kernel BUG at drivers/gpu/drm/i915/i915_gem.c:3661! invalid opcode: 0000 [#1] SMP Modules linked in: snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss uvcvideo +videobuf2_core videodev videobuf2_vmalloc videobuf2_memops uhci_hcd ath9k mac80211 snd_hda_codec_realtek ath9k_common microcode +ath9k_hw psmouse serio_raw sg ath cfg80211 atl1c lpc_ich mfd_core ehci_hcd snd_hda_intel snd_hda_codec snd_hwdep snd_pcm rtc_cmos +snd_timer snd evdev eeepc_laptop snd_page_alloc sparse_keymap Pid: 2866, comm: X Not tainted 3.5.6-rc1-eeepc #1 ASUSTeK Computer INC. 1005HA/1005HA EIP: 0060:[] EFLAGS: 00013297 CPU: 0 EIP is at i915_gem_entervt_ioctl+0xf1/0x110 EAX: f5941df4 EBX: f5940000 ECX: 00000000 EDX: 00020000 ESI: f5835400 EDI: 00000000 EBP: f51d7e38 ESP: f51d7e20 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 CR0: 8005003b CR2: b760e0a0 CR3: 351b6000 CR4: 000007d0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Process X (pid: 2866, ti=f51d6000 task=f61af8d0 task.ti=f51d6000) Stack: 00000001 00000000 f5835414 f51d7e84 f5835400 f54f85c0 f51d7f10 c12b530b 00000001 c151b139 c14751b6 c152e030 00000b32 00006459 00000059 0000e200 00000001 00000000 00006459 c159ddd0 c12dc1a0 ffffffea 00000000 00000000 Call Trace: [] drm_ioctl+0x2eb/0x440 [] ? i915_gem_init+0xe0/0xe0 [] ? enqueue_hrtimer+0x1b/0x50 [] ? __hrtimer_start_range_ns+0x161/0x330 [] ? lock_hrtimer_base+0x23/0x50 [] ? hrtimer_try_to_cancel+0x33/0x70 [] ? drm_version+0x90/0x90 [] vfs_ioctl+0x31/0x50 [] do_vfs_ioctl+0x64/0x510 [] ? hrtimer_nanosleep+0x8e/0x100 [] ? update_rmtp+0x80/0x80 [] sys_ioctl+0x39/0x60 [] syscall_call+0x7/0xb Code: 83 c4 0c 5b 5e 5f 5d c3 c7 44 24 04 2c 05 53 c1 c7 04 24 6f ef 47 c1 e8 6e e0 fd ff c7 83 38 1e 00 00 00 00 00 00 e9 3f ff ff +ff <0f> 0b eb fe 0f 0b eb fe 8d b4 26 00 00 00 00 0f 0b eb fe 8d b6 EIP: [] i915_gem_entervt_ioctl+0xf1/0x110 SS:ESP 0068:f51d7e20 ---[ end trace dd332ec083cbd513 ]--- The crash happens here in i915_gem_entervt_ioctl() : 3659 BUG_ON(!list_empty(&dev_priv->mm.active_list)); 3660 BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); -> 3661 BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); 3662 mutex_unlock(&dev->struct_mutex); Quoting Chris : "That BUG_ON there is silly and can simply be removed. The check is to verify that no batches were submitted to the kernel whilst the UMS/GEM client was suspended - to which the BUG_ONs are a crude approximation. Furthermore, the checks are too late, since it means we attempted to program the hardware whilst it was in an invalid state, the BUG_ONs are the least of your concerns at that point." Note that this regression has been introduced in commit 1b50247a8ddde4af5aaa0e6bc125615372ce6c16 Author: Chris Wilson Date: Tue Apr 24 15:47:30 2012 +0100 drm/i915: Remove the list of pinned inactive objects Signed-off-by: Willy Tarreau Cc: Chris Wilson [danvet: Added note about the regressing commit and cc: stable.] Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 274d25de521e78..97d4f4b76e7002 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3893,7 +3893,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, BUG_ON(!list_empty(&dev_priv->mm.active_list)); BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); - BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); mutex_unlock(&dev->struct_mutex); ret = drm_irq_install(dev); From 248f303079cbc3161e88e8ebbcc4dd25983e82b0 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Sun, 7 Oct 2012 08:51:07 -0700 Subject: [PATCH 0239/1071] drm/i915: Set guardband clipping workaround bit in the right register. commit 26b6e44afb58432a5e998da0343757404f9de9ee upstream. A previous patch, namely: commit bf97b276ca04cee9ab65ffd378fa8e6aedd71ff6 Author: Daniel Vetter Date: Wed Apr 11 20:42:41 2012 +0200 drm/i915: implement w/a for incorrect guarband clipping accidentally set bit 5 in 3D_CHICKEN, which has nothing to do with clipping. This patch changes it to be set in 3D_CHICKEN3, where it belongs. The game "Dante" demonstrates random clipping issues when guardband clipping is enabled and bit 5 of 3D_CHICKEN3 isn't set. So the workaround is actually necessary. Acked-by: Paul Menzel Cc: Daniel Vetter Cc: Oliver McFadden Signed-off-by: Kenneth Graunke Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a3e53c52e41ec6..f02cfad9e6714d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -513,7 +513,7 @@ */ # define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) #define _3D_CHICKEN3 0x02090 -#define _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL (1 << 5) +#define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5) #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8c73faee8ded90..c23c9ea06e33fc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3355,8 +3355,8 @@ static void gen6_init_clock_gating(struct drm_device *dev) GEN6_RCCUNIT_CLOCK_GATE_DISABLE); /* Bspec says we need to always set all mask bits. */ - I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) | - _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL); + I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) | + _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL); /* * According to the spec the following bits should be From 6c34ed3be47036c173f7f43df112f93fbd89026f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 26 Sep 2012 18:43:10 +0300 Subject: [PATCH 0240/1071] drm/i915: use adjusted_mode instead of mode for checking the 6bpc force flag commit 0c96c65b48fba3ffe9822a554cbc0cd610765cd5 upstream. The dithering introduced in commit 3b5c78a35cf7511c15e09a9b0ffab290a42d9bcf Author: Adam Jackson Date: Tue Dec 13 15:41:00 2011 -0800 drm/i915/dp: Dither down to 6bpc if it makes the mode fit stores the INTEL_MODE_DP_FORCE_6BPC flag in the private_flags of the adjusted mode, while i9xx_crtc_mode_set() and ironlake_crtc_mode_set() use the original mode, without the flag, so it would never have any effect. However, the BPC was clamped by VBT settings, making things work by coincidence, until that part was removed in commit 4344b813f105a19f793f1fd93ad775b784648b95 Author: Daniel Vetter Date: Fri Aug 10 11:10:20 2012 +0200 Use adjusted_mode instead of mode when checking for INTEL_MODE_DP_FORCE_6BPC to make the flag have effect. v2: Don't forget to fix this in i9xx_crtc_mode_set() also, pointed out by Daniel both before and after sending the first patch. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47621 CC: Adam Jackson Signed-off-by: Jani Nikula Reviewed-by: Adam Jackson Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0c7f4aa3798a07..b634f6ff25cc75 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4351,7 +4351,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, /* default to 8bpc */ pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); if (is_dp) { - if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { pipeconf |= PIPECONF_BPP_6 | PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP; @@ -4705,7 +4705,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(PIPECONF(pipe)); temp &= ~PIPE_BPC_MASK; - dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode); + dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, adjusted_mode); switch (pipe_bpp) { case 18: temp |= PIPE_6BPC; From 680fb76fbb854d3167477ce83388eb9db36d7dde Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 11 Oct 2012 22:51:41 +0000 Subject: [PATCH 0241/1071] mcs7830: Fix link state detection commit dabdaf0caa3af520dbc1df87b2fb4e77224037bd upstream. The device had an undocumented "feature": it can provide a sequence of spurious link-down status data even if the link is up all the time. A sequence of 10 was seen so update the link state only after the device reports the same link state 20 times. Signed-off-by: Ondrej Zary Reported-by: Michael Leun Tested-by: Michael Leun Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/mcs7830.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 03c2d8d653df1a..cc7e72010ac383 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -117,6 +117,7 @@ enum { struct mcs7830_data { u8 multi_filter[8]; u8 config; + u8 link_counter; }; static const char driver_name[] = "MOSCHIP usb-ethernet driver"; @@ -632,20 +633,31 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) static void mcs7830_status(struct usbnet *dev, struct urb *urb) { u8 *buf = urb->transfer_buffer; - bool link; + bool link, link_changed; + struct mcs7830_data *data = mcs7830_get_data(dev); if (urb->actual_length < 16) return; link = !(buf[1] & 0x20); - if (netif_carrier_ok(dev->net) != link) { - if (link) { - netif_carrier_on(dev->net); - usbnet_defer_kevent(dev, EVENT_LINK_RESET); - } else - netif_carrier_off(dev->net); - netdev_dbg(dev->net, "Link Status is: %d\n", link); - } + link_changed = netif_carrier_ok(dev->net) != link; + if (link_changed) { + data->link_counter++; + /* + track link state 20 times to guard against erroneous + link state changes reported sometimes by the chip + */ + if (data->link_counter > 20) { + data->link_counter = 0; + if (link) { + netif_carrier_on(dev->net); + usbnet_defer_kevent(dev, EVENT_LINK_RESET); + } else + netif_carrier_off(dev->net); + netdev_dbg(dev->net, "Link Status is: %d\n", link); + } + } else + data->link_counter = 0; } static const struct driver_info moschip_info = { From efe463f10b783cc62f6bf8103148a66adf15e038 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 11 Jul 2012 23:16:25 +0200 Subject: [PATCH 0242/1071] jbd: Fix assertion failure in commit code due to lacking transaction credits commit 09e05d4805e6c524c1af74e524e5d0528bb3fef3 upstream. ext3 users of data=journal mode with blocksize < pagesize were occasionally hitting assertion failure in journal_commit_transaction() checking whether the transaction has at least as many credits reserved as buffers attached. The core of the problem is that when a file gets truncated, buffers that still need checkpointing or that are attached to the committing transaction are left with buffer_mapped set. When this happens to buffers beyond i_size attached to a page stradding i_size, subsequent write extending the file will see these buffers and as they are mapped (but underlying blocks were freed) things go awry from here. The assertion failure just coincidentally (and in this case luckily as we would start corrupting filesystem) triggers due to journal_head not being properly cleaned up as well. Under some rare circumstances this bug could even hit data=ordered mode users. There the assertion won't trigger and we would end up corrupting the filesystem. We fix the problem by unmapping buffers if possible (in lots of cases we just need a buffer attached to a transaction as a place holder but it must not be written out anyway). And in one case, we just have to bite the bullet and wait for transaction commit to finish. Reviewed-by: Josef Bacik Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/jbd/commit.c | 45 +++++++++++++++++++++++-------- fs/jbd/transaction.c | 64 ++++++++++++++++++++++++++++++-------------- 2 files changed, 78 insertions(+), 31 deletions(-) diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 52c15c77602909..86b39b167c2364 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -86,7 +86,12 @@ static void release_buffer_page(struct buffer_head *bh) static void release_data_buffer(struct buffer_head *bh) { if (buffer_freed(bh)) { + WARN_ON_ONCE(buffer_dirty(bh)); clear_buffer_freed(bh); + clear_buffer_mapped(bh); + clear_buffer_new(bh); + clear_buffer_req(bh); + bh->b_bdev = NULL; release_buffer_page(bh); } else put_bh(bh); @@ -866,17 +871,35 @@ void journal_commit_transaction(journal_t *journal) * there's no point in keeping a checkpoint record for * it. */ - /* A buffer which has been freed while still being - * journaled by a previous transaction may end up still - * being dirty here, but we want to avoid writing back - * that buffer in the future after the "add to orphan" - * operation been committed, That's not only a performance - * gain, it also stops aliasing problems if the buffer is - * left behind for writeback and gets reallocated for another - * use in a different page. */ - if (buffer_freed(bh) && !jh->b_next_transaction) { - clear_buffer_freed(bh); - clear_buffer_jbddirty(bh); + /* + * A buffer which has been freed while still being journaled by + * a previous transaction. + */ + if (buffer_freed(bh)) { + /* + * If the running transaction is the one containing + * "add to orphan" operation (b_next_transaction != + * NULL), we have to wait for that transaction to + * commit before we can really get rid of the buffer. + * So just clear b_modified to not confuse transaction + * credit accounting and refile the buffer to + * BJ_Forget of the running transaction. If the just + * committed transaction contains "add to orphan" + * operation, we can completely invalidate the buffer + * now. We are rather throughout in that since the + * buffer may be still accessible when blocksize < + * pagesize and it is attached to the last partial + * page. + */ + jh->b_modified = 0; + if (!jh->b_next_transaction) { + clear_buffer_freed(bh); + clear_buffer_jbddirty(bh); + clear_buffer_mapped(bh); + clear_buffer_new(bh); + clear_buffer_req(bh); + bh->b_bdev = NULL; + } } if (buffer_jbddirty(bh)) { diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index febc10db5cedb8..78b7f84241d47b 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1843,15 +1843,16 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) * We're outside-transaction here. Either or both of j_running_transaction * and j_committing_transaction may be NULL. */ -static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) +static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, + int partial_page) { transaction_t *transaction; struct journal_head *jh; int may_free = 1; - int ret; BUFFER_TRACE(bh, "entry"); +retry: /* * It is safe to proceed here without the j_list_lock because the * buffers cannot be stolen by try_to_free_buffers as long as we are @@ -1879,10 +1880,18 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * clear the buffer dirty bit at latest at the moment when the * transaction marking the buffer as freed in the filesystem * structures is committed because from that moment on the - * buffer can be reallocated and used by a different page. + * block can be reallocated and used by a different page. * Since the block hasn't been freed yet but the inode has * already been added to orphan list, it is safe for us to add * the buffer to BJ_Forget list of the newest transaction. + * + * Also we have to clear buffer_mapped flag of a truncated buffer + * because the buffer_head may be attached to the page straddling + * i_size (can happen only when blocksize < pagesize) and thus the + * buffer_head can be reused when the file is extended again. So we end + * up keeping around invalidated buffers attached to transactions' + * BJ_Forget list just to stop checkpointing code from cleaning up + * the transaction this buffer was modified in. */ transaction = jh->b_transaction; if (transaction == NULL) { @@ -1909,13 +1918,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * committed, the buffer won't be needed any * longer. */ JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget"); - ret = __dispose_buffer(jh, + may_free = __dispose_buffer(jh, journal->j_running_transaction); - journal_put_journal_head(jh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - spin_unlock(&journal->j_state_lock); - return ret; + goto zap_buffer; } else { /* There is no currently-running transaction. So the * orphan record which we wrote for this file must have @@ -1923,13 +1928,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * the committing transaction, if it exists. */ if (journal->j_committing_transaction) { JBUFFER_TRACE(jh, "give to committing trans"); - ret = __dispose_buffer(jh, + may_free = __dispose_buffer(jh, journal->j_committing_transaction); - journal_put_journal_head(jh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - spin_unlock(&journal->j_state_lock); - return ret; + goto zap_buffer; } else { /* The orphan record's transaction has * committed. We can cleanse this buffer */ @@ -1950,10 +1951,24 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } /* * The buffer is committing, we simply cannot touch - * it. So we just set j_next_transaction to the - * running transaction (if there is one) and mark - * buffer as freed so that commit code knows it should - * clear dirty bits when it is done with the buffer. + * it. If the page is straddling i_size we have to wait + * for commit and try again. + */ + if (partial_page) { + tid_t tid = journal->j_committing_transaction->t_tid; + + journal_put_journal_head(jh); + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); + spin_unlock(&journal->j_state_lock); + log_wait_commit(journal, tid); + goto retry; + } + /* + * OK, buffer won't be reachable after truncate. We just set + * j_next_transaction to the running transaction (if there is + * one) and mark buffer as freed so that commit code knows it + * should clear dirty bits when it is done with the buffer. */ set_buffer_freed(bh); if (journal->j_running_transaction && buffer_jbddirty(bh)) @@ -1976,6 +1991,14 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } zap_buffer: + /* + * This is tricky. Although the buffer is truncated, it may be reused + * if blocksize < pagesize and it is attached to the page straddling + * EOF. Since the buffer might have been added to BJ_Forget list of the + * running transaction, journal_get_write_access() won't clear + * b_modified and credit accounting gets confused. So clear b_modified + * here. */ + jh->b_modified = 0; journal_put_journal_head(jh); zap_buffer_no_jh: spin_unlock(&journal->j_list_lock); @@ -2024,7 +2047,8 @@ void journal_invalidatepage(journal_t *journal, if (offset <= curr_off) { /* This block is wholly outside the truncation point */ lock_buffer(bh); - may_free &= journal_unmap_buffer(journal, bh); + may_free &= journal_unmap_buffer(journal, bh, + offset > 0); unlock_buffer(bh); } curr_off = next_off; From e722bf58d3647ff16a90ca9c27bb1809da36e389 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 13 Jul 2012 09:28:24 -0700 Subject: [PATCH 0243/1071] mtd: nand: allow NAND_NO_SUBPAGE_WRITE to be set from driver commit bf7a01bf7987b63b121d572b240c132ec44129c4 upstream. The NAND_CHIPOPTIONS_MSK has limited utility and is causing real bugs. It silently masks off at least one flag that might be set by the driver (NAND_NO_SUBPAGE_WRITE). This breaks the GPMI NAND driver and possibly others. Really, as long as driver writers exercise a small amount of care with NAND_* options, this mask is not necessary at all; it was only here to prevent certain options from accidentally being set by the driver. But the original thought turns out to be a bad idea occasionally. Thus, kill it. Note, this patch fixes some major gpmi-nand breakage. Signed-off-by: Brian Norris Tested-by: Huang Shijie Cc: stable@vger.kernel.org Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman index a11253a..c429abd 100644 --- drivers/mtd/nand/nand_base.c | 8 +++----- include/linux/mtd/nand.h | 3 --- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a11253a0fcabd6..c429abd00b8709 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2914,8 +2914,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, if (le16_to_cpu(p->features) & 1) *busw = NAND_BUSWIDTH_16; - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK; + chip->options |= NAND_NO_READRDY; pr_info("ONFI flash detected\n"); return 1; @@ -3080,9 +3079,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->erasesize <<= ((id_data[3] & 0x03) << 1); } } - /* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= type->options & NAND_CHIPOPTIONS_MSK; + /* Get chip options */ + chip->options |= type->options; /* * Check if chip is not a Samsung device. Do not clear the diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 57977c64052923..e5cf2c8407ce3b 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -212,9 +212,6 @@ typedef enum { #define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \ && (chip->page_shift > 9)) -/* Mask to zero out the chip options, which come from the id table */ -#define NAND_CHIPOPTIONS_MSK 0x0000ffff - /* Non chip related options */ /* This option skips the bbt scan during initialization. */ #define NAND_SKIP_BBTSCAN 0x00010000 From 3468e9db2687a4a3ad234f94ec7169028f470d3f Mon Sep 17 00:00:00 2001 From: Hiroaki SHIMODA Date: Wed, 10 Oct 2012 15:34:20 +0000 Subject: [PATCH 0244/1071] e1000e: Change wthresh to 1 to avoid possible Tx stalls commit 8edc0e624db3756783233e464879eb2e3b904c13 upstream. This patch originated from Hiroaki SHIMODA but has been modified by Intel with some minor cleanups and additional commit log text. Denys Fedoryshchenko and others reported Tx stalls on e1000e with BQL enabled. Issue was root caused to hardware delays. They were introduced because some of the e1000e hardware with transmit writeback bursting enabled, waits until the driver does an explict flush OR there are WTHRESH descriptors to write back. Sometimes the delays in question were on the order of seconds, causing visible lag for ssh sessions and unacceptable tx completion latency, especially for BQL enabled kernels. To avoid possible Tx stalls, change WTHRESH back to 1. The current plan is to investigate a method for re-enabling WTHRESH while not harming BQL, but those patches will be later for net-next if they work. please enqueue for stable since v3.3 as this bug was introduced in commit 3f0cfa3bc11e7f00c9994e0f469cbc0e7da7b00c Author: Tom Herbert Date: Mon Nov 28 16:33:16 2011 +0000 e1000e: Support for byte queue limits Changes to e1000e to use byte queue limits. Reported-by: Denys Fedoryshchenko Tested-by: Denys Fedoryshchenko Signed-off-by: Hiroaki SHIMODA CC: eric.dumazet@gmail.com CC: therbert@google.com Signed-off-by: Jesse Brandeburg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/e1000e/e1000.h | 6 +++--- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index cb3356c9af8035..04668b47a1df1a 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -175,13 +175,13 @@ struct e1000_info; /* * in the case of WTHRESH, it appears at least the 82571/2 hardware * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when - * WTHRESH=4, and since we want 64 bytes at a time written back, set - * it to 5 + * WTHRESH=4, so a setting of 5 gives the most efficient bus + * utilization but to avoid possible Tx stalls, set it to 1 */ #define E1000_TXDCTL_DMA_BURST_ENABLE \ (E1000_TXDCTL_GRAN | /* set descriptor granularity */ \ E1000_TXDCTL_COUNT_DESC | \ - (5 << 16) | /* wthresh must be +1 more than desired */\ + (1 << 16) | /* wthresh must be +1 more than desired */\ (1 << 8) | /* hthresh */ \ 0x1f) /* pthresh */ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index d01a099475a143..a46e75e5409743 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2831,7 +2831,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) * set up some performance related parameters to encourage the * hardware to use the bus more efficiently in bursts, depends * on the tx_int_delay to be enabled, - * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time + * wthresh = 1 ==> burst write is disabled to avoid Tx stalls * hthresh = 1 ==> prefetch when one or more available * pthresh = 0x1f ==> prefetch if internal cache 31 or less * BEWARE: this seems to work but should be considered first if From 561948de6498c5a59ebd59f6e383eec7d6d7afd7 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 27 Sep 2012 16:09:33 +0200 Subject: [PATCH 0245/1071] tpm: Propagate error from tpm_transmit to fix a timeout hang commit abce9ac292e13da367bbd22c1f7669f988d931ac upstream. tpm_write calls tpm_transmit without checking the return value and assigns the return value unconditionally to chip->pending_data, even if it's an error value. This causes three bugs. So if we write to /dev/tpm0 with a tpm_param_size bigger than TPM_BUFSIZE=0x1000 (e.g. 0x100a) and a bufsize also bigger than TPM_BUFSIZE (e.g. 0x100a) tpm_transmit returns -E2BIG which is assigned to chip->pending_data as -7, but tpm_write returns that TPM_BUFSIZE bytes have been successfully been written to the TPM, altough this is not true (bug #1). As we did write more than than TPM_BUFSIZE bytes but tpm_write reports that only TPM_BUFSIZE bytes have been written the vfs tries to write the remaining bytes (in this case 10 bytes) to the tpm device driver via tpm_write which then blocks at /* cannot perform a write until the read has cleared either via tpm_read or a user_read_timer timeout */ while (atomic_read(&chip->data_pending) != 0) msleep(TPM_TIMEOUT); for 60 seconds, since data_pending is -7 and nobody is able to read it (since tpm_read luckily checks if data_pending is greater than 0) (#bug 2). After that the remaining bytes are written to the TPM which are interpreted by the tpm as a normal command. (bug #3) So if the last bytes of the command stream happen to be a e.g. tpm_force_clear this gets accidentally sent to the TPM. This patch fixes all three bugs, by propagating the error code of tpm_write and returning -E2BIG if the input buffer is too big, since the response from the tpm for a truncated value is bogus anyway. Moreover it returns -EBUSY to userspace if there is a response ready to be read. Signed-off-by: Peter Huewe Signed-off-by: Kent Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 817f0ee202b686..4dc80241d59211 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1186,17 +1186,20 @@ ssize_t tpm_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - size_t in_size = size, out_size; + size_t in_size = size; + ssize_t out_size; /* cannot perform a write until the read has cleared - either via tpm_read or a user_read_timer timeout */ - while (atomic_read(&chip->data_pending) != 0) - msleep(TPM_TIMEOUT); - - mutex_lock(&chip->buffer_mutex); + either via tpm_read or a user_read_timer timeout. + This also prevents splitted buffered writes from blocking here. + */ + if (atomic_read(&chip->data_pending) != 0) + return -EBUSY; if (in_size > TPM_BUFSIZE) - in_size = TPM_BUFSIZE; + return -E2BIG; + + mutex_lock(&chip->buffer_mutex); if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { @@ -1206,6 +1209,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf, /* atomic tpm command send and result receive */ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); + if (out_size < 0) { + mutex_unlock(&chip->buffer_mutex); + return out_size; + } atomic_set(&chip->data_pending, out_size); mutex_unlock(&chip->buffer_mutex); From 758881acfecdc1e872506a6dc156c4dbb99b8f2a Mon Sep 17 00:00:00 2001 From: Fabio Porcedda Date: Fri, 7 Sep 2012 15:27:42 +0200 Subject: [PATCH 0246/1071] usb: gadget: at91_udc: fix dt support commit 9c6d196d5aa35e07482f23c3e37755e7a82140e0 upstream. Don't fail the initialization check for the platform_data if there is avaiable an associated device tree node. Signed-off-by: Fabio Porcedda Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/at91_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 1e35963bd4edc2..660fd53e28a5f3 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1699,7 +1699,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) int retval; struct resource *res; - if (!dev->platform_data) { + if (!dev->platform_data && !pdev->dev.of_node) { /* small (so we copy it) but critical! */ DBG("missing platform_data\n"); return -ENODEV; From b393c7d4d577fa9f55fa7ba84d51bd30352b80da Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 12 Oct 2012 17:28:18 +0200 Subject: [PATCH 0247/1071] ALSA: hda - Fix registration race of VGA switcheroo commit 128960a9ad67e2d119738f5211956e0304517551 upstream. Delay the registration of VGA switcheroo client to the end of the probing. Otherwise a too quick switching may result in Oops during probing. Also add the check of the return value from snd_hda_lock_devices(). Reported-and-tested-by: Daniel J Blueman Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 12a9432359f7b6..3cbfbcb07ff03f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -487,6 +487,7 @@ struct azx { /* VGA-switcheroo setup */ unsigned int use_vga_switcheroo:1; + unsigned int vga_switcheroo_registered:1; unsigned int init_failed:1; /* delayed init failed */ unsigned int disabled:1; /* disabled by VGA-switcher */ @@ -2556,7 +2557,9 @@ static void azx_vs_set_state(struct pci_dev *pci, if (disabled) { azx_suspend(&pci->dev); chip->disabled = true; - snd_hda_lock_devices(chip->bus); + if (snd_hda_lock_devices(chip->bus)) + snd_printk(KERN_WARNING SFX + "Cannot lock devices!\n"); } else { snd_hda_unlock_devices(chip->bus); chip->disabled = false; @@ -2599,14 +2602,20 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { static int __devinit register_vga_switcheroo(struct azx *chip) { + int err; + if (!chip->use_vga_switcheroo) return 0; /* FIXME: currently only handling DIS controller * is there any machine with two switchable HDMI audio controllers? */ - return vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, + err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, VGA_SWITCHEROO_DIS, chip->bus != NULL); + if (err < 0) + return err; + chip->vga_switcheroo_registered = 1; + return 0; } #else #define init_vga_switcheroo(chip) /* NOP */ @@ -2626,7 +2635,8 @@ static int azx_free(struct azx *chip) if (use_vga_switcheroo(chip)) { if (chip->disabled && chip->bus) snd_hda_unlock_devices(chip->bus); - vga_switcheroo_unregister_client(chip->pci); + if (chip->vga_switcheroo_registered) + vga_switcheroo_unregister_client(chip->pci); } if (chip->initialized) { @@ -2974,14 +2984,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } ok: - err = register_vga_switcheroo(chip); - if (err < 0) { - snd_printk(KERN_ERR SFX - "Error registering VGA-switcheroo client\n"); - azx_free(chip); - return err; - } - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); @@ -3208,6 +3210,13 @@ static int __devinit azx_probe(struct pci_dev *pci, pci_set_drvdata(pci, card); + err = register_vga_switcheroo(chip); + if (err < 0) { + snd_printk(KERN_ERR SFX + "Error registering VGA-switcheroo client\n"); + goto out_free; + } + dev++; return 0; From 5831e4dc072b50a8dc77e69d9247588f8559116c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 16 Oct 2012 16:52:26 +0200 Subject: [PATCH 0248/1071] ALSA: hda - Stop LPIB delay counting on broken hardware commit 1f04661fde9deda4a2cd5845258715a22d8af197 upstream. If LPIB reports a pretty bad value, we can't trust such hardware for calculating the PCM delay. Automatically turn off the delay counting when such a problem is encountered. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48911 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 3cbfbcb07ff03f..a5dc7464e3b423 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2136,9 +2136,12 @@ static unsigned int azx_get_position(struct azx *chip, if (delay < 0) delay += azx_dev->bufsize; if (delay >= azx_dev->period_bytes) { - snd_printdd("delay %d > period_bytes %d\n", - delay, azx_dev->period_bytes); - delay = 0; /* something is wrong */ + snd_printk(KERN_WARNING SFX + "Unstable LPIB (%d >= %d); " + "disabling LPIB delay counting\n", + delay, azx_dev->period_bytes); + delay = 0; + chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; } azx_dev->substream->runtime->delay = bytes_to_frames(azx_dev->substream->runtime, delay); From a2ffa569f0808f2ec15cda2198ab4ebc98731aab Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 17 Oct 2012 12:43:44 +0200 Subject: [PATCH 0249/1071] ALSA: hda - Always check array bounds in alc_get_line_out_pfx commit 71aa5ebe36a4e936eff281b375a4707b6a8320f2 upstream. Even when CONFIG_SND_DEBUG is not enabled, we don't want to return an arbitrary memory location when the channel count is larger than we expected. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b5d7850c3846b9..155cbd260f1321 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2629,8 +2629,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, return "PCM"; break; } - if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name))) + if (ch >= ARRAY_SIZE(channel_name)) { + snd_BUG(); return "PCM"; + } return channel_name[ch]; } From aadc0b179205a575e47cbba85cdfe71199c361a2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 3 Oct 2012 14:33:50 +0200 Subject: [PATCH 0250/1071] ASoC: fsi: don't reschedule DMA from an atomic context commit 57451e437796548d658d03c2c4aab659eafcd799 upstream. shdma doesn't support transfer re-scheduling or triggering from callbacks or from atomic context. The fsi driver issues DMA transfers from a tasklet context, which is a bug. To fix it convert tasklet to a work. Reported-by: Do Q.Thang Tested-by: Do Q.Thang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/sh/fsi.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 0540408a9fa9ab..1bb0d58c8c2083 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -223,7 +224,7 @@ struct fsi_stream { */ struct dma_chan *chan; struct sh_dmae_slave slave; /* see fsi_handler_init() */ - struct tasklet_struct tasklet; + struct work_struct work; dma_addr_t dma; }; @@ -1085,9 +1086,9 @@ static void fsi_dma_complete(void *data) snd_pcm_period_elapsed(io->substream); } -static void fsi_dma_do_tasklet(unsigned long data) +static void fsi_dma_do_work(struct work_struct *work) { - struct fsi_stream *io = (struct fsi_stream *)data; + struct fsi_stream *io = container_of(work, struct fsi_stream, work); struct fsi_priv *fsi = fsi_stream_to_priv(io); struct snd_soc_dai *dai; struct dma_async_tx_descriptor *desc; @@ -1129,7 +1130,7 @@ static void fsi_dma_do_tasklet(unsigned long data) * FIXME * * In DMAEngine case, codec and FSI cannot be started simultaneously - * since FSI is using tasklet. + * since FSI is using the scheduler work queue. * Therefore, in capture case, probably FSI FIFO will have got * overflow error in this point. * in that case, DMA cannot start transfer until error was cleared. @@ -1153,7 +1154,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void *param) static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_schedule(&io->tasklet); + schedule_work(&io->work); return 0; } @@ -1195,14 +1196,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev return fsi_stream_probe(fsi, dev); } - tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); + INIT_WORK(&io->work, fsi_dma_do_work); return 0; } static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_kill(&io->tasklet); + cancel_work_sync(&io->work); fsi_stream_stop(fsi, io); From 4b3de1fa722c1ac09445745a94ad283c23ef1e0d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Oct 2012 12:02:48 +0100 Subject: [PATCH 0251/1071] ASoC: wm2200: Use rev A register patches on rev B commit 5ae9eb4cbdfd640269dbd66aa3c92ea8e11cc838 upstream. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cdece..58ab97a143db93 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2091,6 +2091,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, switch (wm2200->rev) { case 0: + case 1: ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, ARRAY_SIZE(wm2200_reva_patch)); if (ret != 0) { From d45ee4a56528df458b9cc8f1acc71e7635f50c50 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Oct 2012 19:10:43 +0100 Subject: [PATCH 0252/1071] ASoC: wm2200: Fix non-inverted OUT2 mute control commit a1b98e12b7f8fad2f0aa3c08a3302bcac7ae1ec7 upstream. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 58ab97a143db93..c8bff6da53205d 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1028,7 +1028,7 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, digital_tlv), SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, - WM2200_SPK1R_MUTE_SHIFT, 1, 0), + WM2200_SPK1R_MUTE_SHIFT, 1, 1), }; WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); From 0c4439a4e9dafcd3c22652ce0c43c2c85aaa565a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 2 Oct 2012 15:31:16 +0300 Subject: [PATCH 0253/1071] ASoC: omap-abe-twl6040: Fix typo of Vibrator commit 034940a6b3afbe79022ab6922dd9d2982b78e6d5 upstream. It is not Vinrator but Vibrator. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/omap/omap-abe-twl6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 9d93793d3077c6..f8fba57f54f767 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -190,7 +190,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); + twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator"); twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); From f3c3eb99d6cbd372b9cb07fb21be972e06a76e44 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Oct 2012 16:43:40 +0200 Subject: [PATCH 0254/1071] ALSA: ac97 - Fix missing NULL check in snd_ac97_cvol_new() commit 733a48e5ae5bf28b046fad984d458c747cbb8c21 upstream. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=44721 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/ac97/ac97_codec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 9473fca9681dd7..8b0f996883034c 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } + if (!kctl) + return -ENOMEM; if (reg >= AC97_PHONE && reg <= AC97_PCM) set_tlv_db_scale(kctl, db_scale_5bit_12db_max); else From 0b90b298b19530b58a2b93c9f73f95ad21d32d2a Mon Sep 17 00:00:00 2001 From: Maxim Kachur Date: Wed, 17 Oct 2012 18:18:10 +0200 Subject: [PATCH 0255/1071] ALSA: emu10k1: add chip details for E-mu 1010 PCIe card commit 10f571d09106c3eb85951896522c9650596eff2e upstream. Add chip details for E-mu 1010 PCIe card. It has the same chip as found in E-mu 1010b but it uses different PCI id. Signed-off-by: Maxim Kachur Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/emu10k1/emu10k1_main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 754924081d0ac9..a78fdf466fa732 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1416,6 +1416,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ + /* Tested by Maxim Kachur 17th Oct 2012. */ + /* This is MAEM8986, 0202 is MAEM8980 */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, + .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", + .id = "EMU1010", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ /* Tested by James@superbug.co.uk 8th July 2005. */ /* This is MAEM8810, 0202 is MAEM8820 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, From 9f2a940965286754f3a34d5737c3097c05db8725 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Oct 2012 09:32:56 -0700 Subject: [PATCH 0256/1071] Linux 3.6.3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index af5d6a9023f0ac..6cdadf47f6a36e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 2 +SUBLEVEL = 3 EXTRAVERSION = NAME = Terrified Chipmunk From e28b27be06c5e6a5236c0c0b370ca0768ab086bb Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 10 Oct 2012 01:04:58 -0400 Subject: [PATCH 0257/1071] ext4: race-condition protection for ext4_convert_unwritten_extents_endio commit dee1f973ca341c266229faa5a1a5bb268bed3531 upstream. We assumed that at the time we call ext4_convert_unwritten_extents_endio() extent in question is fully inside [map.m_lblk, map->m_len] because it was already split during submission. But this may not be true due to a race between writeback vs fallocate. If extent in question is larger than requested we will split it again. Special precautions should being done if zeroout required because [map.m_lblk, map->m_len] already contains valid data. Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/extents.c | 57 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index aabbb3f53683f5..741bb944f97b33 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -52,6 +52,9 @@ #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ +#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ +#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ + static __le32 ext4_extent_block_csum(struct inode *inode, struct ext4_extent_header *eh) { @@ -2895,6 +2898,9 @@ static int ext4_split_extent_at(handle_t *handle, unsigned int ee_len, depth; int err = 0; + BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == + (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); + ext_debug("ext4_split_extents_at: inode %lu, logical" "block %llu\n", inode->i_ino, (unsigned long long)split); @@ -2953,7 +2959,14 @@ static int ext4_split_extent_at(handle_t *handle, err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - err = ext4_ext_zeroout(inode, &orig_ex); + if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { + if (split_flag & EXT4_EXT_DATA_VALID1) + err = ext4_ext_zeroout(inode, ex2); + else + err = ext4_ext_zeroout(inode, ex); + } else + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) goto fix_extent_len; /* update the extent length and mark as initialized */ @@ -3006,12 +3019,13 @@ static int ext4_split_extent(handle_t *handle, uninitialized = ext4_ext_is_uninitialized(ex); if (map->m_lblk + map->m_len < ee_block + ee_len) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1 | EXT4_EXT_MARK_UNINIT2; + if (split_flag & EXT4_EXT_DATA_VALID2) + split_flag1 |= EXT4_EXT_DATA_VALID1; err = ext4_split_extent_at(handle, inode, path, map->m_lblk + map->m_len, split_flag1, flags1); if (err) @@ -3024,8 +3038,8 @@ static int ext4_split_extent(handle_t *handle, return PTR_ERR(path); if (map->m_lblk >= ee_block) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | + EXT4_EXT_DATA_VALID2); if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1; if (split_flag & EXT4_EXT_MARK_UNINIT2) @@ -3303,26 +3317,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; split_flag |= EXT4_EXT_MARK_UNINIT2; - + if (flags & EXT4_GET_BLOCKS_CONVERT) + split_flag |= EXT4_EXT_DATA_VALID2; flags |= EXT4_GET_BLOCKS_PRE_IO; return ext4_split_extent(handle, inode, path, map, split_flag, flags); } static int ext4_convert_unwritten_extents_endio(handle_t *handle, - struct inode *inode, - struct ext4_ext_path *path) + struct inode *inode, + struct ext4_map_blocks *map, + struct ext4_ext_path *path) { struct ext4_extent *ex; + ext4_lblk_t ee_block; + unsigned int ee_len; int depth; int err = 0; depth = ext_depth(inode); ex = path[depth].p_ext; + ee_block = le32_to_cpu(ex->ee_block); + ee_len = ext4_ext_get_actual_len(ex); ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" "block %llu, max_blocks %u\n", inode->i_ino, - (unsigned long long)le32_to_cpu(ex->ee_block), - ext4_ext_get_actual_len(ex)); + (unsigned long long)ee_block, ee_len); + + /* If extent is larger than requested then split is required */ + if (ee_block != map->m_lblk || ee_len > map->m_len) { + err = ext4_split_unwritten_extents(handle, inode, map, path, + EXT4_GET_BLOCKS_CONVERT); + if (err < 0) + goto out; + ext4_ext_drop_refs(path); + path = ext4_ext_find_extent(inode, map->m_lblk, path); + if (IS_ERR(path)) { + err = PTR_ERR(path); + goto out; + } + depth = ext_depth(inode); + ex = path[depth].p_ext; + } err = ext4_ext_get_access(handle, inode, path + depth); if (err) @@ -3630,7 +3665,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, } /* IO end_io complete, convert the filled extent to written */ if ((flags & EXT4_GET_BLOCKS_CONVERT)) { - ret = ext4_convert_unwritten_extents_endio(handle, inode, + ret = ext4_convert_unwritten_extents_endio(handle, inode, map, path); if (ret >= 0) { ext4_update_inode_fsync_trans(handle, inode, 1); From 462f4e60ea80fc6d82b872243c4d11a9f8286d0d Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 22 Oct 2012 00:34:32 -0400 Subject: [PATCH 0258/1071] ext4: Checksum the block bitmap properly with bigalloc enabled commit 79f1ba49569e5aec919b653c55b03274c2331701 upstream. In mke2fs, we only checksum the whole bitmap block and it is right. While in the kernel, we use EXT4_BLOCKS_PER_GROUP to indicate the size of the checksumed bitmap which is wrong when we enable bigalloc. The right size should be EXT4_CLUSTERS_PER_GROUP and this patch fixes it. Also as every caller of ext4_block_bitmap_csum_set and ext4_block_bitmap_csum_verify pass in EXT4_BLOCKS_PER_GROUP(sb)/8, we'd better removes this parameter and sets it in the function itself. Signed-off-by: Tao Ma Signed-off-by: "Theodore Ts'o" Reviewed-by: Lukas Czerner Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 8 +++----- fs/ext4/bitmap.c | 6 ++++-- fs/ext4/ext4.h | 4 ++-- fs/ext4/ialloc.c | 4 +--- fs/ext4/mballoc.c | 9 +++------ fs/ext4/resize.c | 3 +-- 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1b5089067d018d..cf1821784a16bf 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, ext4_free_inodes_set(sb, gdp, 0); ext4_itable_unused_set(sb, gdp, 0); memset(bh->b_data, 0xff, sb->s_blocksize); - ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); return; } memset(bh->b_data, 0, sb->s_blocksize); @@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, */ ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), sb->s_blocksize * 8, bh->b_data); - ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); ext4_group_desc_csum_set(sb, block_group, gdp); } @@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct super_block *sb, return; } if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, - desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { + desc, bh))) { ext4_unlock_group(sb, block_group); ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); return; diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index 5c2d1813ebe919..3285aa5a706af3 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz) + struct buffer_head *bh) { __u32 hi; __u32 provided, calculated; struct ext4_sb_info *sbi = EXT4_SB(sb); + int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) @@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz) + struct buffer_head *bh) { + int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; __u32 csum; struct ext4_sb_info *sbi = EXT4_SB(sb); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index c3411d4ce2da57..5c69f2b32b1cb1 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1867,10 +1867,10 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct buffer_head *bh, int sz); void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz); + struct buffer_head *bh); int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz); + struct buffer_head *bh); /* balloc.c */ extern void ext4_validate_block_bitmap(struct super_block *sb, diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 26154b81b83679..8ce0076c315238 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -753,9 +753,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, ext4_free_group_clusters_set(sb, gdp, ext4_free_clusters_after_init(sb, group, gdp)); ext4_block_bitmap_csum_set(sb, group, gdp, - block_bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / - 8); + block_bitmap_bh); ext4_group_desc_csum_set(sb, group, gdp); } ext4_unlock_group(sb, group); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 8eae94771c45b0..e3feae5567ab14 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2804,8 +2804,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, } len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len; ext4_free_group_clusters_set(sb, gdp, len); - ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh); ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp); ext4_unlock_group(sb, ac->ac_b_ex.fe_group); @@ -4664,8 +4663,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, ret = ext4_free_group_clusters(sb, gdp) + count_clusters; ext4_free_group_clusters_set(sb, gdp, ret); - ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh); ext4_group_desc_csum_set(sb, block_group, gdp); ext4_unlock_group(sb, block_group); percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); @@ -4809,8 +4807,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, mb_free_blocks(NULL, &e4b, bit, count); blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc); ext4_free_group_clusters_set(sb, desc, blk_free_count); - ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh); ext4_group_desc_csum_set(sb, block_group, desc); ext4_unlock_group(sb, block_group); percpu_counter_add(&sbi->s_freeclusters_counter, diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 0be1789ebc3ba7..71241bc0eea614 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1121,8 +1121,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb, bh = ext4_get_bitmap(sb, group_data->block_bitmap); if (!bh) return -EIO; - ext4_block_bitmap_csum_set(sb, group, gdp, bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, group, gdp, bh); brelse(bh); return 0; From b1f9e723563c5dae07c0c8d49b21ea9602c3e644 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 22 Oct 2012 18:01:19 -0400 Subject: [PATCH 0259/1071] ext4: Avoid underflow in ext4_trim_fs() commit 5de35e8d5c02d271c20e18337e01bc20e6ef472e upstream. Currently if len argument in ext4_trim_fs() is smaller than one block, the 'end' variable underflow. Avoid that by returning EINVAL if len is smaller than file system block. Also remove useless unlikely(). Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/mballoc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index e3feae5567ab14..b26410c8f85249 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4987,8 +4987,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) end = start + (range->len >> sb->s_blocksize_bits) - 1; minlen = range->minlen >> sb->s_blocksize_bits; - if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) || - unlikely(start >= max_blks)) + if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) || + start >= max_blks || + range->len < sb->s_blocksize) return -EINVAL; if (end >= max_blks) end = max_blks - 1; From e4e29779ec498f4905461a13b6ba58ba4f60152b Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 13 Oct 2012 12:20:36 +0200 Subject: [PATCH 0260/1071] usbdevfs: Fix broken scatter-gather transfer commit 014639003c77a51fc319c9fdf225e7747cb6e18d upstream. The handling of large output bulk transfers is broken; the same user page is read over and over again. Fixed with this patch. Acked-by: Peter Stuge Acked-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Henrik Rydberg Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index ebb8a9de8b5fe4..7f75343a15ba2d 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1348,6 +1348,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ret = -EFAULT; goto error; } + uurb->buffer += u; } totlen -= u; } From e0afa17f5335bad3b257a7d1048b2b70c649b681 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 9 Oct 2012 13:23:57 -0700 Subject: [PATCH 0261/1071] hwmon: (coretemp) Add support for Atom CE4110/4150/4170 commit 1102dcab849313bd5a340b299b5cf61b518fbc0f upstream. TjMax for the CE4100 series of Atom CPUs was previously reported to be 110 degrees C. cpuinfo logs on the web show existing CPU types CE4110, CE4150, and CE4170, reported as "model name : Intel(R) Atom(TM) CPU CE41{1|5|7}0 @ 1.{2|6}0GHz" with model 28 (0x1c) and stepping 10 (0x0a). Add the three known variants to the tjmax table. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/coretemp | 1 + drivers/hwmon/coretemp.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp index c86b50c03ea8f0..f17256f069baee 100644 --- a/Documentation/hwmon/coretemp +++ b/Documentation/hwmon/coretemp @@ -105,6 +105,7 @@ Process Processor TjMax(C) 330/230 125 E680/660/640/620 90 E680T/660T/640T/620T 110 + CE4170/4150/4110 110 45nm Core2 Processors Solo ULV SU3500/3300 100 diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 984a3f13923b61..47b8d84b489ddb 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -205,8 +205,11 @@ static const struct tjmax __cpuinitconst tjmax_table[] = { { "CPU N455", 100000 }, { "CPU N470", 100000 }, { "CPU N475", 100000 }, - { "CPU 230", 100000 }, - { "CPU 330", 125000 }, + { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ + { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ + { "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 */ + { "CPU CE4150", 110000 }, /* Model 0x1c, stepping 10 */ + { "CPU CE4170", 110000 }, /* Model 0x1c, stepping 10 */ }; static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, From a6828f217248d46865ac1f8043bff2a5ae20d7b2 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Wed, 10 Oct 2012 11:51:09 +0530 Subject: [PATCH 0262/1071] nohz: Fix idle ticks in cpu summary line of /proc/stat commit 7386cdbf2f57ea8cff3c9fde93f206e58b9fe13f upstream. Git commit 09a1d34f8535ecf9 "nohz: Make idle/iowait counter update conditional" introduced a bug in regard to cpu hotplug. The effect is that the number of idle ticks in the cpu summary line in /proc/stat is still counting ticks for offline cpus. Reproduction is easy, just start a workload that keeps all cpus busy, switch off one or more cpus and then watch the idle field in top. On a dual-core with one cpu 100% busy and one offline cpu you will get something like this: %Cpu(s): 48.7 us, 1.3 sy, 0.0 ni, 50.0 id, 0.0 wa, 0.0 hi, 0.0 si, %0.0 st The problem is that an offline cpu still has ts->idle_active == 1. To fix this we should make sure that the cpu is online when calling get_cpu_idle_time_us and get_cpu_iowait_time_us. [Srivatsa: Rebased to current mainline] Reported-by: Martin Schwidefsky Signed-off-by: Michal Hocko Reviewed-by: Srivatsa S. Bhat Signed-off-by: Srivatsa S. Bhat Link: http://lkml.kernel.org/r/20121010061820.8999.57245.stgit@srivatsabhat.in.ibm.com Cc: deepthi@linux.vnet.ibm.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- fs/proc/stat.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 64c3b3172367ab..e296572c73ed65 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu) static u64 get_idle_time(int cpu) { - u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL); + u64 idle, idle_time = -1ULL; + + if (cpu_online(cpu)) + idle_time = get_cpu_idle_time_us(cpu, NULL); if (idle_time == -1ULL) - /* !NO_HZ so we can rely on cpustat.idle */ + /* !NO_HZ or cpu offline so we can rely on cpustat.idle */ idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; else idle = usecs_to_cputime64(idle_time); @@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu) static u64 get_iowait_time(int cpu) { - u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL); + u64 iowait, iowait_time = -1ULL; + + if (cpu_online(cpu)) + iowait_time = get_cpu_iowait_time_us(cpu, NULL); if (iowait_time == -1ULL) - /* !NO_HZ so we can rely on cpustat.iowait */ + /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */ iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; else iowait = usecs_to_cputime64(iowait_time); From 1e9b1525c67f953107066d7a062a256311199394 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 19 Oct 2012 11:43:11 -0400 Subject: [PATCH 0263/1071] arch/tile: avoid generating .eh_frame information in modules commit 627072b06c362bbe7dc256f618aaa63351f0cfe6 upstream. The tile tool chain uses the .eh_frame information for backtracing. The vmlinux build drops any .eh_frame sections at link time, but when present in kernel modules, it causes a module load failure due to the presence of unsupported pc-relative relocations. When compiling to use compiler feedback support, the compiler by default omits .eh_frame information, so we don't see this problem. But when not using feedback, we need to explicitly suppress the .eh_frame. Signed-off-by: Chris Metcalf Signed-off-by: Greg Kroah-Hartman --- arch/tile/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/tile/Makefile b/arch/tile/Makefile index 55640cf92597b1..3d15364c60714b 100644 --- a/arch/tile/Makefile +++ b/arch/tile/Makefile @@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH)) endif endif +# The tile compiler may emit .eh_frame information for backtracing. +# In kernel modules, this causes load failures due to unsupported relocations. +KBUILD_CFLAGS += -fno-asynchronous-unwind-tables + ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"") KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS) endif From 4e4ca99992f539bdcd1613efc0a45e4ce15f4a8d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 13 Oct 2012 00:30:28 -0400 Subject: [PATCH 0264/1071] NLM: nlm_lookup_file() may return NLMv4-specific error codes commit cd0b16c1c3cda12dbed1f8de8f1a9b0591990724 upstream. If the filehandle is stale, or open access is denied for some reason, nlm_fopen() may return one of the NLMv4-specific error codes nlm4_stale_fh or nlm4_failed. These get passed right through nlm_lookup_file(), and so when nlmsvc_retrieve_args() calls the latter, it needs to filter the result through the cast_status() machinery. Failure to do so, will trigger the BUG_ON() in encode_nlm_stat... Signed-off-by: Trond Myklebust Reported-by: Larry McVoy Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/lockd/clntxdr.c | 2 +- fs/lockd/svcproc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index d269ada7670e15..982d2676e1f813 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c @@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr, { __be32 *p; - BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); + WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); p = xdr_reserve_space(xdr, 4); *p = stat; } diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3009a365e082e3..21171f0c647756 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -68,7 +68,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain file pointer. Not used by FREE_ALL call. */ if (filp != NULL) { - if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) + error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh)); + if (error != 0) goto no_locks; *filp = file; From 73f989c0045ae68f82038cddbda1c702fac63cf6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 Oct 2012 10:18:35 +0300 Subject: [PATCH 0265/1071] oprofile, x86: Fix wrapping bug in op_x86_get_ctrl() commit 44009105081b51417f311f4c3be0061870b6b8ed upstream. The "event" variable is a u16 so the shift will always wrap to zero making the line a no-op. Signed-off-by: Dan Carpenter Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 26b8a8514ee566..48768df2471af2 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model, val |= counter_config->extra; event &= model->event_mask ? model->event_mask : 0xFF; val |= event & 0xFF; - val |= (event & 0x0F00) << 24; + val |= (u64)(event & 0x0F00) << 24; return val; } From 92b9b80b2bd99a192d0444414965b73be3349274 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 18 Oct 2012 11:11:01 +0200 Subject: [PATCH 0266/1071] s390: fix linker script for 31 bit builds commit c985cb37f1b39c2c8035af741a2a0b79f1fbaca7 upstream. Because of a change in the s390 arch backend of binutils (commit 23ecd77 "Pick the default arch depending on the target size" in binutils repo) 31 bit builds will fail since the linker would now try to create 64 bit binary output. Fix this by setting OUTPUT_ARCH to s390:31-bit instead of s390. Thanks to Andreas Krebbel for figuring out the issue. Fixes this build error: LD init/built-in.o s390x-4.7.2-ld: s390:31-bit architecture of input file `arch/s390/kernel/head.o' is incompatible with s390:64-bit output Cc: Andreas Krebbel Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/boot/compressed/vmlinux.lds.S | 2 +- arch/s390/kernel/vmlinux.lds.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S index d80f79d8dd9cd0..8e1fb823928736 100644 --- a/arch/s390/boot/compressed/vmlinux.lds.S +++ b/arch/s390/boot/compressed/vmlinux.lds.S @@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") OUTPUT_ARCH(s390:64-bit) #else OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) #endif ENTRY(startup) diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index de8fa9bbd35ee9..79cb51adc7419b 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -8,7 +8,7 @@ #ifndef CONFIG_64BIT OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) ENTRY(startup) jiffies = jiffies_64 + 4; #else From d702bf50186d554cff95c94f8d07ab5cc4e67aea Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 17 Jul 2012 00:01:26 +0200 Subject: [PATCH 0267/1071] SUNRPC: Prevent kernel stack corruption on long values of flush commit 212ba90696ab4884e2025b0b13726d67aadc2cd4 upstream. The buffer size in read_flush() is too small for the longest possible values for it. This can lead to a kernel stack corruption: [ 43.047329] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff833e64b4 [ 43.047329] [ 43.049030] Pid: 6015, comm: trinity-child18 Tainted: G W 3.5.0-rc7-next-20120716-sasha #221 [ 43.050038] Call Trace: [ 43.050435] [] panic+0xcd/0x1f4 [ 43.050931] [] ? read_flush.isra.7+0xe4/0x100 [ 43.051602] [] __stack_chk_fail+0x16/0x20 [ 43.052206] [] read_flush.isra.7+0xe4/0x100 [ 43.052951] [] ? read_flush_pipefs+0x30/0x30 [ 43.053594] [] read_flush_procfs+0x2c/0x30 [ 43.053596] [] proc_reg_read+0x9c/0xd0 [ 43.053596] [] ? proc_reg_write+0xd0/0xd0 [ 43.053596] [] do_loop_readv_writev+0x4b/0x90 [ 43.053596] [] do_readv_writev+0xf6/0x1d0 [ 43.053596] [] vfs_readv+0x3e/0x60 [ 43.053596] [] sys_readv+0x48/0xb0 [ 43.053596] [] system_call_fastpath+0x1a/0x1f Signed-off-by: Sasha Levin Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 2afd2a84dc35aa..f86d95eada5156 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1409,11 +1409,11 @@ static ssize_t read_flush(struct file *file, char __user *buf, size_t count, loff_t *ppos, struct cache_detail *cd) { - char tbuf[20]; + char tbuf[22]; unsigned long p = *ppos; size_t len; - sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time)); + snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time)); len = strlen(tbuf); if (p >= len) return 0; From 3e75581ec02473059597582fa24cf077f0e20b1b Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 22 Oct 2012 12:35:40 -0400 Subject: [PATCH 0268/1071] SUNRPC: Set alloc_slot for backchannel tcp ops commit 84e28a307e376f271505af65a7b7e212dd6f61f4 upstream. f39c1bfb5a03e2d255451bff05be0d7255298fa4 (SUNRPC: Fix a UDP transport regression) introduced the "alloc_slot" function for xprt operations, but never created one for the backchannel operations. This patch fixes a null pointer dereference when mounting NFS over v4.1. Call Trace: [] ? xprt_reserve+0x47/0x50 [sunrpc] [] call_reserve+0x34/0x60 [sunrpc] [] __rpc_execute+0x90/0x400 [sunrpc] [] rpc_async_schedule+0x2a/0x40 [sunrpc] [] process_one_work+0x139/0x500 [] ? alloc_worker+0x70/0x70 [] ? __rpc_execute+0x400/0x400 [sunrpc] [] worker_thread+0x15e/0x460 [] ? preempt_schedule+0x49/0x70 [] ? rescuer_thread+0x230/0x230 [] kthread+0x93/0xa0 [] kernel_thread_helper+0x4/0x10 [] ? kthread_freezable_should_stop+0x70/0x70 [] ? gs_change+0x13/0x13 Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d1988cf8bf3322..97f8918169edb4 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2539,6 +2539,7 @@ static struct rpc_xprt_ops xs_tcp_ops = { static struct rpc_xprt_ops bc_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xprt_release_xprt, + .alloc_slot = xprt_alloc_slot, .rpcbind = xs_local_rpcbind, .buf_alloc = bc_malloc, .buf_free = bc_free, From c46d0da8fad7ef10a6f86ebd698fba26e7cadcf5 Mon Sep 17 00:00:00 2001 From: Vaibhav Nagarnaik Date: Wed, 10 Oct 2012 16:40:27 -0700 Subject: [PATCH 0269/1071] ring-buffer: Check for uninitialized cpu buffer before resizing commit 8e49f418c9632790bf456634742d34d97120a784 upstream. With a system where, num_present_cpus < num_possible_cpus, even if all CPUs are online, non-present CPUs don't have per_cpu buffers allocated. If per_cpu//buffer_size_kb is modified for such a CPU, it can cause a panic due to NULL dereference in ring_buffer_resize(). To fix this, resize operation is allowed only if the per-cpu buffer has been initialized. Link: http://lkml.kernel.org/r/1349912427-6486-1-git-send-email-vnagarnaik@google.com Signed-off-by: Vaibhav Nagarnaik Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 49491fa7daa2d3..ebd284f63e1be6 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1567,6 +1567,10 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size, put_online_cpus(); } else { + /* Make sure this CPU has been intitialized */ + if (!cpumask_test_cpu(cpu_id, buffer->cpumask)) + goto out; + cpu_buffer = buffer->buffers[cpu_id]; if (nr_pages == cpu_buffer->nr_pages) From c5d5a7c5acb92d444faad8a378a2c94a7afd7f6f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 13:50:56 +0000 Subject: [PATCH 0270/1071] pcmcia: sharpsl: don't discard sharpsl_pcmcia_ops commit fdc858a466b738d35d3492bc7cf77b1dac98bf7c upstream. The sharpsl_pcmcia_ops structure gets passed into sa11xx_drv_pcmcia_probe, where it gets accessed at run-time, unlike all other pcmcia drivers that pass their structures into platform_device_add_data, which makes a copy. This means the gcc warning is valid and the structure must not be marked as __initdata. Without this patch, building collie_defconfig results in: drivers/pcmcia/pxa2xx_sharpsl.c:22:31: fatal error: mach-pxa/hardware.h: No such file or directory compilation terminated. make[3]: *** [drivers/pcmcia/pxa2xx_sharpsl.o] Error 1 make[2]: *** [drivers/pcmcia] Error 2 make[1]: *** [drivers] Error 2 make: *** [sub-make] Error 2 Signed-off-by: Arnd Bergmann Cc: Dominik Brodowski Cc: Russell King Cc: Pavel Machek Cc: linux-pcmcia@lists.infradead.org Cc: Jochen Friedrich Signed-off-by: Greg Kroah-Hartman --- drivers/pcmcia/pxa2xx_sharpsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index b066273b6b4f4d..7dd879ce514df8 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) sharpsl_pcmcia_init_reset(skt); } -static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { +static struct pcmcia_low_level sharpsl_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = sharpsl_pcmcia_hw_init, .socket_state = sharpsl_pcmcia_socket_state, From 53a976ad28154268b3474d9fa45283cc48ff97d4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 19 Oct 2012 13:56:51 -0700 Subject: [PATCH 0271/1071] kernel/sys.c: fix stack memory content leak via UNAME26 commit 2702b1526c7278c4d65d78de209a465d4de2885e upstream. Calling uname() with the UNAME26 personality set allows a leak of kernel stack contents. This fixes it by defensively calculating the length of copy_to_user() call, making the len argument unsigned, and initializing the stack buffer to zero (now technically unneeded, but hey, overkill). CVE-2012-0957 Reported-by: PaX Team Signed-off-by: Kees Cook Cc: Andi Kleen Cc: PaX Team Cc: Brad Spengler Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sys.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index 6fab59a1fc24d9..9e5ab97d34c9d6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem); * Work around broken programs that cannot handle "Linux 3.0". * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 */ -static int override_release(char __user *release, int len) +static int override_release(char __user *release, size_t len) { int ret = 0; - char buf[65]; if (current->personality & UNAME26) { - char *rest = UTS_RELEASE; + const char *rest = UTS_RELEASE; + char buf[65] = { 0 }; int ndots = 0; unsigned v; + size_t copy; while (*rest) { if (*rest == '.' && ++ndots >= 3) @@ -1283,8 +1284,9 @@ static int override_release(char __user *release, int len) rest++; } v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; - snprintf(buf, len, "2.6.%u%s", v, rest); - ret = copy_to_user(release, buf, len); + copy = min(sizeof(buf), max_t(size_t, 1, len)); + copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); + ret = copy_to_user(release, buf, copy + 1); } return ret; } From fe6e782af66c8efaa297229fd92fa209440b4eae Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 19 Oct 2012 18:45:53 -0700 Subject: [PATCH 0272/1071] use clamp_t in UNAME26 fix commit 31fd84b95eb211d5db460a1dda85e004800a7b52 upstream. The min/max call needed to have explicit types on some architectures (e.g. mn10300). Use clamp_t instead to avoid the warning: kernel/sys.c: In function 'override_release': kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default] Reported-by: Fengguang Wu Signed-off-by: Kees Cook Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sys.c b/kernel/sys.c index 9e5ab97d34c9d6..909148a08ec5bb 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1284,7 +1284,7 @@ static int override_release(char __user *release, size_t len) rest++; } v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; - copy = min(sizeof(buf), max_t(size_t, 1, len)); + copy = clamp_t(size_t, len, 1, sizeof(buf)); copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); ret = copy_to_user(release, buf, copy + 1); } From 660dc78ced9178efb5425ab313e6f040c0e5c828 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 1 Oct 2012 14:42:05 +0800 Subject: [PATCH 0273/1071] x86, amd, mce: Avoid NULL pointer reference on CPU northbridge lookup commit 21c5e50e15b1abd797e62f18fd7f90b9cc004cbd upstream. When booting on a federated multi-server system (NumaScale), the processor Northbridge lookup returns NULL; add guards to prevent this causing an oops. On those systems, the northbridge is accessed through MMIO and the "normal" northbridge enumeration in amd_nb.c doesn't work since we're generating the northbridge ID from the initial APIC ID and the last is not unique on those systems. Long story short, we end up without northbridge descriptors. Signed-off-by: Daniel J Blueman Link: http://lkml.kernel.org/r/1349073725-14093-1-git-send-email-daniel@numascale-asia.com [ Boris: beef up commit message ] Signed-off-by: Borislav Petkov Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index c4e916d773780f..698b6ec12e0f40 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -576,12 +576,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) int err = 0; if (shared_bank[bank]) { - nb = node_to_amd_nb(amd_get_nb_id(cpu)); - WARN_ON(!nb); /* threshold descriptor already initialized on this node? */ - if (nb->bank4) { + if (nb && nb->bank4) { /* yes, use it */ b = nb->bank4; err = kobject_add(b->kobj, &dev->kobj, name); @@ -615,8 +613,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) atomic_set(&b->cpus, 1); /* nb is already initialized, see above */ - WARN_ON(nb->bank4); - nb->bank4 = b; + if (nb) { + WARN_ON(nb->bank4); + nb->bank4 = b; + } } err = allocate_threshold_blocks(cpu, bank, 0, From 54ce8ce298f382a06186cb4672ad6aa090b050b6 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Thu, 20 Oct 2011 16:15:26 -0500 Subject: [PATCH 0274/1071] x86: Exclude E820_RESERVED regions and memory holes above 4 GB from direct mapping. commit 1bbbbe779aabe1f0768c2bf8f8c0a5583679b54a upstream. On systems with very large memory (1 TB in our case), BIOS may report a reserved region or a hole in the E820 map, even above the 4 GB range. Exclude these from the direct mapping. [ hpa: this should be done not just for > 4 GB but for everything above the legacy region (1 MB), at the very least. That, however, turns out to require significant restructuring. That work is well underway, but is not suitable for rc/stable. ] Signed-off-by: Jacob Shin Link: http://lkml.kernel.org/r/1319145326-13902-1-git-send-email-jacob.shin@amd.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/setup.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f4b9b80e1b95e2..198e774498ec0e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -919,8 +919,21 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { - max_pfn_mapped = init_memory_mapping(1UL<<32, - max_pfn<addr + ei->size <= 1UL << 32) + continue; + + if (ei->type == E820_RESERVED) + continue; + + max_pfn_mapped = init_memory_mapping( + ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr, + ei->addr + ei->size); + } + /* can we preseve max_low_pfn ?*/ max_low_pfn = max_pfn; } From 43a9e5c3f04f3ee1c5b0bf2c81d8e2fdf9a83668 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 19 Oct 2012 17:29:07 +0100 Subject: [PATCH 0275/1071] xen/x86: don't corrupt %eip when returning from a signal handler commit a349e23d1cf746f8bdc603dcc61fae9ee4a695f6 upstream. In 32 bit guests, if a userspace process has %eax == -ERESTARTSYS (-512) or -ERESTARTNOINTR (-513) when it is interrupted by an event /and/ the process has a pending signal then %eip (and %eax) are corrupted when returning to the main process after handling the signal. The application may then crash with SIGSEGV or a SIGILL or it may have subtly incorrect behaviour (depending on what instruction it returned to). The occurs because handle_signal() is incorrectly thinking that there is a system call that needs to restarted so it adjusts %eip and %eax to re-execute the system call instruction (even though user space had not done a system call). If %eax == -514 (-ERESTARTNOHAND (-514) or -ERESTART_RESTARTBLOCK (-516) then handle_signal() only corrupted %eax (by setting it to -EINTR). This may cause the application to crash or have incorrect behaviour. handle_signal() assumes that regs->orig_ax >= 0 means a system call so any kernel entry point that is not for a system call must push a negative value for orig_ax. For example, for physical interrupts on bare metal the inverse of the vector is pushed and page_fault() sets regs->orig_ax to -1, overwriting the hardware provided error code. xen_hypervisor_callback() was incorrectly pushing 0 for orig_ax instead of -1. Classic Xen kernels pushed %eax which works as %eax cannot be both non-negative and -RESTARTSYS (etc.), but using -1 is consistent with other non-system call entry points and avoids some of the tests in handle_signal(). There were similar bugs in xen_failsafe_callback() of both 32 and 64-bit guests. If the fault was corrected and the normal return path was used then 0 was incorrectly pushed as the value for orig_ax. Signed-off-by: David Vrabel Acked-by: Jan Beulich Acked-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/entry_32.S | 8 +++++--- arch/x86/kernel/entry_64.S | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 623f2883747632..8f8e8eea9085d3 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -1016,7 +1016,7 @@ ENTRY(xen_sysenter_target) ENTRY(xen_hypervisor_callback) CFI_STARTPROC - pushl_cfi $0 + pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL TRACE_IRQS_OFF @@ -1058,14 +1058,16 @@ ENTRY(xen_failsafe_callback) 2: mov 8(%esp),%es 3: mov 12(%esp),%fs 4: mov 16(%esp),%gs + /* EAX == 0 => Category 1 (Bad segment) + EAX != 0 => Category 2 (Bad IRET) */ testl %eax,%eax popl_cfi %eax lea 16(%esp),%esp CFI_ADJUST_CFA_OFFSET -16 jz 5f addl $16,%esp - jmp iret_exc # EAX != 0 => Category 2 (Bad IRET) -5: pushl_cfi $0 # EAX == 0 => Category 1 (Bad segment) + jmp iret_exc +5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp ret_from_exception CFI_ENDPROC diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 69babd8c834f92..dcdd0ea33a3248 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1363,7 +1363,7 @@ ENTRY(xen_failsafe_callback) CFI_RESTORE r11 addq $0x30,%rsp CFI_ADJUST_CFA_OFFSET -0x30 - pushq_cfi $0 + pushq_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp error_exit CFI_ENDPROC From 081232d71a9618f2d1e87a23f8600675323d6103 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 16 Oct 2012 21:21:21 +0800 Subject: [PATCH 0276/1071] USB: cdc-acm: fix pipe type of write endpoint commit c5211187f7ff8e8dbff4ebf7c011ac4c0ffe319c upstream. If the write endpoint is interrupt type, usb_sndintpipe() should be passed to usb_fill_int_urb() instead of usb_sndbulkpipe(). Signed-off-by: Ming Lei Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e8007b8ed94673..53d14fa932047d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1234,7 +1234,7 @@ static int acm_probe(struct usb_interface *intf, if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, - usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + usb_sndintpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); else usb_fill_bulk_urb(snd->urb, usb_dev, From 2a0a93395560888f997be62581eca0d87c4bebb9 Mon Sep 17 00:00:00 2001 From: Nicolas Boullis Date: Tue, 16 Oct 2012 00:06:23 +0200 Subject: [PATCH 0277/1071] usb: acm: fix the computation of the number of data bits commit 301a29da6e891e7eb95c843af0ecdbe86d01f723 upstream. The current code assumes that CSIZE is 0000060, which appears to be wrong on some arches (such as powerpc). Signed-off-by: Nicolas Boullis Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 53d14fa932047d..84f7dffbd96a9a 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -818,10 +818,6 @@ static const __u32 acm_tty_speed[] = { 2500000, 3000000, 3500000, 4000000 }; -static const __u8 acm_tty_size[] = { - 5, 6, 7, 8 -}; - static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { @@ -835,7 +831,21 @@ static void acm_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; + switch (termios->c_cflag & CSIZE) { + case CS5: + newline.bDataBits = 5; + break; + case CS6: + newline.bDataBits = 6; + break; + case CS7: + newline.bDataBits = 7; + break; + case CS8: + default: + newline.bDataBits = 8; + break; + } /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); From 6547e27d6b60717040b105bafb5a4f4d5d5c0f79 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:58 +0200 Subject: [PATCH 0278/1071] USB: io_ti: fix port-data memory leak commit 003615302a16579531932576bcd9582ddeba9018 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 91 ++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 3936904c641969..8ddb06978d2472 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2594,12 +2594,7 @@ static void edge_break(struct tty_struct *tty, int break_state) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; - struct usb_device *dev; int status; - int i; - - dev = serial->dev; /* create our private serial structure */ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); @@ -2617,40 +2612,7 @@ static int edge_startup(struct usb_serial *serial) return status; } - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - goto cleanup; - } - spin_lock_init(&edge_port->ep_lock); - if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - kfree(edge_port); - goto cleanup; - } - edge_port->port = serial->port[i]; - edge_port->edge_serial = edge_serial; - usb_set_serial_port_data(serial->port[i], edge_port); - edge_port->bUartMode = default_uart_mode; - } - return 0; - -cleanup: - for (--i; i >= 0; --i) { - edge_port = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&edge_port->write_fifo); - kfree(edge_port); - usb_set_serial_port_data(serial->port[i], NULL); - } - kfree(edge_serial); - usb_set_serial_data(serial, NULL); - return -ENOMEM; } static void edge_disconnect(struct usb_serial *serial) @@ -2660,19 +2622,54 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { - int i; + kfree(usb_get_serial_data(serial)); +} + +static int edge_port_probe(struct usb_serial_port *port) +{ struct edgeport_port *edge_port; + int ret; - dbg("%s", __func__); + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, + GFP_KERNEL); + if (ret) { + kfree(edge_port); + return -ENOMEM; + } - for (i = 0; i < serial->num_ports; ++i) { - edge_port = usb_get_serial_port_data(serial->port[i]); + ret = edge_create_sysfs_attrs(port); + if (ret) { kfifo_free(&edge_port->write_fifo); kfree(edge_port); + return ret; } - kfree(usb_get_serial_data(serial)); + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + edge_port->edge_serial = usb_get_serial_data(port->serial); + edge_port->bUartMode = default_uart_mode; + + usb_set_serial_port_data(port, edge_port); + + return 0; } +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + + edge_remove_sysfs_attrs(port); + kfifo_free(&edge_port->write_fifo); + kfree(edge_port); + + return 0; +} /* Sysfs Attributes */ @@ -2732,8 +2729,8 @@ static struct usb_serial_driver edgeport_1port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2763,8 +2760,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, From 2a73dc8b5746d4caf3d8624d5f6e20ce54351a9c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Oct 2012 11:43:28 +0200 Subject: [PATCH 0279/1071] USB: io_ti: fix sysfs-attribute creation commit 5d8c61bc283826827e1f06816c146bfc507d3834 upstream. Make sure port data is initialised before creating sysfs attributes to avoid a race. A recent patch ("USB: io_ti: fix port-data memory leak") got the sysfs-attribute creation and port-data initialisation ordering wrong. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 8ddb06978d2472..ccf297dbad965e 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2641,13 +2641,6 @@ static int edge_port_probe(struct usb_serial_port *port) return -ENOMEM; } - ret = edge_create_sysfs_attrs(port); - if (ret) { - kfifo_free(&edge_port->write_fifo); - kfree(edge_port); - return ret; - } - spin_lock_init(&edge_port->ep_lock); edge_port->port = port; edge_port->edge_serial = usb_get_serial_data(port->serial); @@ -2655,6 +2648,13 @@ static int edge_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, edge_port); + ret = edge_create_sysfs_attrs(port); + if (ret) { + kfifo_free(&edge_port->write_fifo); + kfree(edge_port); + return ret; + } + return 0; } From 9e9e9cf3d8712b1af470dbc3c2c7e4c6bb4b0531 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 18:20:54 +0200 Subject: [PATCH 0280/1071] USB: cyberjack: fix port-data memory leak commit a9556040119a63d06fd5238d47f5b683fba4178b upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cyberjack.c | 48 ++++++++++++++-------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 3aa0b530f68ee8..bfec6f4b8f86f9 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -57,9 +57,9 @@ static bool debug; #define CYBERJACK_PRODUCT_ID 0x0100 /* Function prototypes */ -static int cyberjack_startup(struct usb_serial *serial); static void cyberjack_disconnect(struct usb_serial *serial); -static void cyberjack_release(struct usb_serial *serial); +static int cyberjack_port_probe(struct usb_serial_port *port); +static int cyberjack_port_remove(struct usb_serial_port *port); static int cyberjack_open(struct tty_struct *tty, struct usb_serial_port *port); static void cyberjack_close(struct usb_serial_port *port); @@ -85,9 +85,9 @@ static struct usb_serial_driver cyberjack_device = { .description = "Reiner SCT Cyberjack USB card reader", .id_table = id_table, .num_ports = 1, - .attach = cyberjack_startup, .disconnect = cyberjack_disconnect, - .release = cyberjack_release, + .port_probe = cyberjack_port_probe, + .port_remove = cyberjack_port_remove, .open = cyberjack_open, .close = cyberjack_close, .write = cyberjack_write, @@ -109,55 +109,45 @@ struct cyberjack_private { short wrsent; /* Data already sent */ }; -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int cyberjack_startup(struct usb_serial *serial) +static int cyberjack_port_probe(struct usb_serial_port *port) { struct cyberjack_private *priv; - int i; + int result; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); if (!priv) return -ENOMEM; - /* set initial values */ spin_lock_init(&priv->lock); priv->rdtodo = 0; priv->wrfilled = 0; priv->wrsent = 0; - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + usb_set_serial_port_data(port, priv); - for (i = 0; i < serial->num_ports; ++i) { - int result; - result = usb_submit_urb(serial->port[i]->interrupt_in_urb, - GFP_KERNEL); - if (result) - dev_err(&serial->dev->dev, - "usb_submit_urb(read int) failed\n"); - dbg("%s - usb_submit_urb(int urb)", __func__); - } + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); return 0; } -static void cyberjack_disconnect(struct usb_serial *serial) +static int cyberjack_port_remove(struct usb_serial_port *port) { - int i; + struct cyberjack_private *priv; - for (i = 0; i < serial->num_ports; ++i) - usb_kill_urb(serial->port[i]->interrupt_in_urb); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } -static void cyberjack_release(struct usb_serial *serial) +static void cyberjack_disconnect(struct usb_serial *serial) { int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - kfree(usb_get_serial_port_data(serial->port[i])); - } + for (i = 0; i < serial->num_ports; ++i) + usb_kill_urb(serial->port[i]->interrupt_in_urb); } static int cyberjack_open(struct tty_struct *tty, From da2f7d4a8ec01898617e0d1a1808c60b607e32fa Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 15 Oct 2012 11:20:22 +0200 Subject: [PATCH 0281/1071] usb: musb: am35xx: drop spurious unplugging a device commit 6ff1f3d3bd7c69c62ca5773b1b684bce42eff06a upstream. On AM3517, tx and rx interrupt are detected together with the disconnect event. This generates a kernel panic in musb_interrupt, because rx / tx are handled after disconnect. This issue was seen on a Technexion's TAM3517 SOM. Unplugging a device, tx / rx interrupts together with disconnect are detected. This brings to kernel panic like this: [ 68.526153] Unable to handle kernel NULL pointer dereference at virtual address 00000011 [ 68.534698] pgd = c0004000 [ 68.537536] [00000011] *pgd=00000000 [ 68.541351] Internal error: Oops: 17 [#1] ARM [ 68.545928] Modules linked in: [ 68.549163] CPU: 0 Not tainted (3.6.0-rc5-00020-g9e05905 #178) [ 68.555694] PC is at rxstate+0x8/0xdc [ 68.559539] LR is at musb_interrupt+0x98/0x858 [ 68.564239] pc : [] lr : [] psr: 40000193 [ 68.564239] sp : ce83fb40 ip : d0906410 fp : 00000000 [ 68.576293] r10: 00000000 r9 : cf3b0e40 r8 : 00000002 [ 68.581817] r7 : 00000019 r6 : 00000001 r5 : 00000001 r4 : 000000d4 [ 68.588684] r3 : 00000000 r2 : 00000000 r1 : ffffffcc r0 : cf23c108 [ 68.595550] Flags: nZcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment ke Note: this behavior is not seen with a USB hub, while it is easy to reproduce connecting a USB-pen directly to the USB-A of the board. Drop tx / rx interrupts if disconnect is detected. Signed-off-by: Stefano Babic CC: Felipe Balbi Tested-by: Dmitry Lifshitz Tested-by: Igor Grinberg Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/am35x.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 7a95ab87ac00fe..ee9ec137dc7346 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -312,6 +312,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ret = IRQ_HANDLED; } + /* Drop spurious RX and TX if device is disconnected */ + if (musb->int_usb & MUSB_INTR_DISCONNECT) { + musb->int_tx = 0; + musb->int_rx = 0; + } + if (musb->int_tx || musb->int_rx || musb->int_usb) ret |= musb_interrupt(musb); From e8449931df18b2078327a7286c237d1d95db7715 Mon Sep 17 00:00:00 2001 From: "Alexis R. Cortes" Date: Wed, 17 Oct 2012 14:09:12 -0500 Subject: [PATCH 0282/1071] usb: host: xhci: New system added for Compliance Mode Patch on SN65LVPE502CP commit 470809741a28c3092279f4e1f3f432e534d46068 upstream. This minor change adds a new system to which the "Fix Compliance Mode on SN65LVPE502CP Hardware" patch has to be applied also. System added: Vendor: Hewlett-Packard. System Model: Z1 Signed-off-by: Alexis R. Cortes Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a49868d938120d..0644f65b8d8c11 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -479,7 +479,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) if (strstr(dmi_product_name, "Z420") || strstr(dmi_product_name, "Z620") || - strstr(dmi_product_name, "Z820")) + strstr(dmi_product_name, "Z820") || + strstr(dmi_product_name, "Z1")) return true; return false; From 8b399c3d6ae4591e28cc1bdab911ce7ccc7c2d5d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:59 +0200 Subject: [PATCH 0283/1071] USB: iuu_phoenix: fix port-data memory leak commit 53636555b9190f88320d9d46cf142f8797895456 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 70 ++++++++++++++------------------ 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 22b1eb5040b764..c32f2a9afe01e5 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -80,64 +80,54 @@ struct iuu_private { u32 clk; }; - -static void iuu_free_buf(struct iuu_private *priv) +static int iuu_port_probe(struct usb_serial_port *port) { - kfree(priv->buf); - kfree(priv->dbgbuf); - kfree(priv->writebuf); -} + struct iuu_private *priv; + + priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; -static int iuu_alloc_buf(struct iuu_private *priv) -{ priv->buf = kzalloc(256, GFP_KERNEL); - priv->dbgbuf = kzalloc(256, GFP_KERNEL); - priv->writebuf = kzalloc(256, GFP_KERNEL); - if (!priv->buf || !priv->dbgbuf || !priv->writebuf) { - iuu_free_buf(priv); - dbg("%s problem allocation buffer", __func__); + if (!priv->buf) { + kfree(priv); return -ENOMEM; } - dbg("%s - Privates buffers allocation success", __func__); - return 0; -} -static int iuu_startup(struct usb_serial *serial) -{ - struct iuu_private *priv; - priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); - dbg("%s- priv allocation success", __func__); - if (!priv) + priv->writebuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->buf); + kfree(priv); return -ENOMEM; - if (iuu_alloc_buf(priv)) { + } + + priv->dbgbuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->writebuf); + kfree(priv->buf); kfree(priv); return -ENOMEM; } + priv->vcc = vcc_default; spin_lock_init(&priv->lock); init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[0], priv); + + usb_set_serial_port_data(port, priv); + return 0; } -/* Release function */ -static void iuu_release(struct usb_serial *serial) +static int iuu_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct iuu_private *priv = usb_get_serial_port_data(port); - if (!port) - return; - - if (priv) { - iuu_free_buf(priv); - dbg("%s - I will free all", __func__); - usb_set_serial_port_data(port, NULL); - dbg("%s - priv is not anymore in port structure", __func__); - kfree(priv); + kfree(priv->dbgbuf); + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); - dbg("%s priv is now kfree", __func__); - } + return 0; } static int iuu_tiocmset(struct tty_struct *tty, @@ -1241,8 +1231,8 @@ static struct usb_serial_driver iuu_device = { .tiocmset = iuu_tiocmset, .set_termios = iuu_set_termios, .init_termios = iuu_init_termios, - .attach = iuu_startup, - .release = iuu_release, + .port_probe = iuu_port_probe, + .port_remove = iuu_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { From e1d21d7119c98059424137340f8c3a405ee5ef3d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Oct 2012 10:52:17 +0200 Subject: [PATCH 0284/1071] USB: iuu_phoenix: fix sysfs-attribute creation commit 0978c9499944d0670338fd048a3bdb1624dc66dc upstream. Make sure sysfs attributes are created at port probe. A recent patch ("USB: iuu_phoenix: fix port-data memory leak") removed the sysfs-attribute creation by mistake. Reported-by: Yuanhan Liu Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index c32f2a9afe01e5..cdf0f994e883a5 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -60,6 +60,8 @@ static int iuu_cardout; static bool xmas; static int vcc_default = 5; +static int iuu_create_sysfs_attrs(struct usb_serial_port *port); +static int iuu_remove_sysfs_attrs(struct usb_serial_port *port); static void read_rxcmd_callback(struct urb *urb); struct iuu_private { @@ -83,6 +85,7 @@ struct iuu_private { static int iuu_port_probe(struct usb_serial_port *port) { struct iuu_private *priv; + int ret; priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); if (!priv) @@ -115,6 +118,14 @@ static int iuu_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, priv); + ret = iuu_create_sysfs_attrs(port); + if (ret) { + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); + return ret; + } + return 0; } @@ -122,6 +133,7 @@ static int iuu_port_remove(struct usb_serial_port *port) { struct iuu_private *priv = usb_get_serial_port_data(port); + iuu_remove_sysfs_attrs(port); kfree(priv->dbgbuf); kfree(priv->writebuf); kfree(priv->buf); @@ -1221,8 +1233,6 @@ static struct usb_serial_driver iuu_device = { .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, - .port_probe = iuu_create_sysfs_attrs, - .port_remove = iuu_remove_sysfs_attrs, .open = iuu_open, .close = iuu_close, .write = iuu_uart_write, From bb5c0c637f4f2dc8ed38f580881c40977980f031 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 18:20:52 +0200 Subject: [PATCH 0285/1071] USB: ark3116: fix NULL-pointer dereference commit 7bdce71822f471433dd3014692e9096996c7b5f0 upstream. Fix NULL-pointer dereference at release by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is NULL when release is called. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index f8ce97d8b0ad3c..a6758ffd9dbf68 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -126,9 +126,6 @@ static inline int calc_divisor(int bps) static int ark3116_attach(struct usb_serial *serial) { - struct usb_serial_port *port = serial->port[0]; - struct ark3116_private *priv; - /* make sure we have our end-points */ if ((serial->num_bulk_in == 0) || (serial->num_bulk_out == 0) || @@ -143,8 +140,15 @@ static int ark3116_attach(struct usb_serial *serial) return -EINVAL; } - priv = kzalloc(sizeof(struct ark3116_private), - GFP_KERNEL); + return 0; +} + +static int ark3116_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct ark3116_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -199,18 +203,15 @@ static int ark3116_attach(struct usb_serial *serial) return 0; } -static void ark3116_release(struct usb_serial *serial) +static int ark3116_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct ark3116_private *priv = usb_get_serial_port_data(port); /* device is closed, so URBs and DMA should be down */ - - usb_set_serial_port_data(port, NULL); - mutex_destroy(&priv->hw_lock); - kfree(priv); + + return 0; } static void ark3116_init_termios(struct tty_struct *tty) @@ -725,7 +726,8 @@ static struct usb_serial_driver ark3116_device = { .id_table = id_table, .num_ports = 1, .attach = ark3116_attach, - .release = ark3116_release, + .port_probe = ark3116_port_probe, + .port_remove = ark3116_port_remove, .set_termios = ark3116_set_termios, .init_termios = ark3116_init_termios, .ioctl = ark3116_ioctl, From 98ba808a0d98b7abe03543c2ddda6396d76e33ed Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:56 +0200 Subject: [PATCH 0286/1071] USB: f81232: fix port-data memory leak commit 3124d1d71d3df59d40b913b5481df58099e811d1 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/f81232.c | 43 +++++++++++++++---------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 499b15fd82f162..be944367fbc8bc 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -319,39 +319,30 @@ static int f81232_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } -static int f81232_startup(struct usb_serial *serial) +static int f81232_port_probe(struct usb_serial_port *port) { struct f81232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[i], priv); - } - return 0; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; } -static void f81232_release(struct usb_serial *serial) +static int f81232_port_remove(struct usb_serial_port *port) { - int i; struct f81232_private *priv; - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static struct usb_serial_driver f81232_device = { @@ -374,8 +365,8 @@ static struct usb_serial_driver f81232_device = { .tiocmset = f81232_tiocmset, .process_read_urb = f81232_process_read_urb, .read_int_callback = f81232_read_int_callback, - .attach = f81232_startup, - .release = f81232_release, + .port_probe = f81232_port_probe, + .port_remove = f81232_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { From 5b7cefbdd532b41aa75d25b7f0cdeca581e11e09 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:32 +0200 Subject: [PATCH 0287/1071] USB: oti6858: fix port-data memory leak commit 289b076f89c2c3260e914dad18ae12f193ea86d5 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/oti6858.c | 68 +++++++++++++++--------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 5976b65ab6ee68..3aa582e4a594ff 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -139,8 +139,8 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int oti6858_startup(struct usb_serial *serial); -static void oti6858_release(struct usb_serial *serial); +static int oti6858_port_probe(struct usb_serial_port *port); +static int oti6858_port_remove(struct usb_serial_port *port); /* device info */ static struct usb_serial_driver oti6858_device = { @@ -163,8 +163,8 @@ static struct usb_serial_driver oti6858_device = { .write_bulk_callback = oti6858_write_bulk_callback, .write_room = oti6858_write_room, .chars_in_buffer = oti6858_chars_in_buffer, - .attach = oti6858_startup, - .release = oti6858_release, + .port_probe = oti6858_port_probe, + .port_remove = oti6858_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -333,36 +333,33 @@ static void send_data(struct work_struct *work) usb_serial_port_softint(port); } -static int oti6858_startup(struct usb_serial *serial) +static int oti6858_port_probe(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct oti6858_private *priv; - int i; - - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); - if (!priv) - break; - - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->intr_wait); -/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */ -/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */ - priv->port = port; - INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); - INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); - - usb_set_serial_port_data(serial->port[i], priv); - } - if (i == serial->num_ports) - return 0; - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->intr_wait); + priv->port = port; + INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); + INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int oti6858_port_remove(struct usb_serial_port *port) +{ + struct oti6858_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -714,15 +711,6 @@ static int oti6858_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } - -static void oti6858_release(struct usb_serial *serial) -{ - int i; - - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); -} - static void oti6858_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; From 18bdc54d39fdbd37c5ca89cc1f48adde43eb33b1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 18:20:53 +0200 Subject: [PATCH 0288/1071] USB: belkin_sa: fix port-data memory leak commit fa919751a2d26a88140fc5810124dd81644efe51 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/belkin_sa.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 6b7365632951c6..89a3dd3035e2ad 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -47,8 +47,8 @@ static bool debug; #define DRIVER_DESC "USB Belkin Serial converter driver" /* function prototypes for a Belkin USB Serial Adapter F5U103 */ -static int belkin_sa_startup(struct usb_serial *serial); -static void belkin_sa_release(struct usb_serial *serial); +static int belkin_sa_port_probe(struct usb_serial_port *port); +static int belkin_sa_port_remove(struct usb_serial_port *port); static int belkin_sa_open(struct tty_struct *tty, struct usb_serial_port *port); static void belkin_sa_close(struct usb_serial_port *port); @@ -90,8 +90,8 @@ static struct usb_serial_driver belkin_device = { .break_ctl = belkin_sa_break_ctl, .tiocmget = belkin_sa_tiocmget, .tiocmset = belkin_sa_tiocmset, - .attach = belkin_sa_startup, - .release = belkin_sa_release, + .port_probe = belkin_sa_port_probe, + .port_remove = belkin_sa_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -120,17 +120,15 @@ struct belkin_sa_private { (c), BELKIN_SA_SET_REQUEST_TYPE, \ (v), 0, NULL, 0, WDR_TIMEOUT) -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int belkin_sa_startup(struct usb_serial *serial) +static int belkin_sa_port_probe(struct usb_serial_port *port) { - struct usb_device *dev = serial->dev; + struct usb_device *dev = port->serial->dev; struct belkin_sa_private *priv; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL); if (!priv) - return -1; /* error */ - /* set initial values for control structures */ + return -ENOMEM; + spin_lock_init(&priv->lock); priv->control_state = 0; priv->last_lsr = 0; @@ -142,18 +140,19 @@ static int belkin_sa_startup(struct usb_serial *serial) le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control); - init_waitqueue_head(&serial->port[0]->write_wait); - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; } -static void belkin_sa_release(struct usb_serial *serial) +static int belkin_sa_port_remove(struct usb_serial_port *port) { - int i; + struct belkin_sa_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int belkin_sa_open(struct tty_struct *tty, From 4147db8f196114198142b181f90d062602528e82 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 15:47:21 +0200 Subject: [PATCH 0289/1071] USB: pl2303: fix port-data memory leak commit 8bf769eb5f6efc33f95088850f33fcc05d28b508 upstream. Fix port-data memory leak by allocating and freeing port data in port_probe/remove rather than in attach/release, and by introducing serial private data to store the device type which is interface rather than port specific. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 90 ++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 13b8dd6481f565..4d8d2100d6e00d 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -135,12 +135,15 @@ enum pl2303_type { HX, /* HX version of the pl2303 chip */ }; +struct pl2303_serial_private { + enum pl2303_type type; +}; + struct pl2303_private { spinlock_t lock; wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; - enum pl2303_type type; }; static int pl2303_vendor_read(__u16 value, __u16 index, @@ -169,14 +172,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index, static int pl2303_startup(struct usb_serial *serial) { - struct pl2303_private *priv; + struct pl2303_serial_private *spriv; enum pl2303_type type = type_0; unsigned char *buf; - int i; + + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; buf = kmalloc(10, GFP_KERNEL); - if (buf == NULL) + if (!buf) { + kfree(spriv); return -ENOMEM; + } if (serial->dev->descriptor.bDeviceClass == 0x02) type = type_0; @@ -188,15 +196,8 @@ static int pl2303_startup(struct usb_serial *serial) type = type_1; dev_dbg(&serial->interface->dev, "device type: %d\n", type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i], priv); - } + spriv->type = type; + usb_set_serial_data(serial, spriv); pl2303_vendor_read(0x8484, 0, serial, buf); pl2303_vendor_write(0x0404, 0, serial); @@ -215,15 +216,40 @@ static int pl2303_startup(struct usb_serial *serial) kfree(buf); return 0; +} -cleanup: - kfree(buf); - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; +static void pl2303_release(struct usb_serial *serial) +{ + struct pl2303_serial_private *spriv; + + spriv = usb_get_serial_data(serial); + kfree(spriv); +} + +static int pl2303_port_probe(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int pl2303_port_remove(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int set_control_lines(struct usb_device *dev, u8 value) @@ -242,6 +268,7 @@ static void pl2303_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int cflag; @@ -325,7 +352,7 @@ static void pl2303_set_termios(struct tty_struct *tty, } if (baud > 1228800) { /* type_0, type_1 only support up to 1228800 baud */ - if (priv->type != HX) + if (spriv->type != HX) baud = 1228800; else if (baud > 6000000) baud = 6000000; @@ -428,7 +455,7 @@ static void pl2303_set_termios(struct tty_struct *tty, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CRTSCTS) { - if (priv->type == HX) + if (spriv->type == HX) pl2303_vendor_write(0x0, 0x61, serial); else pl2303_vendor_write(0x0, 0x41, serial); @@ -470,10 +497,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; - struct pl2303_private *priv = usb_get_serial_port_data(port); + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int result; - if (priv->type != HX) { + if (spriv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); } else { @@ -657,17 +684,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) dev_err(&port->dev, "error sending break = %d\n", result); } -static void pl2303_release(struct usb_serial *serial) -{ - int i; - struct pl2303_private *priv; - - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} - static void pl2303_update_line_status(struct usb_serial_port *port, unsigned char *data, unsigned int actual_length) @@ -829,6 +845,8 @@ static struct usb_serial_driver pl2303_device = { .read_int_callback = pl2303_read_int_callback, .attach = pl2303_startup, .release = pl2303_release, + .port_probe = pl2303_port_probe, + .port_remove = pl2303_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { From d3189b39faeead89a892e8c2b1afdad0f22b6303 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:34 +0200 Subject: [PATCH 0290/1071] USB: ssu100: fix port-data memory leak commit 638b9e15233c9570bce65301aa9877235316b9f0 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 3fee23bf0c1417..fe3a8a0132dd6a 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -69,13 +69,6 @@ struct ssu100_port_private { struct async_icount icount; }; -static void ssu100_release(struct usb_serial *serial) -{ - struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); - - kfree(priv); -} - static inline int ssu100_control_msg(struct usb_device *dev, u8 request, u16 data, u16 index) { @@ -443,22 +436,34 @@ static int ssu100_ioctl(struct tty_struct *tty, } static int ssu100_attach(struct usb_serial *serial) +{ + return ssu100_initdevice(serial->dev); +} + +static int ssu100_port_probe(struct usb_serial_port *port) { struct ssu100_port_private *priv; - struct usb_serial_port *port = *serial->port; priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*priv)); + if (!priv) return -ENOMEM; - } spin_lock_init(&priv->status_lock); init_waitqueue_head(&priv->delta_msr_wait); + usb_set_serial_port_data(port, priv); - return ssu100_initdevice(serial->dev); + return 0; +} + +static int ssu100_port_remove(struct usb_serial_port *port) +{ + struct ssu100_port_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int ssu100_tiocmget(struct tty_struct *tty) @@ -649,7 +654,8 @@ static struct usb_serial_driver ssu100_device = { .open = ssu100_open, .close = ssu100_close, .attach = ssu100_attach, - .release = ssu100_release, + .port_probe = ssu100_port_probe, + .port_remove = ssu100_port_remove, .dtr_rts = ssu100_dtr_rts, .process_read_urb = ssu100_process_read_urb, .tiocmget = ssu100_tiocmget, From af4af5941e5be633846df08359820d4c1e886fbb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:35:02 +0200 Subject: [PATCH 0291/1071] USB: kobil_sct: fix port-data memory leak commit 95940a04bfe8a4d246f4ca17c6a3b00148bdead0 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index fafeabb64c5531..a579fdc2152e68 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -56,8 +56,8 @@ static bool debug; /* Function prototypes */ -static int kobil_startup(struct usb_serial *serial); -static void kobil_release(struct usb_serial *serial); +static int kobil_port_probe(struct usb_serial_port *probe); +static int kobil_port_remove(struct usb_serial_port *probe); static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); static void kobil_close(struct usb_serial_port *port); static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -91,8 +91,8 @@ static struct usb_serial_driver kobil_device = { .description = "KOBIL USB smart card terminal", .id_table = id_table, .num_ports = 1, - .attach = kobil_startup, - .release = kobil_release, + .port_probe = kobil_port_probe, + .port_remove = kobil_port_remove, .ioctl = kobil_ioctl, .set_termios = kobil_set_termios, .init_termios = kobil_init_termios, @@ -119,9 +119,10 @@ struct kobil_private { }; -static int kobil_startup(struct usb_serial *serial) +static int kobil_port_probe(struct usb_serial_port *port) { int i; + struct usb_serial *serial = port->serial; struct kobil_private *priv; struct usb_device *pdev; struct usb_host_config *actconfig; @@ -152,7 +153,7 @@ static int kobil_startup(struct usb_serial *serial) printk(KERN_DEBUG "KOBIL KAAN SIM detected\n"); break; } - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); /* search for the necessary endpoints */ pdev = serial->dev; @@ -180,12 +181,14 @@ static int kobil_startup(struct usb_serial *serial) } -static void kobil_release(struct usb_serial *serial) +static int kobil_port_remove(struct usb_serial_port *port) { - int i; + struct kobil_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static void kobil_init_termios(struct tty_struct *tty) From 117d01aa6303b6b7d3383077ed2551283d1ca8a3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:55 +0200 Subject: [PATCH 0292/1071] USB: cypress_m8: fix port-data memory leak commit 5c1a0f418d8d985f3a62849bcac43fc5404cc592 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 82 ++++++++++++++++----------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index b78c34eb5d3f6f..5ad6e7db080cd4 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -124,10 +124,10 @@ struct cypress_private { }; /* function prototypes for the Cypress USB to serial device */ -static int cypress_earthmate_startup(struct usb_serial *serial); -static int cypress_hidcom_startup(struct usb_serial *serial); -static int cypress_ca42v2_startup(struct usb_serial *serial); -static void cypress_release(struct usb_serial *serial); +static int cypress_earthmate_port_probe(struct usb_serial_port *port); +static int cypress_hidcom_port_probe(struct usb_serial_port *port); +static int cypress_ca42v2_port_probe(struct usb_serial_port *port); +static int cypress_port_remove(struct usb_serial_port *port); static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port); static void cypress_close(struct usb_serial_port *port); static void cypress_dtr_rts(struct usb_serial_port *port, int on); @@ -157,8 +157,8 @@ static struct usb_serial_driver cypress_earthmate_device = { .description = "DeLorme Earthmate USB", .id_table = id_table_earthmate, .num_ports = 1, - .attach = cypress_earthmate_startup, - .release = cypress_release, + .port_probe = cypress_earthmate_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -183,8 +183,8 @@ static struct usb_serial_driver cypress_hidcom_device = { .description = "HID->COM RS232 Adapter", .id_table = id_table_cyphidcomrs232, .num_ports = 1, - .attach = cypress_hidcom_startup, - .release = cypress_release, + .port_probe = cypress_hidcom_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -209,8 +209,8 @@ static struct usb_serial_driver cypress_ca42v2_device = { .description = "Nokia CA-42 V2 Adapter", .id_table = id_table_nokiaca42v2, .num_ports = 1, - .attach = cypress_ca42v2_startup, - .release = cypress_release, + .port_probe = cypress_ca42v2_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -437,10 +437,10 @@ static void cypress_set_dead(struct usb_serial_port *port) *****************************************************************************/ -static int generic_startup(struct usb_serial *serial) +static int cypress_generic_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) @@ -489,15 +489,17 @@ static int generic_startup(struct usb_serial *serial) } -static int cypress_earthmate_startup(struct usb_serial *serial) +static int cypress_earthmate_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dbg("%s - Failed setting up port %d", __func__, port->number); - return 1; + return ret; } priv = usb_get_serial_port_data(port); @@ -517,54 +519,52 @@ static int cypress_earthmate_startup(struct usb_serial *serial) } return 0; -} /* cypress_earthmate_startup */ - +} -static int cypress_hidcom_startup(struct usb_serial *serial) +static int cypress_hidcom_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; + int ret; - if (generic_startup(serial)) { - dbg("%s - Failed setting up port %d", __func__, - serial->port[0]->number); - return 1; + ret = cypress_generic_port_probe(port); + if (ret) { + dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); + return ret; } - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); priv->chiptype = CT_CYPHIDCOM; return 0; -} /* cypress_hidcom_startup */ - +} -static int cypress_ca42v2_startup(struct usb_serial *serial) +static int cypress_ca42v2_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; + int ret; - if (generic_startup(serial)) { - dbg("%s - Failed setting up port %d", __func__, - serial->port[0]->number); - return 1; + ret = cypress_generic_port_probe(port); + if (ret) { + dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); + return ret; } - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); priv->chiptype = CT_CA42V2; return 0; -} /* cypress_ca42v2_startup */ - +} -static void cypress_release(struct usb_serial *serial) +static int cypress_port_remove(struct usb_serial_port *port) { struct cypress_private *priv; - /* all open ports are closed at this point */ - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); + + kfifo_free(&priv->write_fifo); + kfree(priv); - if (priv) { - kfifo_free(&priv->write_fifo); - kfree(priv); - } + return 0; } From fa21e53e263194b744e0a5b3d5676aa31a6ef0ef Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 15 Oct 2012 15:47:20 +0200 Subject: [PATCH 0293/1071] USB: cp210x: fix port-data memory leak commit 4295fe7791a1b20c90cbaaa6f23f2fb94218b8a7 upstream. Fix port data memory leak by replacing port private data with serial private data. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release. The private data is used to store the control interface number, but as this is the same for all ports on an interface it should be stored as usb-serial data anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 41 +++++++++++++++---------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 1e71079ce33b71..4ea9e330058657 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -164,7 +164,7 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); -struct cp210x_port_private { +struct cp210x_serial_private { __u8 bInterfaceNumber; }; @@ -278,7 +278,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -294,7 +294,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_INTERFACE_TO_HOST, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_GET_TIMEOUT); /* Convert data into an array of integers */ @@ -326,7 +326,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -348,13 +348,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_SET_TIMEOUT); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, data[0], - port_priv->bInterfaceNumber, NULL, 0, + spriv->bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); } @@ -854,37 +854,30 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) static int cp210x_startup(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct usb_host_interface *cur_altsetting; + struct cp210x_serial_private *spriv; /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); - for (i = 0; i < serial->num_ports; i++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) - return -ENOMEM; + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; - memset(port_priv, 0x00, sizeof(*port_priv)); - port_priv->bInterfaceNumber = - serial->interface->cur_altsetting->desc.bInterfaceNumber; + cur_altsetting = serial->interface->cur_altsetting; + spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber; - usb_set_serial_port_data(serial->port[i], port_priv); - } + usb_set_serial_data(serial, spriv); return 0; } static void cp210x_release(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct cp210x_serial_private *spriv; - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - kfree(port_priv); - usb_set_serial_port_data(serial->port[i], NULL); - } + spriv = usb_get_serial_data(serial); + kfree(spriv); } module_usb_serial_driver(serial_drivers, id_table); From 5592d451ce00a108312bf2152bde273e8532cf8c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:33 +0200 Subject: [PATCH 0294/1071] USB: spcp8x5: fix port-data memory leak commit bf90ff5f3b8f67e5b42df4ea4fd543f8010a2676 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 46 ++++++++++++++---------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index cad60898471032..2451c088203a2f 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -159,13 +159,10 @@ struct spcp8x5_private { u8 line_status; }; -/* desc : when device plug in,this function would be called. - * thanks to usb_serial subsystem,then do almost every things for us. And what - * we should do just alloc the buffer */ -static int spcp8x5_startup(struct usb_serial *serial) +static int spcp8x5_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct spcp8x5_private *priv; - int i; enum spcp8x5_type type = SPCP825_007_TYPE; u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); @@ -182,34 +179,27 @@ static int spcp8x5_startup(struct usb_serial *serial) type = SPCP825_PHILIP_TYPE; dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL); - if (!priv) - goto cleanup; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i] , priv); - } + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + priv->type = type; + + usb_set_serial_port_data(port , priv); return 0; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i] , NULL); - } - return -ENOMEM; } -/* call when the device plug out. free all the memory alloced by probe */ -static void spcp8x5_release(struct usb_serial *serial) +static int spcp8x5_port_remove(struct usb_serial_port *port) { - int i; + struct spcp8x5_private *priv; - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } /* set the modem control line of the device. @@ -651,8 +641,8 @@ static struct usb_serial_driver spcp8x5_device = { .ioctl = spcp8x5_ioctl, .tiocmget = spcp8x5_tiocmget, .tiocmset = spcp8x5_tiocmset, - .attach = spcp8x5_startup, - .release = spcp8x5_release, + .port_probe = spcp8x5_port_probe, + .port_remove = spcp8x5_port_remove, .process_read_urb = spcp8x5_process_read_urb, }; From ef7c9b6a9cc09853a449a43050153cc785788d16 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 16:31:35 +0200 Subject: [PATCH 0295/1071] USB: ti_usb_3410_5052: fix port-data memory leak commit 51ef847df74632e7cfdf952afc3887de105b8b35 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 88 +++++++++++++-------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index a4404f5ad68ec5..33537bb778d0e4 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -98,6 +98,8 @@ struct ti_device { static int ti_startup(struct usb_serial *serial); static void ti_release(struct usb_serial *serial); +static int ti_port_probe(struct usb_serial_port *port); +static int ti_port_remove(struct usb_serial_port *port); static int ti_open(struct tty_struct *tty, struct usb_serial_port *port); static void ti_close(struct usb_serial_port *port); static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -223,6 +225,8 @@ static struct usb_serial_driver ti_1port_device = { .num_ports = 1, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -251,6 +255,8 @@ static struct usb_serial_driver ti_2port_device = { .num_ports = 2, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -358,11 +364,8 @@ module_exit(ti_exit); static int ti_startup(struct usb_serial *serial) { struct ti_device *tdev; - struct ti_port *tport; struct usb_device *dev = serial->dev; int status; - int i; - dbg("%s - product 0x%4X, num configurations %d, configuration value %d", __func__, le16_to_cpu(dev->descriptor.idProduct), @@ -409,42 +412,8 @@ static int ti_startup(struct usb_serial *serial) goto free_tdev; } - /* set up port structures */ - for (i = 0; i < serial->num_ports; ++i) { - tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL); - if (tport == NULL) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - status = -ENOMEM; - goto free_tports; - } - spin_lock_init(&tport->tp_lock); - tport->tp_uart_base_addr = (i == 0 ? - TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); - tport->tp_closing_wait = closing_wait; - init_waitqueue_head(&tport->tp_msr_wait); - init_waitqueue_head(&tport->tp_write_wait); - if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - kfree(tport); - status = -ENOMEM; - goto free_tports; - } - tport->tp_port = serial->port[i]; - tport->tp_tdev = tdev; - usb_set_serial_port_data(serial->port[i], tport); - tport->tp_uart_mode = 0; /* default is RS232 */ - } - return 0; -free_tports: - for (--i; i >= 0; --i) { - tport = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&tport->write_fifo); - kfree(tport); - usb_set_serial_port_data(serial->port[i], NULL); - } free_tdev: kfree(tdev); usb_set_serial_data(serial, NULL); @@ -454,21 +423,50 @@ static int ti_startup(struct usb_serial *serial) static void ti_release(struct usb_serial *serial) { - int i; struct ti_device *tdev = usb_get_serial_data(serial); + + kfree(tdev); +} + +static int ti_port_probe(struct usb_serial_port *port) +{ struct ti_port *tport; - for (i = 0; i < serial->num_ports; ++i) { - tport = usb_get_serial_port_data(serial->port[i]); - if (tport) { - kfifo_free(&tport->write_fifo); - kfree(tport); - } + tport = kzalloc(sizeof(*tport), GFP_KERNEL); + if (!tport) + return -ENOMEM; + + spin_lock_init(&tport->tp_lock); + if (port == port->serial->port[0]) + tport->tp_uart_base_addr = TI_UART1_BASE_ADDR; + else + tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; + tport->tp_closing_wait = closing_wait; + init_waitqueue_head(&tport->tp_msr_wait); + init_waitqueue_head(&tport->tp_write_wait); + if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { + kfree(tport); + return -ENOMEM; } + tport->tp_port = port; + tport->tp_tdev = usb_get_serial_data(port->serial); + tport->tp_uart_mode = 0; /* default is RS232 */ - kfree(tdev); + usb_set_serial_port_data(port, tport); + + return 0; } +static int ti_port_remove(struct usb_serial_port *port) +{ + struct ti_port *tport; + + tport = usb_get_serial_port_data(port); + kfifo_free(&tport->write_fifo); + kfree(tport); + + return 0; +} static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) { From 982d0e9cbef68c69fb85e64d897e8cf77c4877e9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:35:01 +0200 Subject: [PATCH 0296/1071] USB: kl5kusb105: fix port-data memory leak commit 99a6f73c495c420df826e5b267fb073fd6766fc3 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kl5kusb105.c | 66 ++++++++++++--------------------- 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 5bed59cd5776d0..366ddee63a656d 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -62,8 +62,8 @@ static bool debug; /* * Function prototypes */ -static int klsi_105_startup(struct usb_serial *serial); -static void klsi_105_release(struct usb_serial *serial); +static int klsi_105_port_probe(struct usb_serial_port *port); +static int klsi_105_port_remove(struct usb_serial_port *port); static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); static void klsi_105_close(struct usb_serial_port *port); static void klsi_105_set_termios(struct tty_struct *tty, @@ -101,8 +101,8 @@ static struct usb_serial_driver kl5kusb105d_device = { /*.break_ctl = klsi_105_break_ctl,*/ .tiocmget = klsi_105_tiocmget, .tiocmset = klsi_105_tiocmset, - .attach = klsi_105_startup, - .release = klsi_105_release, + .port_probe = klsi_105_port_probe, + .port_remove = klsi_105_port_remove, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, .process_read_urb = klsi_105_process_read_urb, @@ -225,58 +225,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, * Driver's tty interface functions */ -static int klsi_105_startup(struct usb_serial *serial) +static int klsi_105_port_probe(struct usb_serial_port *port) { struct klsi_105_private *priv; - int i; - /* check if we support the product id (see keyspan.c) - * FIXME - */ + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* allocate the private data structure */ - for (i = 0; i < serial->num_ports; i++) { - priv = kmalloc(sizeof(struct klsi_105_private), - GFP_KERNEL); - if (!priv) { - dbg("%skmalloc for klsi_105_private failed.", __func__); - i--; - goto err_cleanup; - } - /* set initial values for control structures */ - priv->cfg.pktlen = 5; - priv->cfg.baudrate = kl5kusb105a_sio_b9600; - priv->cfg.databits = kl5kusb105a_dtb_8; - priv->cfg.unknown1 = 0; - priv->cfg.unknown2 = 1; + /* set initial values for control structures */ + priv->cfg.pktlen = 5; + priv->cfg.baudrate = kl5kusb105a_sio_b9600; + priv->cfg.databits = kl5kusb105a_dtb_8; + priv->cfg.unknown1 = 0; + priv->cfg.unknown2 = 1; - priv->line_state = 0; + priv->line_state = 0; - usb_set_serial_port_data(serial->port[i], priv); + spin_lock_init(&priv->lock); - spin_lock_init(&priv->lock); + /* priv->termios is left uninitialized until port opening */ - /* priv->termios is left uninitialized until port opening */ - init_waitqueue_head(&serial->port[i]->write_wait); - } + usb_set_serial_port_data(port, priv); return 0; - -err_cleanup: - for (; i >= 0; i--) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; } -static void klsi_105_release(struct usb_serial *serial) +static int klsi_105_port_remove(struct usb_serial_port *port) { - int i; + struct klsi_105_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) From 12ddc74e8e25107eda81aceb74e3311c1480b381 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:34:57 +0200 Subject: [PATCH 0297/1071] USB: io_edgeport: fix port-data memory leak commit c27f3efc56080a246f6ab7f57f0a6f56d256d769 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 54 +++++++++++++++++--------------- drivers/usb/serial/io_tables.h | 8 +++++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index e1f5ccd1e8f8c6..dca27a5269f765 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -228,6 +228,8 @@ static int edge_get_icount(struct tty_struct *tty, static int edge_startup(struct usb_serial *serial); static void edge_disconnect(struct usb_serial *serial); static void edge_release(struct usb_serial *serial); +static int edge_port_probe(struct usb_serial_port *port); +static int edge_port_remove(struct usb_serial_port *port); #include "io_tables.h" /* all of the devices that this driver supports */ @@ -2921,9 +2923,8 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; struct usb_device *dev; - int i, j; + int i; int response; bool interrupt_in_found; bool bulk_in_found; @@ -3007,26 +3008,6 @@ static int edge_startup(struct usb_serial *serial) /* we set up the pointers to the endpoints in the edge_open function, * as the structures aren't created yet. */ - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - for (j = 0; j < i; ++j) { - kfree(usb_get_serial_port_data(serial->port[j])); - usb_set_serial_port_data(serial->port[j], - NULL); - } - usb_set_serial_data(serial, NULL); - kfree(edge_serial); - return -ENOMEM; - } - spin_lock_init(&edge_port->ep_lock); - edge_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], edge_port); - } - response = 0; if (edge_serial->is_epic) { @@ -3175,12 +3156,35 @@ static void edge_release(struct usb_serial *serial) dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); - kfree(edge_serial); } +static int edge_port_probe(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + + usb_set_serial_port_data(port, edge_port); + + return 0; +} + +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + kfree(edge_port); + + return 0; +} + module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 350afddb55ba8c..1511dd0ad32426 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport_4port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport_8port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -197,6 +203,8 @@ static struct usb_serial_driver epic_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, From d50da5d33094e51c22433e0d14acd369657aedfa Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Oct 2012 13:35:00 +0200 Subject: [PATCH 0298/1071] USB: keyspan_pda: fix port-data memory leak commit 94ab71ce288921490ca857e25ad174e1921b1e29 upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index a4ac3cfeffc4b8..1e73171625e0ab 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -735,29 +735,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); #endif -static int keyspan_pda_startup(struct usb_serial *serial) +static int keyspan_pda_port_probe(struct usb_serial_port *port) { struct keyspan_pda_private *priv; - /* allocate the private data structures for all ports. Well, for all - one ports. */ - priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL); if (!priv) - return 1; /* error */ - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + return -ENOMEM; + INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); - priv->serial = serial; - priv->port = serial->port[0]; + priv->serial = port->serial; + priv->port = port; + + usb_set_serial_port_data(port, priv); + return 0; } -static void keyspan_pda_release(struct usb_serial *serial) +static int keyspan_pda_port_remove(struct usb_serial_port *port) { - kfree(usb_get_serial_port_data(serial->port[0])); + struct keyspan_pda_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } #ifdef KEYSPAN @@ -808,8 +812,8 @@ static struct usb_serial_driver keyspan_pda_device = { .break_ctl = keyspan_pda_break_ctl, .tiocmget = keyspan_pda_tiocmget, .tiocmset = keyspan_pda_tiocmset, - .attach = keyspan_pda_startup, - .release = keyspan_pda_release, + .port_probe = keyspan_pda_port_probe, + .port_remove = keyspan_pda_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { From 769492bc4ff326a6eb9773bf89c26d5ea26f6533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 18 Oct 2012 17:19:53 +0200 Subject: [PATCH 0299/1071] USB: option: blacklist net interface on ZTE devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1452df6f1b7e396d89c2a1fdbdc0e0e839f97671 upstream. Based on information from the ZTE Windows drivers. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 68 ++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5f30800663b238..e0f85b05106770 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -503,11 +503,19 @@ static const struct option_blacklist_info net_intf5_blacklist = { .reserved = BIT(5), }; +static const struct option_blacklist_info net_intf6_blacklist = { + .reserved = BIT(6), +}; + static const struct option_blacklist_info zte_mf626_blacklist = { .sendsetup = BIT(0) | BIT(1), .reserved = BIT(4), }; +static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -853,13 +861,19 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, @@ -872,7 +886,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, @@ -886,7 +901,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1002,18 +1018,24 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_1255_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) }, @@ -1071,15 +1093,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, From 11c7a299c9846320859916e81f0f5d38fc596a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 18 Oct 2012 17:14:17 +0200 Subject: [PATCH 0300/1071] USB: option: add more ZTE devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4b35f1c52943851b310afb09047bfe991ac8f5ae upstream. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e0f85b05106770..a0542ca03a3fd0 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -895,6 +895,12 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */ + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), @@ -903,6 +909,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1080,8 +1088,16 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, From 740b0a623f05bbb796a441e2c51ebfe37eef1c21 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Oct 2012 11:58:00 +0300 Subject: [PATCH 0301/1071] usb: dwc3: gadget: fix 'endpoint always busy' bug commit 041d81f493d90c940ec41f0ec98bc7c4f2fba431 upstream. If a USB transfer has already been started, meaning we have already issued StartTransfer command to that particular endpoint, DWC3_EP_BUSY flag has also already been set. When we try to cancel this transfer which is already in controller's cache, we will not receive XferComplete event and we must clear DWC3_EP_BUSY in order to allow subsequent requests to be properly started. The best place to clear that flag is right after issuing DWC3_DEPCMD_ENDTRANSFER. Reported-by: Moiz Sonasath Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c2813c2b005a8e..eb0fd100cfa8c1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1899,6 +1899,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); WARN_ON_ONCE(ret); dep->resource_index = 0; + dep->flags &= ~DWC3_EP_BUSY; } static void dwc3_stop_active_transfers(struct dwc3 *dwc) From 6a154bb60bfcbc91b515a94ee68e35c3b4b01b7c Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 3 Oct 2012 11:18:05 -0700 Subject: [PATCH 0302/1071] usb: Don't enable LPM if the exit latency is zero. commit ae8963adb4ad8c5f2a89ca1d99fb7bb721e7599f upstream. Some USB 3.0 devices signal that they don't implement Link PM by having all zeroes in the U1/U2 exit latencies in their SuperSpeed BOS descriptor. Don found that a Western Digital device he has experiences transfer errors when LPM is enabled. The lsusb shows the U1/U2 exit latencies are set to zero: Binary Object Store Descriptor: bLength 5 bDescriptorType 15 wTotalLength 22 bNumDeviceCaps 2 SuperSpeed USB Device Capability: bLength 10 bDescriptorType 16 bDevCapabilityType 3 bmAttributes 0x00 Latency Tolerance Messages (LTM) Supported wSpeedsSupported 0x000e Device can operate at Full Speed (12Mbps) Device can operate at High Speed (480Mbps) Device can operate at SuperSpeed (5Gbps) bFunctionalitySupport 1 Lowest fully-functional device speed is Full Speed (12Mbps) bU1DevExitLat 0 micro seconds bU2DevExitLat 0 micro seconds The fix is to not enable LPM for a particular link state if we find its corresponding exit latency is zero. This patch should be backported to kernels as old as 3.5, that contain the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to enable/disable USB3 link states." Signed-off-by: Sarah Sharp Reported-by: Don Zickus Tested-by: Don Zickus Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 128a804c42f406..d1a43ab01167e0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3353,6 +3353,16 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { int timeout; + __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; + __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; + + /* If the device says it doesn't have *any* exit latency to come out of + * U1 or U2, it's probably lying. Assume it doesn't implement that link + * state. + */ + if ((state == USB3_LPM_U1 && u1_mel == 0) || + (state == USB3_LPM_U2 && u2_mel == 0)) + return; /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the From 094c5b6410392321492c59603879f8ec7d87358a Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 4 Oct 2012 09:53:43 -0700 Subject: [PATCH 0303/1071] USB: Enable LPM after a failed probe. commit d01f87c0ffa96cb44faa78710711eb6e974b891c upstream. Before a driver is probed, we want to disable USB 3.0 Link Power Management (LPM), in case the driver needs hub-initiated LPM disabled. After the probe finishes, we want to attempt to re-enable LPM, order to balance the LPM ref count. When a probe fails (such as when libusual doesn't want to bind to a USB 3.0 mass storage device), make sure to balance the LPM ref counts by re-enabling LPM. This patch should be backported to kernels as old as 3.5, that contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB: Disable USB 3.0 LPM in critical sections." Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 445455a4429bef..fb6e97f5278d89 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -372,6 +372,10 @@ static int usb_probe_interface(struct device *dev) intf->condition = USB_INTERFACE_UNBOUND; usb_cancel_queued_reset(intf); + /* If the LPM disable succeeded, balance the ref counts. */ + if (!lpm_disable_error) + usb_unlocked_enable_lpm(udev); + /* Unbound interfaces are always runtime-PM-disabled and -suspended */ if (driver->supports_autosuspend) pm_runtime_disable(dev); From 4e0532a22664501721fdd89a00d61948c1e34a23 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 5 Oct 2012 10:32:07 -0700 Subject: [PATCH 0304/1071] usb: Send Set SEL before enabling parent U1/U2 timeout. commit 65a95b75bc5afa7bbb844e222481044c1c4767eb upstream. The Set SEL control transfer tells a device the exit latencies associated with a device-initated U1 or U2 exit. Since a parent hub may initiate a transition to U1 soon after a downstream port's U1 timeout is set, we need to make sure the device receives the Set SEL transfer before the parent hub timeout is set. This patch should be backported to kernels as old as 3.5, that contain the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to enable/disable USB3 link states." Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d1a43ab01167e0..bbff14318c1f69 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3257,16 +3257,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev, } if (enable) { - /* - * First, let the device know about the exit latencies - * associated with the link state we're about to enable. - */ - ret = usb_req_set_sel(udev, state); - if (ret < 0) { - dev_warn(&udev->dev, "Set SEL for device-initiated " - "%s failed.\n", usb3_lpm_names[state]); - return -EBUSY; - } /* * Now send the control transfer to enable device-initiated LPM * for either U1 or U2. @@ -3352,7 +3342,7 @@ static int usb_set_lpm_timeout(struct usb_device *udev, static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { - int timeout; + int timeout, ret; __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; @@ -3364,6 +3354,17 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, (state == USB3_LPM_U2 && u2_mel == 0)) return; + /* + * First, let the device know about the exit latencies + * associated with the link state we're about to enable. + */ + ret = usb_req_set_sel(udev, state); + if (ret < 0) { + dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n", + usb3_lpm_names[state]); + return; + } + /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the * additional latency to send data to a device in a lower power From 1f212892776010ea4ebc9982e7a725732df3a7f0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 10 Oct 2012 14:10:21 -0400 Subject: [PATCH 0305/1071] USB: fix port probing and removal in garmin_gps commit db5c8b524444d4fc6b1f32d368a50a3729e50002 upstream. This patch (as1615) fixes a bug in the Garmin USB serial driver. It uses attach, disconnect, and release routines to carry out actions that should be handled by port_probe and port_remove routines, because they access port-specific data. The bug causes an oops when the device in unplugged, because the private data for each port structure now gets erased when the port is unbound from the driver, resulting in a null-pointer dereference. Signed-off-by: Alan Stern Reported--by: Markus Schauler Tested-by: Markus Schauler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/garmin_gps.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 346c15a510663c..de9cfd42e2a176 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1414,11 +1414,10 @@ static void timeout_handler(unsigned long data) -static int garmin_attach(struct usb_serial *serial) +static int garmin_port_probe(struct usb_serial_port *port) { - int status = 0; - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = NULL; + int status; + struct garmin_data *garmin_data_p; garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { @@ -1443,22 +1442,14 @@ static int garmin_attach(struct usb_serial *serial) } -static void garmin_disconnect(struct usb_serial *serial) +static int garmin_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); -} - - -static void garmin_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - kfree(garmin_data_p); + return 0; } @@ -1475,9 +1466,8 @@ static struct usb_serial_driver garmin_device = { .close = garmin_close, .throttle = garmin_throttle, .unthrottle = garmin_unthrottle, - .attach = garmin_attach, - .disconnect = garmin_disconnect, - .release = garmin_release, + .port_probe = garmin_port_probe, + .port_remove = garmin_port_remove, .write = garmin_write, .write_room = garmin_write_room, .write_bulk_callback = garmin_write_bulk_callback, From 52f65d5b473c7d5bc166ed7f86570be7852edb9a Mon Sep 17 00:00:00 2001 From: Daisuke Nishimura Date: Thu, 4 Oct 2012 16:37:16 +0900 Subject: [PATCH 0306/1071] cgroup: notify_on_release may not be triggered in some cases commit 1f5320d5972aa50d3e8d2b227b636b370e608359 upstream. notify_on_release must be triggered when the last process in a cgroup is move to another. But if the first(and only) process in a cgroup is moved to another, notify_on_release is not triggered. # mkdir /cgroup/cpu/SRC # mkdir /cgroup/cpu/DST # # echo 1 >/cgroup/cpu/SRC/notify_on_release # echo 1 >/cgroup/cpu/DST/notify_on_release # # sleep 300 & [1] 8629 # # echo 8629 >/cgroup/cpu/SRC/tasks # echo 8629 >/cgroup/cpu/DST/tasks -> notify_on_release for /SRC must be triggered at this point, but it isn't. This is because put_css_set() is called before setting CGRP_RELEASABLE in cgroup_task_migrate(), and is a regression introduce by the commit:74a1166d(cgroups: make procs file writable), which was merged into v3.0. Acked-by: Li Zefan Cc: Ben Blum Signed-off-by: Daisuke Nishimura Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 79818507e444aa..7d01182c92eb98 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1923,9 +1923,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp, * trading it for newcg is protected by cgroup_mutex, we're safe to drop * it here; it will be freed under RCU. */ - put_css_set(oldcg); - set_bit(CGRP_RELEASABLE, &oldcgrp->flags); + put_css_set(oldcg); } /** From b4cd7aa6602e17f7c128ddf0c9b0dc7b4e2b897c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 18 Oct 2012 17:40:30 -0700 Subject: [PATCH 0307/1071] Revert "cgroup: Remove task_lock() from cgroup_post_fork()" commit d87838321124061f6c935069d97f37010fa417e6 upstream. This reverts commit 7e3aa30ac8c904a706518b725c451bb486daaae9. The commit incorrectly assumed that fork path always performed threadgroup_change_begin/end() and depended on that for synchronization against task exit and cgroup migration paths instead of explicitly grabbing task_lock(). threadgroup_change is not locked when forking a new process (as opposed to a new thread in the same process) and even if it were it wouldn't be effective as different processes use different threadgroup locks. Revert the incorrect optimization. Signed-off-by: Tejun Heo LKML-Reference: <20121008020000.GB2575@localhost> Acked-by: Li Zefan Cc: Frederic Weisbecker Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 7d01182c92eb98..0907aa52403532 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4771,19 +4771,10 @@ void cgroup_post_fork(struct task_struct *child) */ if (use_task_css_set_links) { write_lock(&css_set_lock); - if (list_empty(&child->cg_list)) { - /* - * It's safe to use child->cgroups without task_lock() - * here because we are protected through - * threadgroup_change_begin() against concurrent - * css_set change in cgroup_task_migrate(). Also - * the task can't exit at that point until - * wake_up_new_task() is called, so we are protected - * against cgroup_exit() setting child->cgroup to - * init_css_set. - */ + task_lock(child); + if (list_empty(&child->cg_list)) list_add(&child->cg_list, &child->cgroups->tasks); - } + task_unlock(child); write_unlock(&css_set_lock); } } From 04900efcfcd89fd11302748bbe88659d12fd7fb5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 18 Oct 2012 17:52:07 -0700 Subject: [PATCH 0308/1071] Revert "cgroup: Drop task_lock(parent) on cgroup_fork()" commit 9bb71308b8133d643648776243e4d5599b1c193d upstream. This reverts commit 7e381b0eb1e1a9805c37335562e8dc02e7d7848c. The commit incorrectly assumed that fork path always performed threadgroup_change_begin/end() and depended on that for synchronization against task exit and cgroup migration paths instead of explicitly grabbing task_lock(). threadgroup_change is not locked when forking a new process (as opposed to a new thread in the same process) and even if it were it wouldn't be effective as different processes use different threadgroup locks. Revert the incorrect optimization. Signed-off-by: Tejun Heo LKML-Reference: <20121008020000.GB2575@localhost> Acked-by: Li Zefan Bitterly-Acked-by: Frederic Weisbecker Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 0907aa52403532..ff2bce5daa5513 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4694,31 +4694,20 @@ static const struct file_operations proc_cgroupstats_operations = { * * A pointer to the shared css_set was automatically copied in * fork.c by dup_task_struct(). However, we ignore that copy, since - * it was not made under the protection of RCU, cgroup_mutex or - * threadgroup_change_begin(), so it might no longer be a valid - * cgroup pointer. cgroup_attach_task() might have already changed - * current->cgroups, allowing the previously referenced cgroup - * group to be removed and freed. - * - * Outside the pointer validity we also need to process the css_set - * inheritance between threadgoup_change_begin() and - * threadgoup_change_end(), this way there is no leak in any process - * wide migration performed by cgroup_attach_proc() that could otherwise - * miss a thread because it is too early or too late in the fork stage. + * it was not made under the protection of RCU or cgroup_mutex, so + * might no longer be a valid cgroup pointer. cgroup_attach_task() might + * have already changed current->cgroups, allowing the previously + * referenced cgroup group to be removed and freed. * * At the point that cgroup_fork() is called, 'current' is the parent * task, and the passed argument 'child' points to the child task. */ void cgroup_fork(struct task_struct *child) { - /* - * We don't need to task_lock() current because current->cgroups - * can't be changed concurrently here. The parent obviously hasn't - * exited and called cgroup_exit(), and we are synchronized against - * cgroup migration through threadgroup_change_begin(). - */ + task_lock(current); child->cgroups = current->cgroups; get_css_set(child->cgroups); + task_unlock(current); INIT_LIST_HEAD(&child->cg_list); } From f29ff626db3d3cbfdbff20b5c41eb32e1e92d1fa Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Wed, 17 Oct 2012 11:51:37 +0530 Subject: [PATCH 0309/1071] pinctrl: tegra: correct bank for pingroup and drv pingroup commit a03690e44468dcd3088f6600ab036d17bd2130ff upstream. Signed-off-by: Pritesh Raithatha Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/pinctrl-tegra30.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 0386fdf0da1644..7894f14c705900 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = { FUNCTION(vi_alt3), }; -#define MUXCTL_REG_A 0x3000 -#define PINGROUP_REG_A 0x868 +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ -#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A) +#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A) #define PINGROUP_REG_N(r) -1 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior) \ @@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = { }, \ .func_safe = TEGRA_MUX_ ## f_safe, \ .mux_reg = PINGROUP_REG_Y(r), \ - .mux_bank = 0, \ + .mux_bank = 1, \ .mux_bit = 0, \ .pupd_reg = PINGROUP_REG_Y(r), \ - .pupd_bank = 0, \ + .pupd_bank = 1, \ .pupd_bit = 2, \ .tri_reg = PINGROUP_REG_Y(r), \ - .tri_bank = 0, \ + .tri_bank = 1, \ .tri_bit = 4, \ .einput_reg = PINGROUP_REG_Y(r), \ - .einput_bank = 0, \ + .einput_bank = 1, \ .einput_bit = 5, \ .odrain_reg = PINGROUP_REG_##od(r), \ - .odrain_bank = 0, \ + .odrain_bank = 1, \ .odrain_bit = 6, \ .lock_reg = PINGROUP_REG_Y(r), \ - .lock_bank = 0, \ + .lock_bank = 1, \ .lock_bit = 7, \ .ioreset_reg = PINGROUP_REG_##ior(r), \ - .ioreset_bank = 0, \ + .ioreset_bank = 1, \ .ioreset_bit = 8, \ .drv_reg = -1, \ } @@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = { .odrain_reg = -1, \ .lock_reg = -1, \ .ioreset_reg = -1, \ - .drv_reg = ((r) - PINGROUP_REG_A), \ - .drv_bank = 1, \ + .drv_reg = ((r) - DRV_PINGROUP_REG_A), \ + .drv_bank = 0, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ From 501bb61ad86a43f64686230f203f21c31224d071 Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Wed, 17 Oct 2012 17:07:00 +0530 Subject: [PATCH 0310/1071] dt: Document: correct tegra20/30 pinctrl slew-rate name commit d6ec6b60a56a1e7d99da1fc69c031fa5ab54ba94 upstream. change nvidia,slew_rate* to nvidia,slew-rate* Signed-off-by: Pritesh Raithatha Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt | 2 +- .../devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt index c8e578263ce265..683fde93c4fb1a 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt @@ -93,7 +93,7 @@ Valid values for pin and group names are: With some exceptions, these support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength, - nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling. + nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling. drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2, drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg, diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt index c275b70349c11a..6f426ed7009e5e 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt @@ -83,7 +83,7 @@ Valid values for pin and group names are: drive groups: These all support nvidia,pull-down-strength, nvidia,pull-up-strength, - nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all + nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode. ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1, From 11a1f627e40ad19f09d3e1f5690967f6123d24ca Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Wed, 17 Oct 2012 17:09:36 +0530 Subject: [PATCH 0311/1071] pinctrl: tegra: set low power mode bank width to 2 commit 154f3ebf53edcfbe28728452b4ab37a118581125 upstream. Signed-off-by: Pritesh Raithatha Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/pinctrl-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index ae52e4e5d098cc..5a5f2612b5841d 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -466,7 +466,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx, *bank = g->drv_bank; *reg = g->drv_reg; *bit = g->lpmd_bit; - *width = 1; + *width = 2; break; case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: *bank = g->drv_bank; From 49d14e6bc5f7a8ff3f581f9399f0992622c35556 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Thu, 18 Oct 2012 17:07:01 +0800 Subject: [PATCH 0312/1071] pinctrl: remove mutex lock in groups show commit 7ae9d71e8df27a3ab60a05ae3add08728debc09c upstream. Mutex is locked duplicatly by pinconf_groups_show() and pin_config_group_get(). It results dead lock. So avoid to lock mutex in pinconf_groups_show(). Signed-off-by: Haojian Zhuang Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/pinconf.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 43f474cdc11082..baee2cc46a17a7 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) seq_puts(s, "Pin config settings per pin group\n"); seq_puts(s, "Format: group (name): configs\n"); - mutex_lock(&pinctrl_mutex); - while (selector < ngroups) { const char *gname = pctlops->get_group_name(pctldev, selector); @@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) selector++; } - mutex_unlock(&pinctrl_mutex); - return 0; } From 651d36d9fc0dc6aef0889bdf8321bb8870782141 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 22 Oct 2012 12:58:09 +0800 Subject: [PATCH 0313/1071] pinctrl: fix missing unlock on error in pinctrl_groups_show() commit b4dd784ba8af03bf1f9ee5118c792d7abd4919bd upstream. Add the missing unlock on the error handle path in function pinctrl_groups_show(). Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index dc5c126e398a0a..63560c3a322c56 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1059,8 +1059,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) seq_printf(s, "group: %s\n", gname); for (i = 0; i < num_pins; i++) { pname = pin_get_name(pctldev, pins[i]); - if (WARN_ON(!pname)) + if (WARN_ON(!pname)) { + mutex_unlock(&pinctrl_mutex); return -EINVAL; + } seq_printf(s, "pin %d (%s)\n", pins[i], pname); } seq_puts(s, "\n"); From 351e8508d85ce80a75af36336b2d633715c1f9e3 Mon Sep 17 00:00:00 2001 From: Hiro Sugawara Date: Thu, 18 Oct 2012 08:35:10 +0300 Subject: [PATCH 0314/1071] iommu/tegra: smmu: Fix deadly typo commit d0078e72314df2e5ede03f2102cddde06767c374 upstream. Fix a deadly typo in macro definition. Signed-off-by: Hiro Sugawara Signed-off-by: Hiroshi Doyu Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/tegra-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 2a4bb36bc6888a..cef812affe44e0 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -146,7 +146,7 @@ #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12) #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22) -#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22) +#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22) #define _READABLE (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT) #define _WRITABLE (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT) From 5c61f172ad55e0d7073747f0a126d267faeb4512 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 23 Oct 2012 14:09:39 -0700 Subject: [PATCH 0315/1071] amd64_edac:__amd64_set_scrub_rate(): avoid overindexing scrubrates[] commit 168bfeef7bba3f9784f7540b053e4ac72b769ce9 upstream. If none of the elements in scrubrates[] matches, this loop will cause __amd64_set_scrub_rate() to incorrectly use the n+1th element. As the function is designed to use the final scrubrates[] element in the case of no match, we can fix this bug by simply terminating the array search at the n-1th element. Boris: this code is fragile anyway, see here why: http://marc.info/?l=linux-kernel&m=135102834131236&w=2 It will be rewritten more robustly soonish. Reported-by: Denis Kirjanov Cc: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 5a297a26211d62..cc8e7c78a23ca2 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) * memory controller and apply to register. Search for the first * bandwidth entry that is greater or equal than the setting requested * and program that. If at last entry, turn off DRAM scrubbing. + * + * If no suitable bandwidth is found, turn off DRAM scrubbing entirely + * by falling back to the last element in scrubrates[]. */ - for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { + for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) { /* * skip scrub rates which aren't recommended * (see F10 BKDG, F3x58) @@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) if (scrubrates[i].bandwidth <= new_bw) break; - - /* - * if no suitable bandwidth found, turn off DRAM scrubbing - * entirely by falling back to the last element in the - * scrubrates array. - */ } scrubval = scrubrates[i].scrubval; From 7551ed08b73e53a240c2f1281815bf693b12bd68 Mon Sep 17 00:00:00 2001 From: Chris Zankel Date: Fri, 19 Oct 2012 10:46:44 -0700 Subject: [PATCH 0316/1071] xtensa: add missing system calls to the syscall table commit 7216cabfff5149670445cd65d415ed5db21314b4 upstream. Add the following system calls to the syscall table: fallocate sendmmsg umount2 syncfs epoll_create1 inotify_init1 signalfd4 dup3 pipe2 timerfd_create timerfd_settime timerfd_gettime eventfd2 preadv pwritev fanotify_init fanotify_mark process_vm_readv process_vm_writev name_to_handle_at open_by_handle_at sync_file_range perf_event_open rt_tgsigqueueinfo clock_adjtime prlimit64 kcmp Note that we have to use the 'sys_sync_file_range2' version, so that the 64-bit arguments are aligned correctly to the argument registers. Signed-off-by: Chris Zankel Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/include/asm/unistd.h | 91 +++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index bc7e005faa602f..6b3ff986764a5e 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -148,8 +148,8 @@ __SYSCALL( 59, sys_getdents, 3) __SYSCALL( 60, sys_getdents64, 3) #define __NR_fcntl64 61 __SYSCALL( 61, sys_fcntl64, 3) -#define __NR_available62 62 -__SYSCALL( 62, sys_ni_syscall, 0) +#define __NR_fallocate 62 +__SYSCALL( 62, sys_fallocate, 6) #define __NR_fadvise64_64 63 __SYSCALL( 63, xtensa_fadvise64_64, 6) #define __NR_utime 64 /* glibc 2.3.3 ?? */ @@ -264,8 +264,8 @@ __SYSCALL(112, sys_socketpair, 4) __SYSCALL(113, sys_sendfile, 4) #define __NR_sendfile64 114 __SYSCALL(114, sys_sendfile64, 4) -#define __NR_available115 115 -__SYSCALL(115, sys_ni_syscall, 0) +#define __NR_sendmmsg 115 +__SYSCALL(115, sys_sendmmsg, 4) /* Process Operations */ @@ -380,11 +380,11 @@ __SYSCALL(168, sys_msgrcv, 4) __SYSCALL(169, sys_msgctl, 4) #define __NR_available170 170 __SYSCALL(170, sys_ni_syscall, 0) -#define __NR_available171 171 -__SYSCALL(171, sys_ni_syscall, 0) /* File System */ +#define __NR_umount2 171 +__SYSCALL(171, sys_umount, 2) #define __NR_mount 172 __SYSCALL(172, sys_mount, 5) #define __NR_swapon 173 @@ -399,8 +399,8 @@ __SYSCALL(176, sys_umount, 2) __SYSCALL(177, sys_swapoff, 1) #define __NR_sync 178 __SYSCALL(178, sys_sync, 0) -#define __NR_available179 179 -__SYSCALL(179, sys_ni_syscall, 0) +#define __NR_syncfs 179 +__SYSCALL(179, sys_syncfs, 1) #define __NR_setfsuid 180 __SYSCALL(180, sys_setfsuid, 1) #define __NR_setfsgid 181 @@ -455,7 +455,7 @@ __SYSCALL(203, sys_reboot, 3) #define __NR_quotactl 204 __SYSCALL(204, sys_quotactl, 4) #define __NR_nfsservctl 205 -__SYSCALL(205, sys_ni_syscall, 0) +__SYSCALL(205, sys_ni_syscall, 0) /* old nfsservctl */ #define __NR__sysctl 206 __SYSCALL(206, sys_sysctl, 1) #define __NR_bdflush 207 @@ -562,7 +562,7 @@ __SYSCALL(252, sys_timer_getoverrun, 1) /* System */ -#define __NR_reserved244 253 +#define __NR_reserved253 253 __SYSCALL(253, sys_ni_syscall, 0) #define __NR_lookup_dcookie 254 __SYSCALL(254, sys_lookup_dcookie, 4) @@ -609,8 +609,8 @@ __SYSCALL(272, sys_pselect6, 0) __SYSCALL(273, sys_ppoll, 0) #define __NR_epoll_pwait 274 __SYSCALL(274, sys_epoll_pwait, 0) -#define __NR_available275 275 -__SYSCALL(275, sys_ni_syscall, 0) +#define __NR_epoll_create1 275 +__SYSCALL(275, sys_epoll_create1, 1) #define __NR_inotify_init 276 __SYSCALL(276, sys_inotify_init, 0) @@ -618,8 +618,8 @@ __SYSCALL(276, sys_inotify_init, 0) __SYSCALL(277, sys_inotify_add_watch, 3) #define __NR_inotify_rm_watch 278 __SYSCALL(278, sys_inotify_rm_watch, 2) -#define __NR_available279 279 -__SYSCALL(279, sys_ni_syscall, 0) +#define __NR_inotify_init1 279 +__SYSCALL(279, sys_inotify_init1, 1) #define __NR_getcpu 280 __SYSCALL(280, sys_getcpu, 0) @@ -635,10 +635,10 @@ __SYSCALL(283, sys_ioprio_get, 3) __SYSCALL(284, sys_set_robust_list, 3) #define __NR_get_robust_list 285 __SYSCALL(285, sys_get_robust_list, 3) -#define __NR_reserved286 286 /* sync_file_rangeX */ -__SYSCALL(286, sys_ni_syscall, 3) +#define __NR_available286 286 +__SYSCALL(286, sys_ni_syscall, 0) #define __NR_available287 287 -__SYSCALL(287, sys_faccessat, 0) +__SYSCALL(287, sys_ni_syscall, 0) /* Relative File Operations */ @@ -683,10 +683,63 @@ __SYSCALL(305, sys_ni_syscall, 0) __SYSCALL(306, sys_eventfd, 1) #define __NR_recvmmsg 307 __SYSCALL(307, sys_recvmmsg, 5) + #define __NR_setns 308 __SYSCALL(308, sys_setns, 2) - -#define __NR_syscall_count 309 +#define __NR_signalfd4 309 +__SYSCALL(309, sys_signalfd4, 4) +#define __NR_dup3 310 +__SYSCALL(310, sys_dup3, 3) +#define __NR_pipe2 311 +__SYSCALL(311, sys_pipe2, 2) + +#define __NR_timerfd_create 312 +__SYSCALL(312, sys_timerfd_create, 2) +#define __NR_timerfd_settime 313 +__SYSCALL(313, sys_timerfd_settime, 4) +#define __NR_timerfd_gettime 314 +__SYSCALL(314, sys_timerfd_gettime, 2) +#define __NR_available315 315 +__SYSCALL(315, sys_ni_syscall, 0) + +#define __NR_eventfd2 316 +__SYSCALL(316, sys_eventfd2, 2) +#define __NR_preadv 317 +__SYSCALL(317, sys_preadv, 5) +#define __NR_pwritev 318 +__SYSCALL(318, sys_pwritev, 5) +#define __NR_available319 319 +__SYSCALL(319, sys_ni_syscall, 0) + +#define __NR_fanotify_init 320 +__SYSCALL(320, sys_fanotify_init, 2) +#define __NR_fanotify_mark 321 +__SYSCALL(321, sys_fanotify_mark, 6) +#define __NR_process_vm_readv 322 +__SYSCALL(322, sys_process_vm_readv, 6) +#define __NR_process_vm_writev 323 +__SYSCALL(323, sys_process_vm_writev, 6) + +#define __NR_name_to_handle_at 324 +__SYSCALL(324, sys_name_to_handle_at, 5) +#define __NR_open_by_handle_at 325 +__SYSCALL(325, sys_open_by_handle_at, 3) +#define __NR_sync_file_range 326 +__SYSCALL(326, sys_sync_file_range2, 6) +#define __NR_perf_event_open 327 +__SYSCALL(327, sys_perf_event_open, 5) + +#define __NR_rt_tgsigqueueinfo 328 +__SYSCALL(328, sys_rt_tgsigqueueinfo, 4) +#define __NR_clock_adjtime 329 +__SYSCALL(329, sys_clock_adjtime, 2) +#define __NR_prlimit64 330 +__SYSCALL(330, sys_prlimit64, 4) +#define __NR_kcmp 331 +__SYSCALL(331, sys_kcmp, 5) + + +#define __NR_syscall_count 332 /* * sysxtensa syscall handler From 1161c54f6c3d4681a1a366232b76d6a5b21b2dfa Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 6 Aug 2012 22:47:03 -0300 Subject: [PATCH 0317/1071] media: au0828: fix case where STREAMOFF being called on stopped stream causes BUG() commit a595c1ce4c9d572cf53513570b9f1a263d7867f2 upstream. We weren't checking whether the resource was in use before calling res_free(), so applications which called STREAMOFF on a v4l2 device that wasn't already streaming would cause a BUG() to be hit (MythTV). Reported-by: Larry Finger Reported-by: Jay Harbeston Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index ac3dd733ab815d..902825a39ef34a 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1692,14 +1692,18 @@ static int vidioc_streamoff(struct file *file, void *priv, (AUVI_INPUT(i).audio_setup)(dev, 0); } - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); + if (res_check(fh, AU0828_RESOURCE_VIDEO)) { + videobuf_streamoff(&fh->vb_vidq); + res_free(fh, AU0828_RESOURCE_VIDEO); + } } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { dev->vbi_timeout_running = 0; del_timer_sync(&dev->vbi_timeout); - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); + if (res_check(fh, AU0828_RESOURCE_VBI)) { + videobuf_streamoff(&fh->vb_vbiq); + res_free(fh, AU0828_RESOURCE_VBI); + } } return 0; From 2c609a2f31e7961301c3b7ecbc8b47b29c1ea790 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Aug 2012 13:12:52 +0100 Subject: [PATCH 0318/1071] drm/i915: Use cpu relocations if the object is in the GTT but not mappable commit 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 upstream. This prevents the case of unbinding the object in order to process the relocations through the GTT and then rebinding it only to then proceed to use cpu relocations as the object is now in the CPU write domain. By choosing to use cpu relocations up front, we can therefore avoid the rebind penalty. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Cc: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index ff2819ea08130f..cdf46b544d4541 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -269,6 +269,7 @@ eb_destroy(struct eb_objects *eb) static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) { return (obj->base.write_domain == I915_GEM_DOMAIN_CPU || + !obj->map_and_fenceable || obj->cache_level != I915_CACHE_NONE); } From 51f2e2ce2b04971dc852643bc5cc4b3657af4bc5 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 4 Oct 2012 20:15:48 +0000 Subject: [PATCH 0319/1071] netlink: add reference of module in netlink_dump_start [ Upstream commit 6dc878a8ca39e93f70c42f3dd7260bde10c1e0f1 ] I get a panic when I use ss -a and rmmod inet_diag at the same time. It's because netlink_dump uses inet_diag_dump which belongs to module inet_diag. I search the codes and find many modules have the same problem. We need to add a reference to the module which the cb->dump belongs to. Thanks for all help from Stephen,Jan,Eric,Steffen and Pablo. Change From v3: change netlink_dump_start to inline,suggestion from Pablo and Eric. Change From v2: delete netlink_dump_done,and call module_put in netlink_dump and netlink_sock_destruct. Signed-off-by: Gao feng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/netlink.h | 21 +++++++++++++++++---- net/netlink/af_netlink.c | 29 +++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index f74dd133788f7c..e8937360fc10e3 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -153,6 +153,7 @@ struct nlattr { #include #include +#include struct net; @@ -232,6 +233,8 @@ struct netlink_callback { struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); void *data; + /* the module that dump function belong to */ + struct module *module; u16 family; u16 min_dump_alloc; unsigned int prev_seq, seq; @@ -249,14 +252,24 @@ __nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags) struct netlink_dump_control { int (*dump)(struct sk_buff *skb, struct netlink_callback *); - int (*done)(struct netlink_callback*); + int (*done)(struct netlink_callback *); void *data; + struct module *module; u16 min_dump_alloc; }; -extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - const struct nlmsghdr *nlh, - struct netlink_dump_control *control); +extern int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control); +static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control) +{ + if (!control->module) + control->module = THIS_MODULE; + + return __netlink_dump_start(ssk, skb, nlh, control); +} #define NL_NONROOT_RECV 0x1 diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 527023823b5c5e..9172179becfb2c 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -169,6 +169,8 @@ static void netlink_sock_destruct(struct sock *sk) if (nlk->cb) { if (nlk->cb->done) nlk->cb->done(nlk->cb); + + module_put(nlk->cb->module); netlink_destroy_callback(nlk->cb); } @@ -1760,6 +1762,7 @@ static int netlink_dump(struct sock *sk) nlk->cb = NULL; mutex_unlock(nlk->cb_mutex); + module_put(cb->module); netlink_consume_callback(cb); return 0; @@ -1769,9 +1772,9 @@ static int netlink_dump(struct sock *sk) return err; } -int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - const struct nlmsghdr *nlh, - struct netlink_dump_control *control) +int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control) { struct netlink_callback *cb; struct sock *sk; @@ -1786,6 +1789,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, cb->done = control->done; cb->nlh = nlh; cb->data = control->data; + cb->module = control->module; cb->min_dump_alloc = control->min_dump_alloc; atomic_inc(&skb->users); cb->skb = skb; @@ -1796,19 +1800,28 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, return -ECONNREFUSED; } nlk = nlk_sk(sk); - /* A dump is in progress... */ + mutex_lock(nlk->cb_mutex); + /* A dump is in progress... */ if (nlk->cb) { mutex_unlock(nlk->cb_mutex); netlink_destroy_callback(cb); - sock_put(sk); - return -EBUSY; + ret = -EBUSY; + goto out; } + /* add reference of module which cb->dump belongs to */ + if (!try_module_get(cb->module)) { + mutex_unlock(nlk->cb_mutex); + netlink_destroy_callback(cb); + ret = -EPROTONOSUPPORT; + goto out; + } + nlk->cb = cb; mutex_unlock(nlk->cb_mutex); ret = netlink_dump(sk); - +out: sock_put(sk); if (ret) @@ -1819,7 +1832,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, */ return -EINTR; } -EXPORT_SYMBOL(netlink_dump_start); +EXPORT_SYMBOL(__netlink_dump_start); void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) { From e9ad2fc50a33c322bf343661851b1f179598b072 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 4 Oct 2012 20:15:49 +0000 Subject: [PATCH 0320/1071] infiniband: pass rdma_cm module to netlink_dump_start [ Upstream commit 809d5fc9bf6589276a12bd4fd611e4c7ff9940c3 ] set netlink_dump_control.module to avoid panic. Signed-off-by: Gao feng Cc: Roland Dreier Cc: Sean Hefty Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/cma.c | 3 ++- drivers/infiniband/core/netlink.c | 1 + include/rdma/rdma_netlink.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 7172559ce0c148..d1febf0760cc53 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3495,7 +3495,8 @@ static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb) } static const struct ibnl_client_cbs cma_cb_table[] = { - [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats }, + [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats, + .module = THIS_MODULE }, }; static int __init cma_init(void) diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index 3ae2bfd310158d..53b43a5b4d6657 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -154,6 +154,7 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { struct netlink_dump_control c = { .dump = client->cb_table[op].dump, + .module = client->cb_table[op].module, }; return netlink_dump_start(nls, skb, nlh, &c); } diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h index 3c5363ab867b26..bd3d8b24b42024 100644 --- a/include/rdma/rdma_netlink.h +++ b/include/rdma/rdma_netlink.h @@ -39,6 +39,7 @@ struct rdma_cm_id_stats { struct ibnl_client_cbs { int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb); + struct module *module; }; int ibnl_init(void); From 541321132ac28c92394b1d57361448d2c6dd5faf Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 5 Oct 2012 06:23:55 +0000 Subject: [PATCH 0321/1071] net: remove skb recycling [ Upstream commits acb600def2110b1310466c0e485c0d26299898ae and 66eef59f22275002f621ff9d951886b513d011b3. ] Over time, skb recycling infrastructure got litle interest and many bugs. Generic rx path skb allocation is now using page fragments for efficient GRO / TCP coalescing, and recyling a tx skb for rx path is not worth the pain. Last identified bug is that fat skbs can be recycled and it can endup using high order pages after few iterations. With help from Maxime Bizon, who pointed out that commit 87151b8689d (net: allow pskb_expand_head() to get maximum tailroom) introduced this regression for recycled skbs. Instead of fixing this bug, lets remove skb recycling. Drivers wanting really hot skbs should use build_skb() anyway, to allocate/populate sk_buff right before netif_receive_skb() Signed-off-by: Eric Dumazet Cc: Maxime Bizon Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/calxeda/xgmac.c | 19 +------- drivers/net/ethernet/freescale/gianfar.c | 27 ++--------- drivers/net/ethernet/freescale/gianfar.h | 2 - drivers/net/ethernet/freescale/ucc_geth.c | 29 +++--------- drivers/net/ethernet/freescale/ucc_geth.h | 2 - drivers/net/ethernet/marvell/mv643xx_eth.c | 18 +------ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 20 +------- include/linux/skbuff.h | 24 ---------- net/core/skbuff.c | 47 ------------------- 10 files changed, 16 insertions(+), 173 deletions(-) diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 2b4b4f529ab4db..16814b34d4b66a 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -375,7 +375,6 @@ struct xgmac_priv { unsigned int tx_tail; void __iomem *base; - struct sk_buff_head rx_recycle; unsigned int dma_buf_sz; dma_addr_t dma_rx_phy; dma_addr_t dma_tx_phy; @@ -672,9 +671,7 @@ static void xgmac_rx_refill(struct xgmac_priv *priv) p = priv->dma_rx + entry; if (priv->rx_skbuff[entry] == NULL) { - skb = __skb_dequeue(&priv->rx_recycle); - if (skb == NULL) - skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz); + skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz); if (unlikely(skb == NULL)) break; @@ -887,17 +884,7 @@ static void xgmac_tx_complete(struct xgmac_priv *priv) desc_get_buf_len(p), DMA_TO_DEVICE); } - /* - * If there's room in the queue (limit it to size) - * we add this skb back into the pool, - * if it's the right size. - */ - if ((skb_queue_len(&priv->rx_recycle) < - DMA_RX_RING_SZ) && - skb_recycle_check(skb, priv->dma_buf_sz)) - __skb_queue_head(&priv->rx_recycle, skb); - else - dev_kfree_skb(skb); + dev_kfree_skb(skb); } if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) > @@ -1016,7 +1003,6 @@ static int xgmac_open(struct net_device *dev) dev->dev_addr); } - skb_queue_head_init(&priv->rx_recycle); memset(&priv->xstats, 0, sizeof(struct xgmac_extra_stats)); /* Initialize the XGMAC and descriptors */ @@ -1053,7 +1039,6 @@ static int xgmac_stop(struct net_device *dev) napi_disable(&priv->napi); writel(0, priv->base + XGMAC_DMA_INTR_ENA); - skb_queue_purge(&priv->rx_recycle); /* Disable the MAC core */ xgmac_mac_disable(priv->base); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index d3233f59a82e47..e0ef1e547f0256 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1757,7 +1757,6 @@ static void free_skb_resources(struct gfar_private *priv) sizeof(struct rxbd8) * priv->total_rx_ring_size, priv->tx_queue[0]->tx_bd_base, priv->tx_queue[0]->tx_bd_dma_base); - skb_queue_purge(&priv->rx_recycle); } void gfar_start(struct net_device *dev) @@ -1935,8 +1934,6 @@ static int gfar_enet_open(struct net_device *dev) enable_napi(priv); - skb_queue_head_init(&priv->rx_recycle); - /* Initialize a bunch of registers */ init_registers(dev); @@ -2525,16 +2522,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) bytes_sent += skb->len; - /* If there's room in the queue (limit it to rx_buffer_size) - * we add this skb back into the pool, if it's the right size - */ - if (skb_queue_len(&priv->rx_recycle) < rx_queue->rx_ring_size && - skb_recycle_check(skb, priv->rx_buffer_size + - RXBUF_ALIGNMENT)) { - gfar_align_skb(skb); - skb_queue_head(&priv->rx_recycle, skb); - } else - dev_kfree_skb_any(skb); + dev_kfree_skb_any(skb); tx_queue->tx_skbuff[skb_dirtytx] = NULL; @@ -2600,7 +2588,7 @@ static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, static struct sk_buff *gfar_alloc_skb(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct sk_buff *skb = NULL; + struct sk_buff *skb; skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT); if (!skb) @@ -2613,14 +2601,7 @@ static struct sk_buff *gfar_alloc_skb(struct net_device *dev) struct sk_buff *gfar_new_skb(struct net_device *dev) { - struct gfar_private *priv = netdev_priv(dev); - struct sk_buff *skb = NULL; - - skb = skb_dequeue(&priv->rx_recycle); - if (!skb) - skb = gfar_alloc_skb(dev); - - return skb; + return gfar_alloc_skb(dev); } static inline void count_errors(unsigned short status, struct net_device *dev) @@ -2779,7 +2760,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) if (unlikely(!newskb)) newskb = skb; else if (skb) - skb_queue_head(&priv->rx_recycle, skb); + dev_kfree_skb(skb); } else { /* Increment the number of packets */ rx_queue->stats.rx_packets++; diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 2136c7ff5e6d23..27d8aebde9e3c6 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -1072,8 +1072,6 @@ struct gfar_private { u32 cur_filer_idx; - struct sk_buff_head rx_recycle; - /* RX queue filer rule set*/ struct ethtool_rx_list rx_list; struct mutex rx_queue_access; diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 21c6574c5f15cd..f6259ff4e5608d 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -210,14 +210,12 @@ static struct list_head *dequeue(struct list_head *lh) static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 __iomem *bd) { - struct sk_buff *skb = NULL; + struct sk_buff *skb; - skb = __skb_dequeue(&ugeth->rx_recycle); + skb = netdev_alloc_skb(ugeth->ndev, + ugeth->ug_info->uf_info.max_rx_buf_length + + UCC_GETH_RX_DATA_BUF_ALIGNMENT); if (!skb) - skb = netdev_alloc_skb(ugeth->ndev, - ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT); - if (skb == NULL) return NULL; /* We need the data buffer to be aligned properly. We will reserve @@ -2021,8 +2019,6 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) iounmap(ugeth->ug_regs); ugeth->ug_regs = NULL; } - - skb_queue_purge(&ugeth->rx_recycle); } static void ucc_geth_set_multi(struct net_device *dev) @@ -2231,8 +2227,6 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) return -ENOMEM; } - skb_queue_head_init(&ugeth->rx_recycle); - return 0; } @@ -3275,12 +3269,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit if (netif_msg_rx_err(ugeth)) ugeth_err("%s, %d: ERROR!!! skb - 0x%08x", __func__, __LINE__, (u32) skb); - if (skb) { - skb->data = skb->head + NET_SKB_PAD; - skb->len = 0; - skb_reset_tail_pointer(skb); - __skb_queue_head(&ugeth->rx_recycle, skb); - } + dev_kfree_skb(skb); ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL; dev->stats.rx_dropped++; @@ -3350,13 +3339,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) dev->stats.tx_packets++; - if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN && - skb_recycle_check(skb, - ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT)) - __skb_queue_head(&ugeth->rx_recycle, skb); - else - dev_kfree_skb(skb); + dev_kfree_skb(skb); ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL; ugeth->skb_dirtytx[txQ] = diff --git a/drivers/net/ethernet/freescale/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h index f71b3e7b12defe..75f337163ce3c6 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.h +++ b/drivers/net/ethernet/freescale/ucc_geth.h @@ -1214,8 +1214,6 @@ struct ucc_geth_private { /* index of the first skb which hasn't been transmitted yet. */ u16 skb_dirtytx[NUM_TX_QUEUES]; - struct sk_buff_head rx_recycle; - struct ugeth_mii_info *mii_info; struct phy_device *phydev; phy_interface_t phy_interface; diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 087b9e0669f181..84c13263c514c9 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -412,7 +412,6 @@ struct mv643xx_eth_private { u8 work_rx_refill; int skb_size; - struct sk_buff_head rx_recycle; /* * RX state. @@ -673,9 +672,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget) struct rx_desc *rx_desc; int size; - skb = __skb_dequeue(&mp->rx_recycle); - if (skb == NULL) - skb = netdev_alloc_skb(mp->dev, mp->skb_size); + skb = netdev_alloc_skb(mp->dev, mp->skb_size); if (skb == NULL) { mp->oom = 1; @@ -989,14 +986,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) desc->byte_cnt, DMA_TO_DEVICE); } - if (skb != NULL) { - if (skb_queue_len(&mp->rx_recycle) < - mp->rx_ring_size && - skb_recycle_check(skb, mp->skb_size)) - __skb_queue_head(&mp->rx_recycle, skb); - else - dev_kfree_skb(skb); - } + dev_kfree_skb(skb); } __netif_tx_unlock(nq); @@ -2349,8 +2339,6 @@ static int mv643xx_eth_open(struct net_device *dev) napi_enable(&mp->napi); - skb_queue_head_init(&mp->rx_recycle); - mp->int_mask = INT_EXT; for (i = 0; i < mp->rxq_count; i++) { @@ -2445,8 +2433,6 @@ static int mv643xx_eth_stop(struct net_device *dev) mib_counters_update(mp); del_timer_sync(&mp->mib_counters_timer); - skb_queue_purge(&mp->rx_recycle); - for (i = 0; i < mp->rxq_count; i++) rxq_deinit(mp->rxq + i); for (i = 0; i < mp->txq_count; i++) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index e872e1da3137ce..7d51a65ab09960 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -50,7 +50,6 @@ struct stmmac_priv { unsigned int dirty_rx; struct sk_buff **rx_skbuff; dma_addr_t *rx_skbuff_dma; - struct sk_buff_head rx_recycle; struct net_device *dev; dma_addr_t dma_rx_phy; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3be88331d17ab0..c6cdbc4eb05e61 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -747,18 +747,7 @@ static void stmmac_tx(struct stmmac_priv *priv) priv->hw->ring->clean_desc3(p); if (likely(skb != NULL)) { - /* - * If there's room in the queue (limit it to size) - * we add this skb back into the pool, - * if it's the right size. - */ - if ((skb_queue_len(&priv->rx_recycle) < - priv->dma_rx_size) && - skb_recycle_check(skb, priv->dma_buf_sz)) - __skb_queue_head(&priv->rx_recycle, skb); - else - dev_kfree_skb(skb); - + dev_kfree_skb(skb); priv->tx_skbuff[entry] = NULL; } @@ -1169,7 +1158,6 @@ static int stmmac_open(struct net_device *dev) priv->eee_enabled = stmmac_eee_init(priv); napi_enable(&priv->napi); - skb_queue_head_init(&priv->rx_recycle); netif_start_queue(dev); return 0; @@ -1222,7 +1210,6 @@ static int stmmac_release(struct net_device *dev) kfree(priv->tm); #endif napi_disable(&priv->napi); - skb_queue_purge(&priv->rx_recycle); /* Free the IRQ lines */ free_irq(dev->irq, dev); @@ -1388,10 +1375,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) if (likely(priv->rx_skbuff[entry] == NULL)) { struct sk_buff *skb; - skb = __skb_dequeue(&priv->rx_recycle); - if (skb == NULL) - skb = netdev_alloc_skb_ip_align(priv->dev, - bfsize); + skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); if (unlikely(skb == NULL)) break; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 7632c87da2c9fd..f3165d26c1636c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -589,9 +589,6 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE); } -extern void skb_recycle(struct sk_buff *skb); -extern bool skb_recycle_check(struct sk_buff *skb, int skb_size); - extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); extern struct sk_buff *skb_clone(struct sk_buff *skb, @@ -2642,27 +2639,6 @@ static inline void skb_checksum_none_assert(const struct sk_buff *skb) bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off); -static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size) -{ - if (irqs_disabled()) - return false; - - if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) - return false; - - if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) - return false; - - skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD); - if (skb_end_offset(skb) < skb_size) - return false; - - if (skb_shared(skb) || skb_cloned(skb)) - return false; - - return true; -} - /** * skb_head_is_locked - Determine if the skb->head is locked down * @skb: skb to check diff --git a/net/core/skbuff.c b/net/core/skbuff.c index e33ebae519c8c3..ef172afd3a8b43 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -641,53 +641,6 @@ void consume_skb(struct sk_buff *skb) } EXPORT_SYMBOL(consume_skb); -/** - * skb_recycle - clean up an skb for reuse - * @skb: buffer - * - * Recycles the skb to be reused as a receive buffer. This - * function does any necessary reference count dropping, and - * cleans up the skbuff as if it just came from __alloc_skb(). - */ -void skb_recycle(struct sk_buff *skb) -{ - struct skb_shared_info *shinfo; - - skb_release_head_state(skb); - - shinfo = skb_shinfo(skb); - memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); - atomic_set(&shinfo->dataref, 1); - - memset(skb, 0, offsetof(struct sk_buff, tail)); - skb->data = skb->head + NET_SKB_PAD; - skb_reset_tail_pointer(skb); -} -EXPORT_SYMBOL(skb_recycle); - -/** - * skb_recycle_check - check if skb can be reused for receive - * @skb: buffer - * @skb_size: minimum receive buffer size - * - * Checks that the skb passed in is not shared or cloned, and - * that it is linear and its head portion at least as large as - * skb_size so that it can be recycled as a receive buffer. - * If these conditions are met, this function does any necessary - * reference count dropping and cleans up the skbuff as if it - * just came from __alloc_skb(). - */ -bool skb_recycle_check(struct sk_buff *skb, int skb_size) -{ - if (!skb_is_recycleable(skb, skb_size)) - return false; - - skb_recycle(skb); - - return true; -} -EXPORT_SYMBOL(skb_recycle_check); - static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) { new->tstamp = old->tstamp; From ea89601ac85f4d90f1aab99801647423bd3ca069 Mon Sep 17 00:00:00 2001 From: "ramesh.nagappa@gmail.com" Date: Fri, 5 Oct 2012 19:10:15 +0000 Subject: [PATCH 0322/1071] net: Fix skb_under_panic oops in neigh_resolve_output [ Upstream commit e1f165032c8bade3a6bdf546f8faf61fda4dd01c ] The retry loop in neigh_resolve_output() and neigh_connected_output() call dev_hard_header() with out reseting the skb to network_header. This causes the retry to fail with skb_under_panic. The fix is to reset the network_header within the retry loop. Signed-off-by: Ramesh Nagappa Reviewed-by: Shawn Lu Reviewed-by: Robert Coulson Reviewed-by: Billie Alsup Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/neighbour.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 117afaf512689b..058bb1ea3e014e 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1301,8 +1301,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) if (!dst) goto discard; - __skb_pull(skb, skb_network_offset(skb)); - if (!neigh_event_send(neigh, skb)) { int err; struct net_device *dev = neigh->dev; @@ -1312,6 +1310,7 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) neigh_hh_init(neigh, dst); do { + __skb_pull(skb, skb_network_offset(skb)); seq = read_seqbegin(&neigh->ha_lock); err = dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len); @@ -1342,9 +1341,8 @@ int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) unsigned int seq; int err; - __skb_pull(skb, skb_network_offset(skb)); - do { + __skb_pull(skb, skb_network_offset(skb)); seq = read_seqbegin(&neigh->ha_lock); err = dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len); From b50a0bdfd24cf4e3b0551fa6ae2791692231776a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 5 Oct 2012 20:43:30 +0000 Subject: [PATCH 0323/1071] ipv6: GRO should be ECN friendly [ Upstream commit 51ec04038c113a811b177baa85d293feff9ce995 ] IPv4 side of the problem was addressed in commit a9e050f4e7f9d (net: tcp: GRO should be ECN friendly) This patch does the same, but for IPv6 : A Traffic Class mismatch doesnt mean flows are different, but instead should force a flush of previous packets. This patch removes artificial packet reordering problem. Signed-off-by: Eric Dumazet Cc: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/af_inet6.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e22e6d88bac681..f757e3b7cfbfbb 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -880,22 +880,25 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, nlen = skb_network_header_len(skb); for (p = *head; p; p = p->next) { - struct ipv6hdr *iph2; + const struct ipv6hdr *iph2; + __be32 first_word; /* */ if (!NAPI_GRO_CB(p)->same_flow) continue; iph2 = ipv6_hdr(p); + first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ; - /* All fields must match except length. */ + /* All fields must match except length and Traffic Class. */ if (nlen != skb_network_header_len(p) || - memcmp(iph, iph2, offsetof(struct ipv6hdr, payload_len)) || + (first_word & htonl(0xF00FFFFF)) || memcmp(&iph->nexthdr, &iph2->nexthdr, nlen - offsetof(struct ipv6hdr, nexthdr))) { NAPI_GRO_CB(p)->same_flow = 0; continue; } - + /* flush if Traffic Class fields are different */ + NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000)); NAPI_GRO_CB(p)->flush |= flush; } From b434571cec084eb0798fd160073d4b66937892ab Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 7 Oct 2012 22:47:25 +0000 Subject: [PATCH 0324/1071] ipv4: Always invalidate or update the route on pmtu events [ Upstream commit d851c12b60471188e15e5c8405b289073e8dd025 ] Some protocols, like IPsec still cache routes. So we need to invalidate the old route on pmtu events to avoid the reuse of stale routes. We also need to update the mtu and expire time of the route if we already use a nh exception route, otherwise we ignore newly learned pmtu values after the first expiration. With this patch we always invalidate or update the route on pmtu events. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index fd9af60397b590..09e85c74e872a2 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -904,22 +904,29 @@ out: kfree_skb(skb); return 0; } -static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) +static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) { + struct dst_entry *dst = &rt->dst; struct fib_result res; if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; + if (!rt->rt_pmtu) { + dst->obsolete = DST_OBSOLETE_KILL; + } else { + rt->rt_pmtu = mtu; + dst->expires = max(1UL, jiffies + ip_rt_mtu_expires); + } + rcu_read_lock(); - if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { + if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) { struct fib_nh *nh = &FIB_RES_NH(res); update_or_create_fnhe(nh, fl4->daddr, 0, mtu, jiffies + ip_rt_mtu_expires); } rcu_read_unlock(); - return mtu; } static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, @@ -929,14 +936,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, struct flowi4 fl4; ip_rt_build_flow_key(&fl4, sk, skb); - mtu = __ip_rt_update_pmtu(rt, &fl4, mtu); - - if (!rt->rt_pmtu) { - dst->obsolete = DST_OBSOLETE_KILL; - } else { - rt->rt_pmtu = mtu; - rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires); - } + __ip_rt_update_pmtu(rt, &fl4, mtu); } void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, From 2db8263a627414aa2f6a60f80ec99178f12f757b Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 7 Oct 2012 22:48:18 +0000 Subject: [PATCH 0325/1071] ipv4: Don't create nh exeption when the device mtu is smaller than the reported pmtu [ Upstream commit 7f92d334ba19a0d8e96f8f8f092219553367d921 ] When a local tool like tracepath tries to send packets bigger than the device mtu, we create a nh exeption and set the pmtu to device mtu. The device mtu does not expire, so check if the device mtu is smaller than the reported pmtu and don't crerate a nh exeption in that case. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 09e85c74e872a2..11814ad59fa604 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -909,6 +909,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) struct dst_entry *dst = &rt->dst; struct fib_result res; + if (dst->dev->mtu < mtu) + return; + if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; From 0dbade79f4fbb1035c3c846cdd358a67db67a2ce Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Mon, 8 Oct 2012 00:56:54 +0000 Subject: [PATCH 0326/1071] ipv4: Don't report stale pmtu values to userspace [ Upstream commit ee9a8f7ab2edf801b8b514c310455c94acc232f6 ] We report cached pmtu values even if they are already expired. Change this to not report these values after they are expired and fix a race in the expire time calculation, as suggested by Eric Dumazet. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 11814ad59fa604..94775f14e40d9c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2187,8 +2187,18 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway)) goto nla_put_failure; + expires = rt->dst.expires; + if (expires) { + unsigned long now = jiffies; + + if (time_before(now, expires)) + expires -= now; + else + expires = 0; + } + memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics)); - if (rt->rt_pmtu) + if (rt->rt_pmtu && expires) metrics[RTAX_MTU - 1] = rt->rt_pmtu; if (rtnetlink_put_metrics(skb, metrics) < 0) goto nla_put_failure; @@ -2198,13 +2208,6 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, goto nla_put_failure; error = rt->dst.error; - expires = rt->dst.expires; - if (expires) { - if (time_before(jiffies, expires)) - expires -= jiffies; - else - expires = 0; - } if (rt_is_input_route(rt)) { if (nla_put_u32(skb, RTA_IIF, rt->rt_iif)) From 18850d74d599a447b22b05600b13d51238f92a3e Mon Sep 17 00:00:00 2001 From: Graham Gower Date: Mon, 8 Oct 2012 08:34:50 +0000 Subject: [PATCH 0327/1071] skge: Add DMA mask quirk for Marvell 88E8001 on ASUS P5NSLI motherboard [ Upstream commit a2af139ff1cd85df586690ff626619ab1ee88b0a ] Marvell 88E8001 on an ASUS P5NSLI motherboard is unable to send/receive packets on a system with >4gb ram unless a 32bit DMA mask is used. This issue has been around for years and a fix was sent 3.5 years ago, but there was some debate as to whether it should instead be fixed as a PCI quirk. http://www.spinics.net/lists/netdev/msg88670.html However, 18 months later a similar workaround was introduced for another chipset exhibiting the same problem. http://www.spinics.net/lists/netdev/msg142287.html Signed-off-by: Graham Gower Signed-off-by: Jan Ceuleers Acked-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/marvell/skge.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 5a30bf823099a0..f4be8f7c286636 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -4153,6 +4153,13 @@ static struct dmi_system_id skge_32bit_dma_boards[] = { DMI_MATCH(DMI_BOARD_NAME, "nForce"), }, }, + { + .ident = "ASUS P5NSLI", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "P5NSLI") + }, + }, {} }; From 9f6bf366262af645ad1b8e12f241fc692d0a617b Mon Sep 17 00:00:00 2001 From: Florian Zumbiehl Date: Sun, 7 Oct 2012 15:51:58 +0000 Subject: [PATCH 0328/1071] vlan: don't deliver frames for unknown vlans to protocols [ Upstream commit 48cc32d38a52d0b68f91a171a8d00531edc6a46e ] 6a32e4f9dd9219261f8856f817e6655114cfec2f made the vlan code skip marking vlan-tagged frames for not locally configured vlans as PACKET_OTHERHOST if there was an rx_handler, as the rx_handler could cause the frame to be received on a different (virtual) vlan-capable interface where that vlan might be configured. As rx_handlers do not necessarily return RX_HANDLER_ANOTHER, this could cause frames for unknown vlans to be delivered to the protocol stack as if they had been received untagged. For example, if an ipv6 router advertisement that's tagged for a locally not configured vlan is received on an interface with macvlan interfaces attached, macvlan's rx_handler returns RX_HANDLER_PASS after delivering the frame to the macvlan interfaces, which caused it to be passed to the protocol stack, leading to ipv6 addresses for the announced prefix being configured even though those are completely unusable on the underlying interface. The fix moves marking as PACKET_OTHERHOST after the rx_handler so the rx_handler, if there is one, sees the frame unchanged, but afterwards, before the frame is delivered to the protocol stack, it gets marked whether there is an rx_handler or not. Signed-off-by: Florian Zumbiehl Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/if_vlan.h | 8 ++++---- net/8021q/vlan_core.c | 10 ++-------- net/core/dev.c | 7 +++++-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index a810987cb80e47..561e130df0b2fe 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -82,6 +82,8 @@ static inline int is_vlan_dev(struct net_device *dev) } #define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT) +#define vlan_tx_nonzero_tag_present(__skb) \ + (vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK)) #define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT) #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) @@ -91,7 +93,7 @@ extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); extern u16 vlan_dev_vlan_id(const struct net_device *dev); -extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler); +extern bool vlan_do_receive(struct sk_buff **skb); extern struct sk_buff *vlan_untag(struct sk_buff *skb); extern int vlan_vid_add(struct net_device *dev, unsigned short vid); @@ -120,10 +122,8 @@ static inline u16 vlan_dev_vlan_id(const struct net_device *dev) return 0; } -static inline bool vlan_do_receive(struct sk_buff **skb, bool last_handler) +static inline bool vlan_do_receive(struct sk_buff **skb) { - if (((*skb)->vlan_tci & VLAN_VID_MASK) && last_handler) - (*skb)->pkt_type = PACKET_OTHERHOST; return false; } diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 830059ded496cd..fe29a6450f5712 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -5,7 +5,7 @@ #include #include "vlan.h" -bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) +bool vlan_do_receive(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; @@ -13,14 +13,8 @@ bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) struct vlan_pcpu_stats *rx_stats; vlan_dev = vlan_find_dev(skb->dev, vlan_id); - if (!vlan_dev) { - /* Only the last call to vlan_do_receive() should change - * pkt_type to PACKET_OTHERHOST - */ - if (vlan_id && last_handler) - skb->pkt_type = PACKET_OTHERHOST; + if (!vlan_dev) return false; - } skb = *skbp = skb_share_check(skb, GFP_ATOMIC); if (unlikely(!skb)) diff --git a/net/core/dev.c b/net/core/dev.c index 89e33a5d4d932c..2fb9f590b3316b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3275,18 +3275,18 @@ static int __netif_receive_skb(struct sk_buff *skb) && !skb_pfmemalloc_protocol(skb)) goto drop; - rx_handler = rcu_dereference(skb->dev->rx_handler); if (vlan_tx_tag_present(skb)) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = NULL; } - if (vlan_do_receive(&skb, !rx_handler)) + if (vlan_do_receive(&skb)) goto another_round; else if (unlikely(!skb)) goto unlock; } + rx_handler = rcu_dereference(skb->dev->rx_handler); if (rx_handler) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); @@ -3306,6 +3306,9 @@ static int __netif_receive_skb(struct sk_buff *skb) } } + if (vlan_tx_nonzero_tag_present(skb)) + skb->pkt_type = PACKET_OTHERHOST; + /* deliver only exact match when indicated */ null_or_dev = deliver_exact ? skb->dev : NULL; From da7819a17b178d73b207439dc3ca537b0d72b984 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 8 Oct 2012 11:41:15 +0000 Subject: [PATCH 0329/1071] ipv4: fix sending of redirects [ Upstream commit e81da0e113a1b7fc7449ae6213f65f89ccac6d06 ] After "Cache input routes in fib_info nexthops" (commit d2d68ba9fe) and "Elide fib_validate_source() completely when possible" (commit 7a9bc9b81a) we can not send ICMP redirects. It seems we should not cache the RTCF_DOREDIRECT flag in nh_rth_input because the same fib_info can be used for traffic that is not redirected, eg. from other input devices or from sources that are not in same subnet. As result, we have to disable the caching of RTCF_DOREDIRECT flag and to force source validation for the case when forwarding traffic to the input device. If traffic comes from directly connected source we allow redirection as it was done before both changes. Avoid setting RTCF_DOREDIRECT if IN_DEV_TX_REDIRECTS is disabled, this can avoid source address validation and to help caching the routes. After the change "Adjust semantics of rt->rt_gateway" (commit f8126f1d51) we should make sure our ICMP_REDIR_HOST messages contain daddr instead of 0.0.0.0 when target is directly connected. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/fib_frontend.c | 3 ++- net/ipv4/route.c | 30 ++++++++++++++++-------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 8e2b475da9faca..f444ac748d90be 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -322,7 +322,8 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, { int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev); - if (!r && !fib_num_tclassid_users(dev_net(dev))) { + if (!r && !fib_num_tclassid_users(dev_net(dev)) && + (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev))) { *itag = 0; return 0; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 94775f14e40d9c..7a99968df9e5b2 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -802,7 +802,8 @@ void ip_rt_send_redirect(struct sk_buff *skb) net = dev_net(rt->dst.dev); peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); if (!peer) { - icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); + icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, + rt_nexthop(rt, ip_hdr(skb)->daddr)); return; } @@ -827,7 +828,9 @@ void ip_rt_send_redirect(struct sk_buff *skb) time_after(jiffies, (peer->rate_last + (ip_rt_redirect_load << peer->rate_tokens)))) { - icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); + __be32 gw = rt_nexthop(rt, ip_hdr(skb)->daddr); + + icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw); peer->rate_last = jiffies; ++peer->rate_tokens; #ifdef CONFIG_IP_ROUTE_VERBOSE @@ -835,7 +838,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) peer->rate_tokens == ip_rt_redirect_number) net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n", &ip_hdr(skb)->saddr, inet_iif(skb), - &ip_hdr(skb)->daddr, &rt->rt_gateway); + &ip_hdr(skb)->daddr, &gw); #endif } out_put_peer: @@ -1445,10 +1448,13 @@ static int __mkroute_input(struct sk_buff *skb, goto cleanup; } - if (out_dev == in_dev && err && + do_cache = res->fi && !itag; + if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && (IN_DEV_SHARED_MEDIA(out_dev) || - inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) + inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { flags |= RTCF_DOREDIRECT; + do_cache = false; + } if (skb->protocol != htons(ETH_P_IP)) { /* Not IP (i.e. ARP). Do not create route, if it is @@ -1465,15 +1471,11 @@ static int __mkroute_input(struct sk_buff *skb, } } - do_cache = false; - if (res->fi) { - if (!itag) { - rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); - if (rt_cache_valid(rth)) { - skb_dst_set_noref(skb, &rth->dst); - goto out; - } - do_cache = true; + if (do_cache) { + rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); + if (rt_cache_valid(rth)) { + skb_dst_set_noref(skb, &rth->dst); + goto out; } } From 77470c37d5aa126548d5901a1e459ebabdac6308 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 8 Oct 2012 11:41:16 +0000 Subject: [PATCH 0330/1071] ipv4: fix forwarding for strict source routes [ Upstream commit e0adef0f7456d5d3a3bfe8ea61c7dddf146b40e1 ] After the change "Adjust semantics of rt->rt_gateway" (commit f8126f1d51) rt_gateway can be 0 but ip_forward() compares it directly with nexthop. What we want here is to check if traffic is to directly connected nexthop and to fail if using gateway. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_forward.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index ab09b126423ce3..7f35ac26a71a33 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb) rt = skb_rtable(skb); - if (opt->is_strictroute && opt->nexthop != rt->rt_gateway) + if (opt->is_strictroute && rt->rt_gateway) goto sr_failed; if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && From c82f64b90308bcb10b3862be0515d1b0efc8f928 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 8 Oct 2012 11:41:17 +0000 Subject: [PATCH 0331/1071] ipv4: make sure nh_pcpu_rth_output is always allocated [ Upstream commit f8a17175c63fd3e8b573719f7538816f8c96abf4 ] Avoid checking nh_pcpu_rth_output in fast path, abort fib_info creation on alloc_percpu failure. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/fib_semantics.c | 2 ++ net/ipv4/route.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index a74710048b13e3..9633661fe3113b 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -840,6 +840,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg) change_nexthops(fi) { nexthop_nh->nh_parent = fi; nexthop_nh->nh_pcpu_rth_output = alloc_percpu(struct rtable __rcu *); + if (!nexthop_nh->nh_pcpu_rth_output) + goto failure; } endfor_nexthops(fi) if (cfg->fc_mx) { diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 7a99968df9e5b2..079f0ba77f0d68 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1210,8 +1210,6 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt) if (rt_is_input_route(rt)) { p = (struct rtable **)&nh->nh_rth_input; } else { - if (!nh->nh_pcpu_rth_output) - goto nocache; p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output); } orig = *p; @@ -1226,7 +1224,6 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt) * unsuccessful at storing this route into the cache * we really need to set it. */ -nocache: rt->dst.flags |= DST_NOCACHE; ret = false; } From 87a2496fa427fd98aafb6d4dcf263a9f35f2f49c Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 8 Oct 2012 11:41:18 +0000 Subject: [PATCH 0332/1071] ipv4: introduce rt_uses_gateway [ Upstream commit 155e8336c373d14d87a7f91e356d85ef4b93b8f9 ] Add new flag to remember when route is via gateway. We will use it to allow rt_gateway to contain address of directly connected host for the cases when DST_NOCACHE is used or when the NH exception caches per-destination route without DST_NOCACHE flag, i.e. when routes are not used for other destinations. By this way we force the neighbour resolving to work with the routed destination but we can use different address in the packet, feature needed for IPVS-DR where original packet for virtual IP is routed via route to real IP. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/route.h | 3 ++- net/ipv4/inet_connection_sock.c | 4 +-- net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_output.c | 4 +-- net/ipv4/route.c | 48 ++++++++++++++++++--------------- net/ipv4/xfrm4_policy.c | 1 + 6 files changed, 34 insertions(+), 28 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index da22243d27600c..bc40b633a5c4dc 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -48,7 +48,8 @@ struct rtable { int rt_genid; unsigned int rt_flags; __u16 rt_type; - __u16 rt_is_input; + __u8 rt_is_input; + __u8 rt_uses_gateway; int rt_iif; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 7f75f21d7b8346..0405cc8842b841 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -386,7 +386,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, rt = ip_route_output_flow(net, fl4, sk); if (IS_ERR(rt)) goto no_route; - if (opt && opt->opt.is_strictroute && rt->rt_gateway) + if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) goto route_err; return &rt->dst; @@ -422,7 +422,7 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, rt = ip_route_output_flow(net, fl4, sk); if (IS_ERR(rt)) goto no_route; - if (opt && opt->opt.is_strictroute && rt->rt_gateway) + if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) goto route_err; rcu_read_unlock(); return &rt->dst; diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 7f35ac26a71a33..694de3b7aebfed 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb) rt = skb_rtable(skb); - if (opt->is_strictroute && rt->rt_gateway) + if (opt->is_strictroute && rt->rt_uses_gateway) goto sr_failed; if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index c196d749daf23b..94ad7ea35a4198 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -193,7 +193,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) } rcu_read_lock_bh(); - nexthop = rt->rt_gateway ? rt->rt_gateway : ip_hdr(skb)->daddr; + nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr); neigh = __ipv4_neigh_lookup_noref(dev, nexthop); if (unlikely(!neigh)) neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); @@ -371,7 +371,7 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) skb_dst_set_noref(skb, &rt->dst); packet_routed: - if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_gateway) + if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_uses_gateway) goto no_route; /* OK, we know where to send it, allocate and build IP header. */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 079f0ba77f0d68..308d9639a885cc 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1129,7 +1129,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) mtu = dst->dev->mtu; if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { - if (rt->rt_gateway && mtu > 576) + if (rt->rt_uses_gateway && mtu > 576) mtu = 576; } @@ -1180,7 +1180,9 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, if (fnhe->fnhe_gw) { rt->rt_flags |= RTCF_REDIRECTED; rt->rt_gateway = fnhe->fnhe_gw; - } + rt->rt_uses_gateway = 1; + } else if (!rt->rt_gateway) + rt->rt_gateway = daddr; orig = rcu_dereference(fnhe->fnhe_rth); rcu_assign_pointer(fnhe->fnhe_rth, rt); @@ -1189,13 +1191,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, fnhe->fnhe_stamp = jiffies; ret = true; - } else { - /* Routes we intend to cache in nexthop exception have - * the DST_NOCACHE bit clear. However, if we are - * unsuccessful at storing this route into the cache - * we really need to set it. - */ - rt->dst.flags |= DST_NOCACHE; } spin_unlock_bh(&fnhe_lock); @@ -1218,15 +1213,8 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt) if (prev == orig) { if (orig) rt_free(orig); - } else { - /* Routes we intend to cache in the FIB nexthop have - * the DST_NOCACHE bit clear. However, if we are - * unsuccessful at storing this route into the cache - * we really need to set it. - */ - rt->dst.flags |= DST_NOCACHE; + } else ret = false; - } return ret; } @@ -1287,8 +1275,10 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, if (fi) { struct fib_nh *nh = &FIB_RES_NH(*res); - if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) + if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) { rt->rt_gateway = nh->nh_gw; + rt->rt_uses_gateway = 1; + } dst_init_metrics(&rt->dst, fi->fib_metrics, true); #ifdef CONFIG_IP_ROUTE_CLASSID rt->dst.tclassid = nh->nh_tclassid; @@ -1297,8 +1287,18 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, cached = rt_bind_exception(rt, fnhe, daddr); else if (!(rt->dst.flags & DST_NOCACHE)) cached = rt_cache_route(nh, rt); - } - if (unlikely(!cached)) + if (unlikely(!cached)) { + /* Routes we intend to cache in nexthop exception or + * FIB nexthop have the DST_NOCACHE bit clear. + * However, if we are unsuccessful at storing this + * route into the cache we really need to set it. + */ + rt->dst.flags |= DST_NOCACHE; + if (!rt->rt_gateway) + rt->rt_gateway = daddr; + rt_add_uncached_list(rt); + } + } else rt_add_uncached_list(rt); #ifdef CONFIG_IP_ROUTE_CLASSID @@ -1366,6 +1366,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_iif = 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); if (our) { rth->dst.input= ip_local_deliver; @@ -1435,7 +1436,6 @@ static int __mkroute_input(struct sk_buff *skb, return -EINVAL; } - err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res), in_dev->dev, in_dev, &itag); if (err < 0) { @@ -1491,6 +1491,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_iif = 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); rth->dst.input = ip_forward; @@ -1658,6 +1659,7 @@ out: return err; rth->rt_iif = 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); if (res.type == RTN_UNREACHABLE) { rth->dst.input= ip_error; @@ -1826,6 +1828,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_iif = orig_oif ? : 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); RT_CACHE_STAT_INC(out_slow_tot); @@ -2104,6 +2107,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_flags = ort->rt_flags; rt->rt_type = ort->rt_type; rt->rt_gateway = ort->rt_gateway; + rt->rt_uses_gateway = ort->rt_uses_gateway; INIT_LIST_HEAD(&rt->rt_uncached); @@ -2182,7 +2186,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr)) goto nla_put_failure; } - if (rt->rt_gateway && + if (rt->rt_uses_gateway && nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway)) goto nla_put_failure; diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 681ea2f413e2ff..05c5ab8d983c46 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -91,6 +91,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, RTCF_LOCAL); xdst->u.rt.rt_type = rt->rt_type; xdst->u.rt.rt_gateway = rt->rt_gateway; + xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway; xdst->u.rt.rt_pmtu = rt->rt_pmtu; INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); From 1f6cc51c46ed910f8f68d4f3359ad3bca7ee7bc2 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 8 Oct 2012 11:41:19 +0000 Subject: [PATCH 0333/1071] ipv4: Add FLOWI_FLAG_KNOWN_NH [ Upstream commit c92b96553a80c1dbe2ebe128bbe37c8f98f148bf ] Add flag to request that output route should be returned with known rt_gateway, in case we want to use it as nexthop for neighbour resolving. The returned route can be cached as follows: - in NH exception: because the cached routes are not shared with other destinations - in FIB NH: when using gateway because all destinations for NH share same gateway As last option, to return rt_gateway!=0 we have to set DST_NOCACHE. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/flow.h | 1 + net/ipv4/route.c | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/net/flow.h b/include/net/flow.h index e1dd5082ec7e43..628e11b98c580d 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -21,6 +21,7 @@ struct flowi_common { __u8 flowic_flags; #define FLOWI_FLAG_ANYSRC 0x01 #define FLOWI_FLAG_CAN_SLEEP 0x02 +#define FLOWI_FLAG_KNOWN_NH 0x04 __u32 flowic_secid; }; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 308d9639a885cc..2a1383c10fb28b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1762,6 +1762,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, struct in_device *in_dev; u16 type = res->type; struct rtable *rth; + bool do_cache; in_dev = __in_dev_get_rcu(dev_out); if (!in_dev) @@ -1798,24 +1799,36 @@ static struct rtable *__mkroute_output(const struct fib_result *res, } fnhe = NULL; + do_cache = fi != NULL; if (fi) { struct rtable __rcu **prth; + struct fib_nh *nh = &FIB_RES_NH(*res); - fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr); + fnhe = find_exception(nh, fl4->daddr); if (fnhe) prth = &fnhe->fnhe_rth; - else - prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output); + else { + if (unlikely(fl4->flowi4_flags & + FLOWI_FLAG_KNOWN_NH && + !(nh->nh_gw && + nh->nh_scope == RT_SCOPE_LINK))) { + do_cache = false; + goto add; + } + prth = __this_cpu_ptr(nh->nh_pcpu_rth_output); + } rth = rcu_dereference(*prth); if (rt_cache_valid(rth)) { dst_hold(&rth->dst); return rth; } } + +add: rth = rt_dst_alloc(dev_out, IN_DEV_CONF_GET(in_dev, NOPOLICY), IN_DEV_CONF_GET(in_dev, NOXFRM), - fi); + do_cache); if (!rth) return ERR_PTR(-ENOBUFS); From c4e6940cc12c1cac1e8664a2a46ef01f0783c69c Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 8 Oct 2012 11:41:20 +0000 Subject: [PATCH 0334/1071] ipvs: fix ARP resolving for direct routing mode [ Upstream commit ad4d3ef8b7eb527cca478dc08c02c10936e64115 ] After the change "Make neigh lookups directly in output packet path" (commit a263b30936) IPVS can not reach the real server for DR mode because we resolve the destination address from IP header, not from route neighbour. Use the new FLOWI_FLAG_KNOWN_NH flag to request output routes with known nexthop, so that it has preference on resolving. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/ipvs/ip_vs_xmit.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 65b616ae171636..c3c6291555408e 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -49,6 +49,7 @@ enum { IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to * local */ + IP_VS_RT_MODE_KNOWN_NH = 16,/* Route via remote addr */ }; /* @@ -103,6 +104,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, memset(&fl4, 0, sizeof(fl4)); fl4.daddr = dest->addr.ip; fl4.flowi4_tos = rtos; + fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? + FLOWI_FLAG_KNOWN_NH : 0; rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) { spin_unlock(&dest->dst_lock); @@ -127,6 +130,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, memset(&fl4, 0, sizeof(fl4)); fl4.daddr = daddr; fl4.flowi4_tos = rtos; + fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? + FLOWI_FLAG_KNOWN_NH : 0; rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) { IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", @@ -1014,7 +1019,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, RT_TOS(iph->tos), IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL, NULL))) + IP_VS_RT_MODE_NON_LOCAL | + IP_VS_RT_MODE_KNOWN_NH, NULL))) goto tx_error_icmp; if (rt->rt_flags & RTCF_LOCAL) { ip_rt_put(rt); From 0b5b763426e93ed843aad22101265f0f975e48a5 Mon Sep 17 00:00:00 2001 From: "jeff.liu" Date: Mon, 8 Oct 2012 18:57:27 +0000 Subject: [PATCH 0335/1071] RDS: fix rds-ping spinlock recursion [ Upstream commit 5175a5e76bbdf20a614fb47ce7a38f0f39e70226 ] This is the revised patch for fixing rds-ping spinlock recursion according to Venkat's suggestions. RDS ping/pong over TCP feature has been broken for years(2.6.39 to 3.6.0) since we have to set TCP cork and call kernel_sendmsg() between ping/pong which both need to lock "struct sock *sk". However, this lock has already been hold before rds_tcp_data_ready() callback is triggerred. As a result, we always facing spinlock resursion which would resulting in system panic. Given that RDS ping is only used to test the connectivity and not for serious performance measurements, we can queue the pong transmit to rds_wq as a delayed response. Reported-by: Dan Carpenter CC: Venkat Venkatsubra CC: David S. Miller CC: James Morris Signed-off-by: Jie Liu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rds/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rds/send.c b/net/rds/send.c index 96531d4033a216..88eace57dd6bb1 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -1122,7 +1122,7 @@ rds_send_pong(struct rds_connection *conn, __be16 dport) rds_stats_inc(s_send_pong); if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags)) - rds_send_xmit(conn); + queue_delayed_work(rds_wq, &conn->c_send_w, 0); rds_message_put(rm); return 0; From f124c052cdd3c8bafd62c2d8d98b90a16a688e7e Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 12 Oct 2012 04:34:17 +0000 Subject: [PATCH 0336/1071] tcp: resets are misrouted [ Upstream commit 4c67525849e0b7f4bd4fab2487ec9e43ea52ef29 ] After commit e2446eaa ("tcp_v4_send_reset: binding oif to iif in no sock case").. tcp resets are always lost, when routing is asymmetric. Yes, backing out that patch will result in misrouting of resets for dead connections which used interface binding when were alive, but we actually cannot do anything here. What's died that's died and correct handling normal unbound connections is obviously a priority. Comment to comment: > This has few benefits: > 1. tcp_v6_send_reset already did that. It was done to route resets for IPv6 link local addresses. It was a mistake to do so for global addresses. The patch fixes this as well. Actually, the problem appears to be even more serious than guaranteed loss of resets. As reported by Sergey Soloviev , those misrouted resets create a lot of arp traffic and huge amount of unresolved arp entires putting down to knees NAT firewalls which use asymmetric routing. Signed-off-by: Alexey Kuznetsov Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_ipv4.c | 7 ++++--- net/ipv6/tcp_ipv6.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 00a748d14062d5..db7bfad4308221 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -693,10 +693,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.csumoffset = offsetof(struct tcphdr, check) / 2; arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; /* When socket is gone, all binding information is lost. - * routing might fail in this case. using iif for oif to - * make sure we can deliver it + * routing might fail in this case. No choice here, if we choose to force + * input interface, we will misroute in case of asymmetric route. */ - arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb); + if (sk) + arg.bound_dev_if = sk->sk_bound_dev_if; net = dev_net(skb_dst(skb)->dev); arg.tos = ip_hdr(skb)->tos; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index acd32e3f1b68e7..7e32d429ea6541 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -863,7 +863,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); fl6.flowi6_proto = IPPROTO_TCP; - fl6.flowi6_oif = inet6_iif(skb); + if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) + fl6.flowi6_oif = inet6_iif(skb); fl6.fl6_dport = t1->dest; fl6.fl6_sport = t1->source; security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); From 8ca3905dc049794f2ada11abe8252a8cde734952 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 16 Oct 2012 07:37:27 +0000 Subject: [PATCH 0337/1071] ipv6: addrconf: fix /proc/net/if_inet6 [ Upstream commit 9f0d3c2781baa1102108e16efbe640dd74564a7c ] Commit 1d5783030a1 (ipv6/addrconf: speedup /proc/net/if_inet6 filling) added bugs hiding some devices from if_inet6 and breaking applications. "ip -6 addr" could still display all IPv6 addresses, while "ifconfig -a" couldnt. One way to reproduce the bug is by starting in a shell : unshare -n /bin/bash ifconfig lo up And in original net namespace, lo device disappeared from if_inet6 Reported-by: Jan Hinnerk Stosch Tested-by: Jan Hinnerk Stosch Signed-off-by: Eric Dumazet Cc: Mihai Maruseac Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ea3e9af86d4bf7..b10374d048ab35 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3088,14 +3088,15 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos) struct hlist_node *n; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; /* sync with offset */ if (p < state->offset) { p++; continue; } state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } /* prepare for next bucket */ @@ -3113,18 +3114,20 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct hlist_node *n = &ifa->addr_lst; hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } while (++state->bucket < IN6_ADDR_HSIZE) { state->offset = 0; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } } From 8f3d8be7a7259de7cff4ffa1eec1894ddc1a4397 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Oct 2012 17:25:00 -0700 Subject: [PATCH 0338/1071] sparc64: fix ptrace interaction with force_successful_syscall_return() [ Upstream commit 55c2770e413e96871147b9406a9c41fe9bc5209c ] we want syscall_trace_leave() called on exit from any syscall; skipping its call in case we'd done force_successful_syscall_return() is broken... Signed-off-by: Al Viro Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/syscalls.S | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 1d7e274f3f2b42..7f5f65d0b3fde9 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -212,24 +212,20 @@ linux_sparc_syscall: 3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] ret_sys_call: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 sllx %g2, 32, %g2 - /* Check if force_successful_syscall_return() - * was invoked. - */ - ldub [%g6 + TI_SYS_NOERROR], %l2 - brnz,a,pn %l2, 80f - stb %g0, [%g6 + TI_SYS_NOERROR] - cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 -80: + andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 + ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc + +2: + stb %g0, [%g6 + TI_SYS_NOERROR] /* System call success, clear Carry condition code. */ andn %g3, %g2, %g3 +3: stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 add %l1, 0x4, %l2 ! npc = npc+4 @@ -238,20 +234,20 @@ ret_sys_call: stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] 1: + /* Check if force_successful_syscall_return() + * was invoked. + */ + ldub [%g6 + TI_SYS_NOERROR], %l2 + brnz,pn %l2, 2b + ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. */ - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 sub %g0, %o0, %o0 - or %g3, %g2, %g3 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, linux_syscall_trace2 - add %l1, 0x4, %l2 ! npc = npc+4 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] + ba,pt %xcc, 3b + or %g3, %g2, %g3 - b,pt %xcc, rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] linux_syscall_trace2: call syscall_trace_leave add %sp, PTREGS_OFF, %o0 From f386dbc80c65fe40a5a76806358a5e565086e23c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 14 Oct 2012 17:59:40 -0700 Subject: [PATCH 0339/1071] sparc64: Like x86 we should check current->mm during perf backtrace generation. [ Upstream commit 08280e6c4c2e8049ac61d9e8e3536ec1df629c0d ] If the MM is not active, only report the top-level PC. Do not try to access the address space. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/perf_event.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 5713957dcb8a38..b0cce262f8381b 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1426,8 +1426,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] + STACK_BIAS; do { struct sparc_stackf *usf, sf; @@ -1448,8 +1446,6 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; do { struct sparc_stackf32 *usf, sf; @@ -1468,6 +1464,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) { + perf_callchain_store(entry, regs->tpc); + + if (!current->mm) + return; + flushw_user(); if (test_thread_flag(TIF_32BIT)) perf_callchain_user_32(entry, regs); From 060672c399c00f09d8e238756c1853a4c870b48a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Oct 2012 13:05:25 -0700 Subject: [PATCH 0340/1071] sparc64: Fix bit twiddling in sparc_pmu_enable_event(). [ Upstream commit e793d8c6740f8fe704fa216e95685f4d92c4c4b9 ] There was a serious disconnect in the logic happening in sparc_pmu_disable_event() vs. sparc_pmu_enable_event(). Event disable is implemented by programming a NOP event into the PCR. However, event enable was not reversing this operation. Instead, it was setting the User/Priv/Hypervisor trace enable bits. That's not sparc_pmu_enable_event()'s job, that's what sparc_pmu_enable() and sparc_pmu_disable() do . The intent of sparc_pmu_enable_event() is clear, since it first clear out the event type encoding field. So fix this by OR'ing in the event encoding rather than the trace enable bits. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/perf_event.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index b0cce262f8381b..ac180370e59d5d 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -557,11 +557,13 @@ static u64 nop_for_index(int idx) static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx) { - u64 val, mask = mask_for_index(idx); + u64 enc, val, mask = mask_for_index(idx); + + enc = perf_event_get_enc(cpuc->events[idx]); val = cpuc->pcr; val &= ~mask; - val |= hwc->config; + val |= event_encoding(enc, idx); cpuc->pcr = val; pcr_ops->write(cpuc->pcr); From 3ae3dacc90a358dc113b565ddb1f4560d68109b1 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 5 Oct 2012 17:57:39 -0700 Subject: [PATCH 0341/1071] mac80211: call drv_get_tsf() in sleepable context commit 55fabefe3695241e6ccfa0cd4974f3fa497693dc upstream. The call to drv_get/set_tsf() was put on the workqueue to perform tsf adjustments since that function might sleep. However it ended up inside a spinlock, whose critical section must be atomic. Do tsf adjustment outside the spinlock instead, and get rid of a warning. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mesh_sync.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index accfa00ffcdf0e..a16b7b4b1e026a 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c @@ -56,7 +56,6 @@ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) u64 tsfdelta; spin_lock_bh(&ifmsh->sync_offset_lock); - if (ifmsh->sync_offset_clockdrift_max < beacon_int_fraction) { msync_dbg(sdata, "TBTT : max clockdrift=%lld; adjusting\n", (long long) ifmsh->sync_offset_clockdrift_max); @@ -69,11 +68,11 @@ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) tsfdelta = -beacon_int_fraction; ifmsh->sync_offset_clockdrift_max -= beacon_int_fraction; } + spin_unlock_bh(&ifmsh->sync_offset_lock); tsf = drv_get_tsf(local, sdata); if (tsf != -1ULL) drv_set_tsf(local, sdata, tsf + tsfdelta); - spin_unlock_bh(&ifmsh->sync_offset_lock); } static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, From c32b33d6d757f244ffa570478bd43a12f2ad5c77 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 28 Oct 2012 10:57:51 -0700 Subject: [PATCH 0342/1071] Linux 3.6.4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6cdadf47f6a36e..dcf132ae3f07fd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 3 +SUBLEVEL = 4 EXTRAVERSION = NAME = Terrified Chipmunk From 1aafcaec30b2b4cfcab0472692426f46ab104ef9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 16 Oct 2012 12:51:45 -0400 Subject: [PATCH 0343/1071] drm/radeon: add some new SI PCI ids commit b6aa22db7857ab7ed042d6c56b800bfc727cfdff upstream. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index c78bb997e2c608..af1cbaf535edeb 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -205,6 +205,8 @@ {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ @@ -217,6 +219,7 @@ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ From 7eff2fdcdb9c78d8d2c9e27b223d67b4a9da3a5a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 19 Oct 2012 13:27:04 -0400 Subject: [PATCH 0344/1071] drm/radeon: add error output if VM CS fails on cayman commit c71721324c612f7f040657ce9917d87f530f9784 upstream. So we know why the CS was rejected. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index d883b20f45d2dd..e932810c9b5a6f 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2829,6 +2829,7 @@ static bool evergreen_vm_reg_valid(u32 reg) case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: return true; default: + DRM_ERROR("Invalid register 0x%x in CS\n", reg); return false; } } From 92b0d35d9926aa5e17540928b18cc7a997ab78cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stef=C3=A1n=20Freyr?= Date: Fri, 19 Oct 2012 22:46:00 +0200 Subject: [PATCH 0345/1071] ALSA: hda - add dock support for Thinkpad T430 commit 84f98fdf7865fbd35b312eb39ea91e5618c514c7 upstream. I have a Lenovo ThinkPad T430 and an UltraBase Series 3 docking station. Without this patch, if I plug my headphones into the jack on the computer, everything works fine. The computer speakers mute and the audio is played in the headphones. However, if I plug into the docking station headphone jack the computer speakers are muted but there is no audio in the headphones. Addresses https://bugs.launchpad.net/bugs/1060372 Signed-off-by: Joseph Salisbury Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 155cbd260f1321..0d5da6699e655f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6214,6 +6214,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), From 64d03fc009db65b2308c7e6319c58454f499632a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 20 Oct 2012 10:55:21 +0200 Subject: [PATCH 0346/1071] ALSA: hda - Fix silent headphone output from Toshiba P200 commit cb766404e6b8c566569eb9ada02ea45d28729864 upstream. By some reason, Toshiba laptop doesn't like the EAPD turned up for the headphone pin. Add a fix up code to force to turn down EAPD for NID 0x15. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=569991 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0d5da6699e655f..70ce60fd530133 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5704,6 +5704,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = { enum { ALC268_FIXUP_INV_DMIC, + ALC268_FIXUP_HP_EAPD, }; static const struct alc_fixup alc268_fixups[] = { @@ -5711,10 +5712,26 @@ static const struct alc_fixup alc268_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc_fixup_inv_dmic_0x12, }, + [ALC268_FIXUP_HP_EAPD] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0}, + {} + } + }, }; static const struct alc_model_fixup alc268_fixup_models[] = { {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, + {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"}, + {} +}; + +static const struct snd_pci_quirk alc268_fixup_tbl[] = { + /* below is codec SSID since multiple Toshiba laptops have the + * same PCI SSID 1179:ff00 + */ + SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD), {} }; @@ -5749,7 +5766,7 @@ static int patch_alc268(struct hda_codec *codec) spec = codec->spec; - alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); + alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); /* automatic parse from the BIOS config */ From f625bfd3fb3768dd116303e87799c40f1a4cd92e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 26 Oct 2012 10:05:07 -0700 Subject: [PATCH 0347/1071] VFS: don't do protected {sym,hard}links by default commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415 upstream. In commit 800179c9b8a1 ("This adds symlink and hardlink restrictions to the Linux VFS"), the new link protections were enabled by default, in the hope that no actual application would care, despite it being technically against legacy UNIX (and documented POSIX) behavior. However, it does turn out to break some applications. It's rare, and it's unfortunate, but it's unacceptable to break existing systems, so we'll have to default to legacy behavior. In particular, it has broken the way AFD distributes files, see http://www.dwd.de/AFD/ along with some legacy scripts. Distributions can end up setting this at initrd time or in system scripts: if you have security problems due to link attacks during your early boot sequence, you have bigger problems than some kernel sysctl setting. Do: echo 1 > /proc/sys/fs/protected_symlinks echo 1 > /proc/sys/fs/protected_hardlinks to re-enable the link protections. Alternatively, we may at some point introduce a kernel config option that sets these kinds of "more secure but not traditional" behavioural options automatically. Reported-by: Nick Bowler Reported-by: Holger Kiehl Cc: Kees Cook Cc: Ingo Molnar Cc: Andrew Morton Cc: Al Viro Cc: Alan Cox Cc: Theodore Ts'o Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/namei.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 81bd5463d908df..091c4b7986cba1 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -651,8 +651,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki path_put(link); } -int sysctl_protected_symlinks __read_mostly = 1; -int sysctl_protected_hardlinks __read_mostly = 1; +int sysctl_protected_symlinks __read_mostly = 0; +int sysctl_protected_hardlinks __read_mostly = 0; /** * may_follow_link - Check symlink following for unsafe situations From 73e75b4b4bd0ff7d2911165e9119306b95282c21 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 25 Oct 2012 13:38:14 -0700 Subject: [PATCH 0348/1071] gen_init_cpio: avoid stack overflow when expanding commit 20f1de659b77364d55d4e7fad2ef657e7730323f upstream. Fix possible overflow of the buffer used for expanding environment variables when building file list. In the extremely unlikely case of an attacker having control over the environment variables visible to gen_init_cpio, control over the contents of the file gen_init_cpio parses, and gen_init_cpio was built without compiler hardening, the attacker can gain arbitrary execution control via a stack buffer overflow. $ cat usr/crash.list file foo ${BIG}${BIG}${BIG}${BIG}${BIG}${BIG} 0755 0 0 $ BIG=$(perl -e 'print "A" x 4096;') ./usr/gen_init_cpio usr/crash.list *** buffer overflow detected ***: ./usr/gen_init_cpio terminated This also replaces the space-indenting with tabs. Patch based on existing fix extracted from grsecurity. Signed-off-by: Kees Cook Cc: Michal Marek Cc: Brad Spengler Cc: PaX Team Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- usr/gen_init_cpio.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c index af0f22fb1ef71e..aca6edcbbc6fa0 100644 --- a/usr/gen_init_cpio.c +++ b/usr/gen_init_cpio.c @@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location, int retval; int rc = -1; int namesize; - int i; + unsigned int i; mode |= S_IFREG; @@ -381,25 +381,28 @@ static int cpio_mkfile(const char *name, const char *location, static char *cpio_replace_env(char *new_location) { - char expanded[PATH_MAX + 1]; - char env_var[PATH_MAX + 1]; - char *start; - char *end; - - for (start = NULL; (start = strstr(new_location, "${")); ) { - end = strchr(start, '}'); - if (start < end) { - *env_var = *expanded = '\0'; - strncat(env_var, start + 2, end - start - 2); - strncat(expanded, new_location, start - new_location); - strncat(expanded, getenv(env_var), PATH_MAX); - strncat(expanded, end + 1, PATH_MAX); - strncpy(new_location, expanded, PATH_MAX); - } else - break; - } - - return new_location; + char expanded[PATH_MAX + 1]; + char env_var[PATH_MAX + 1]; + char *start; + char *end; + + for (start = NULL; (start = strstr(new_location, "${")); ) { + end = strchr(start, '}'); + if (start < end) { + *env_var = *expanded = '\0'; + strncat(env_var, start + 2, end - start - 2); + strncat(expanded, new_location, start - new_location); + strncat(expanded, getenv(env_var), + PATH_MAX - strlen(expanded)); + strncat(expanded, end + 1, + PATH_MAX - strlen(expanded)); + strncpy(new_location, expanded, PATH_MAX); + new_location[PATH_MAX] = 0; + } else + break; + } + + return new_location; } From 8f86e6317334a1e220b1e4b77979a0fb7149f811 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 25 Oct 2012 13:38:16 -0700 Subject: [PATCH 0349/1071] fs/compat_ioctl.c: VIDEO_SET_SPU_PALETTE missing error check commit 12176503366885edd542389eed3aaf94be163fdb upstream. The compat ioctl for VIDEO_SET_SPU_PALETTE was missing an error check while converting ioctl arguments. This could lead to leaking kernel stack contents into userspace. Patch extracted from existing fix in grsecurity. Signed-off-by: Kees Cook Cc: David Miller Cc: Brad Spengler Cc: PaX Team Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/compat_ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index debdfe0fc809ed..5d2069ff635cdb 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, err = get_user(palp, &up->palette); err |= get_user(length, &up->length); + if (err) + return -EFAULT; up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); err = put_user(compat_ptr(palp), &up_native->palette); From 36fe350e99a78d973a2a82b6b7dbc01f52044790 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Thu, 25 Oct 2012 13:38:11 -0700 Subject: [PATCH 0350/1071] drivers/rtc/rtc-imxdi.c: add missing spin lock initialization commit fee0de7791f967c2c5f0d43eb7b7261761b45e64 upstream. Signed-off-by: Jan Luebbe Cc: Alessandro Zummo Cc: Roland Stigge Cc: Grant Likely Tested-by: Roland Stigge Cc: Sascha Hauer Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-imxdi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 891cd6c61d0ae7..4eed51044c5dd3 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev) if (imxdi->ioaddr == NULL) return -ENOMEM; + spin_lock_init(&imxdi->irq_lock); + imxdi->irq = platform_get_irq(pdev, 0); if (imxdi->irq < 0) return imxdi->irq; From e5982ed6b4de838a30c6dfaa255ffdcc8c5584f2 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 25 Oct 2012 13:37:51 -0700 Subject: [PATCH 0351/1071] genalloc: stop crashing the system when destroying a pool commit eedce141cd2dad8d0cefc5468ef41898949a7031 upstream. The genalloc code uses the bitmap API from include/linux/bitmap.h and lib/bitmap.c, which is based on long values. Both bitmap_set from lib/bitmap.c and bitmap_set_ll, which is the lockless version from genalloc.c, use BITMAP_LAST_WORD_MASK to set the first bits in a long in the bitmap. That one uses (1 << bits) - 1, 0b111, if you are setting the first three bits. This means that the API counts from the least significant bits (LSB from now on) to the MSB. The LSB in the first long is bit 0, then. The same works for the lookup functions. The genalloc code uses longs for the bitmap, as it should. In include/linux/genalloc.h, struct gen_pool_chunk has unsigned long bits[0] as its last member. When allocating the struct, genalloc should reserve enough space for the bitmap. This should be a proper number of longs that can fit the amount of bits in the bitmap. However, genalloc allocates an integer number of bytes that fit the amount of bits, but may not be an integer amount of longs. 9 bytes, for example, could be allocated for 70 bits. This is a problem in itself if the Least Significat Bit in a long is in the byte with the largest address, which happens in Big Endian machines. This means genalloc is not allocating the byte in which it will try to set or check for a bit. This may end up in memory corruption, where genalloc will try to set the bits it has not allocated. In fact, genalloc may not set these bits because it may find them already set, because they were not zeroed since they were not allocated. And that's what causes a BUG when gen_pool_destroy is called and check for any set bits. What really happens is that genalloc uses kmalloc_node with __GFP_ZERO on gen_pool_add_virt. With SLAB and SLUB, this means the whole slab will be cleared, not only the requested bytes. Since struct gen_pool_chunk has a size that is a multiple of 8, and slab sizes are multiples of 8, we get lucky and allocate and clear the right amount of bytes. Hower, this is not the case with SLOB or with older code that did memset after allocating instead of using __GFP_ZERO. So, a simple module as this (running 3.6.0), will cause a crash when rmmod'ed. [root@phantom-lp2 foo]# cat foo.c #include #include #include #include MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); static struct gen_pool *foo_pool; static __init int foo_init(void) { int ret; foo_pool = gen_pool_create(10, -1); if (!foo_pool) return -ENOMEM; ret = gen_pool_add(foo_pool, 0xa0000000, 32 << 10, -1); if (ret) { gen_pool_destroy(foo_pool); return ret; } return 0; } static __exit void foo_exit(void) { gen_pool_destroy(foo_pool); } module_init(foo_init); module_exit(foo_exit); [root@phantom-lp2 foo]# zcat /proc/config.gz | grep SLOB CONFIG_SLOB=y [root@phantom-lp2 foo]# insmod ./foo.ko [root@phantom-lp2 foo]# rmmod foo ------------[ cut here ]------------ kernel BUG at lib/genalloc.c:243! cpu 0x4: Vector: 700 (Program Check) at [c0000000bb0e7960] pc: c0000000003cb50c: .gen_pool_destroy+0xac/0x110 lr: c0000000003cb4fc: .gen_pool_destroy+0x9c/0x110 sp: c0000000bb0e7be0 msr: 8000000000029032 current = 0xc0000000bb0e0000 paca = 0xc000000006d30e00 softe: 0 irq_happened: 0x01 pid = 13044, comm = rmmod kernel BUG at lib/genalloc.c:243! [c0000000bb0e7ca0] d000000004b00020 .foo_exit+0x20/0x38 [foo] [c0000000bb0e7d20] c0000000000dff98 .SyS_delete_module+0x1a8/0x290 [c0000000bb0e7e30] c0000000000097d4 syscall_exit+0x0/0x94 --- Exception: c00 (System Call) at 000000800753d1a0 SP (fffd0b0e640) is in userspace Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Paul Gortmaker Cc: Benjamin Gaignard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/genalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/genalloc.c b/lib/genalloc.c index 6bc04aab6ec717..7cb7a5dac09b4a 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -176,7 +176,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy struct gen_pool_chunk *chunk; int nbits = size >> pool->min_alloc_order; int nbytes = sizeof(struct gen_pool_chunk) + - (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; + BITS_TO_LONGS(nbits) * sizeof(long); chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid); if (unlikely(chunk == NULL)) From cd88996ecbb6f66edd1dbcd15c1219f3291a3733 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 19 Oct 2012 17:53:01 +0100 Subject: [PATCH 0352/1071] ARM: 7559/1: smp: switch away from the idmap before updating init_mm.mm_count commit 5f40b909728ad784eb43aa309d3c4e9bdf050781 upstream. When booting a secondary CPU, the primary CPU hands two sets of page tables via the secondary_data struct: (1) swapper_pg_dir: a normal, cacheable, shared (if SMP) mapping of the kernel image (i.e. the tables used by init_mm). (2) idmap_pgd: an uncached mapping of the .idmap.text ELF section. The idmap is generally used when enabling and disabling the MMU, which includes early CPU boot. In this case, the secondary CPU switches to swapper as soon as it enters C code: struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); cpu_switch_mm(mm->pgd, mm); This causes a problem on ARMv7, where the identity mapping is treated as strongly-ordered leading to architecturally UNPREDICTABLE behaviour of exclusive accesses, such as those used by atomic_inc. This patch re-orders the secondary_start_kernel function so that we switch to swapper before performing any exclusive accesses. Reported-by: Gilles Chanteperdrix Cc: David McKay Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/smp.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index ebd8ad274d76bb..0181f7efc53b01 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -222,18 +222,24 @@ static void percpu_timer_setup(void); asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + /* + * The identity mapping is uncached (strongly ordered), so + * switch away from it before attempting any exclusive accesses. + */ + cpu_switch_mm(mm->pgd, mm); + enter_lazy_tlb(mm, current); + local_flush_tlb_all(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ + cpu = smp_processor_id(); atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); - cpu_switch_mm(mm->pgd, mm); - enter_lazy_tlb(mm, current); - local_flush_tlb_all(); printk("CPU%u: Booted secondary processor\n", cpu); From e7ecfa878b2a49dbe28349d9529ee52777f86225 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 4 Oct 2012 14:48:10 +0100 Subject: [PATCH 0353/1071] x86-64: Fix page table accounting commit 876ee61aadf01aa0db981b5d249cbdd53dc28b5e upstream. Commit 20167d3421a089a1bf1bd680b150dc69c9506810 ("x86-64: Fix accounting in kernel_physical_mapping_init()") went a little too far by entirely removing the counting of pre-populated page tables: this should be done at boot time (to cover the page tables set up in early boot code), but shouldn't be done during memory hot add. Hence, re-add the removed increments of "pages", but make them and the one in phys_pte_init() conditional upon !after_bootmem. Reported-Acked-and-Tested-by: Hugh Dickins Signed-off-by: Jan Beulich Link: http://lkml.kernel.org/r/506DAFBA020000780009FA8C@nat28.tlf.novell.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/init_64.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 2b6b4a3c8beb87..3baff255adac64 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, * these mappings are more intelligent. */ if (pte_val(*pte)) { - pages++; + if (!after_bootmem) + pages++; continue; } @@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, * attributes. */ if (page_size_mask & (1 << PG_LEVEL_2M)) { + if (!after_bootmem) + pages++; last_map_addr = next; continue; } @@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, * attributes. */ if (page_size_mask & (1 << PG_LEVEL_1G)) { + if (!after_bootmem) + pages++; last_map_addr = next; continue; } From 8a9ff86ca1afa2381646774e4c5f10fb10996378 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Thu, 18 Oct 2012 14:33:23 +0800 Subject: [PATCH 0354/1071] Revert "x86/mm: Fix the size calculation of mapping tables" commit 7b16bbf97375d9fb7fc107b3f80afeb94a204e44 upstream. Commit: 722bc6b16771 x86/mm: Fix the size calculation of mapping tables Tried to address the issue that the first 2/4M should use 4k pages if PSE enabled, but extra counts should only be valid for x86_32. This commit caused a kdump regression: the kdump kernel hangs. Work is in progress to fundamentally fix the various page table initialization issues that we have, via the design suggested by H. Peter Anvin, but it's not ready yet to be merged. So, to get a working kdump revert to the last known working version, which is the revert of this commit and of a followup fix (which was incomplete): bd2753b2dda7 x86/mm: Only add extra pages count for the first memory range during pre-allocation Tested kdump on physical and virtual machines. Signed-off-by: Dave Young Acked-by: Yinghai Lu Acked-by: Cong Wang Acked-by: Flavio Leitner Tested-by: Flavio Leitner Cc: Dan Carpenter Cc: Cong Wang Cc: Flavio Leitner Cc: Tejun Heo Cc: ianfang.cn@gmail.com Cc: Vivek Goyal Cc: Linus Torvalds Cc: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/init.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index ab1f6a93b527c9..8653b3a722be2d 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -29,14 +29,8 @@ int direct_gbpages #endif ; -struct map_range { - unsigned long start; - unsigned long end; - unsigned page_size_mask; -}; - -static void __init find_early_table_space(struct map_range *mr, unsigned long end, - int use_pse, int use_gbpages) +static void __init find_early_table_space(unsigned long end, int use_pse, + int use_gbpages) { unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; phys_addr_t base; @@ -61,10 +55,6 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en #ifdef CONFIG_X86_32 extra += PMD_SIZE; #endif - /* The first 2/4M doesn't use large pages. */ - if (mr->start < PMD_SIZE) - extra += mr->end - mr->start; - ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; @@ -95,6 +85,12 @@ void __init native_pagetable_reserve(u64 start, u64 end) memblock_reserve(start, end - start); } +struct map_range { + unsigned long start; + unsigned long end; + unsigned page_size_mask; +}; + #ifdef CONFIG_X86_32 #define NR_RANGE_MR 3 #else /* CONFIG_X86_64 */ @@ -267,7 +263,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, * nodes are discovered. */ if (!after_bootmem) - find_early_table_space(&mr[0], end, use_pse, use_gbpages); + find_early_table_space(end, use_pse, use_gbpages); for (i = 0; i < nr_range; i++) ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, From 40555316c4423bb20d98c747d32aea5503c463a2 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Oct 2012 16:35:18 -0700 Subject: [PATCH 0355/1071] x86, mm: Trim memory in memblock to be page aligned commit 6ede1fd3cb404c0016de6ac529df46d561bd558b upstream. We will not map partial pages, so need to make sure memblock allocation will not allocate those bytes out. Also we will use for_each_mem_pfn_range() to loop to map memory range to keep them consistent. Signed-off-by: Yinghai Lu Link: http://lkml.kernel.org/r/CAE9FiQVZirvaBMFYRfXMmWEcHbKSicQEHz4VAwUv0xFCk51ZNw@mail.gmail.com Acked-by: Jacob Shin Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/e820.c | 3 +++ include/linux/memblock.h | 1 + mm/memblock.c | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index ed858e9e9a7461..df06ade26bef84 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void) memblock_add(ei->addr, ei->size); } + /* throw away partial pages */ + memblock_trim_memory(PAGE_SIZE); + memblock_dump_all(); } diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 19dc455b4f3dd0..c948c440ea2c87 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +void memblock_trim_memory(phys_addr_t align); #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, diff --git a/mm/memblock.c b/mm/memblock.c index 82aa349d2f7a04..0e490e8dcebae3 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -929,6 +929,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; } +void __init_memblock memblock_trim_memory(phys_addr_t align) +{ + int i; + phys_addr_t start, end, orig_start, orig_end; + struct memblock_type *mem = &memblock.memory; + + for (i = 0; i < mem->cnt; i++) { + orig_start = mem->regions[i].base; + orig_end = mem->regions[i].base + mem->regions[i].size; + start = round_up(orig_start, align); + end = round_down(orig_end, align); + + if (start == orig_start && end == orig_end) + continue; + + if (start < end) { + mem->regions[i].base = start; + mem->regions[i].size = end - start; + } else { + memblock_remove_region(mem, i); + i--; + } + } +} void __init_memblock memblock_set_current_limit(phys_addr_t limit) { From b2cbf7d3826c2dc36ce2c0332befb2dd281960ea Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 25 Oct 2012 13:37:31 -0700 Subject: [PATCH 0356/1071] mm: fix XFS oops due to dirty pages without buffers on s390 commit ef5d437f71afdf4afdbab99213add99f4b1318fd upstream. On s390 any write to a page (even from kernel itself) sets architecture specific page dirty bit. Thus when a page is written to via buffered write, HW dirty bit gets set and when we later map and unmap the page, page_remove_rmap() finds the dirty bit and calls set_page_dirty(). Dirtying of a page which shouldn't be dirty can cause all sorts of problems to filesystems. The bug we observed in practice is that buffers from the page get freed, so when the page gets later marked as dirty and writeback writes it, XFS crashes due to an assertion BUG_ON(!PagePrivate(page)) in page_buffers() called from xfs_count_page_state(). Similar problem can also happen when zero_user_segment() call from xfs_vm_writepage() (or block_write_full_page() for that matter) set the hardware dirty bit during writeback, later buffers get freed, and then page unmapped. Fix the issue by ignoring s390 HW dirty bit for page cache pages of mappings with mapping_cap_account_dirty(). This is safe because for such mappings when a page gets marked as writeable in PTE it is also marked dirty in do_wp_page() or do_page_fault(). When the dirty bit is cleared by clear_page_dirty_for_io(), the page gets writeprotected in page_mkclean(). So pagecache page is writeable if and only if it is dirty. Thanks to Hugh Dickins for pointing out mapping has to have mapping_cap_account_dirty() for things to work and proposing a cleaned up variant of the patch. The patch has survived about two hours of running fsx-linux on tmpfs while heavily swapping and several days of running on out build machines where the original problem was triggered. Signed-off-by: Jan Kara Cc: Martin Schwidefsky Cc: Mel Gorman Cc: Hugh Dickins Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/rmap.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index 0f3b7cda2a24c5..aa95e597aaf1e7 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -56,6 +56,7 @@ #include #include #include +#include #include @@ -971,11 +972,8 @@ int page_mkclean(struct page *page) if (page_mapped(page)) { struct address_space *mapping = page_mapping(page); - if (mapping) { + if (mapping) ret = page_mkclean_file(mapping, page); - if (page_test_and_clear_dirty(page_to_pfn(page), 1)) - ret = 1; - } } return ret; @@ -1161,6 +1159,7 @@ void page_add_file_rmap(struct page *page) */ void page_remove_rmap(struct page *page) { + struct address_space *mapping = page_mapping(page); bool anon = PageAnon(page); bool locked; unsigned long flags; @@ -1183,8 +1182,19 @@ void page_remove_rmap(struct page *page) * this if the page is anon, so about to be freed; but perhaps * not if it's in swapcache - there might be another pte slot * containing the swap entry, but page not yet written to swap. + * + * And we can skip it on file pages, so long as the filesystem + * participates in dirty tracking; but need to catch shm and tmpfs + * and ramfs pages which have been modified since creation by read + * fault. + * + * Note that mapping must be decided above, before decrementing + * mapcount (which luckily provides a barrier): once page is unmapped, + * it could be truncated and page->mapping reset to NULL at any moment. + * Note also that we are relying on page_mapping(page) to set mapping + * to &swapper_space when PageSwapCache(page). */ - if ((!anon || PageSwapCache(page)) && + if (mapping && !mapping_cap_account_dirty(mapping) && page_test_and_clear_dirty(page_to_pfn(page), 1)) set_page_dirty(page); /* From 27d32c280df4953e2a28f8c8ff2d9491effa3a4c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 22 Oct 2012 17:14:36 -0400 Subject: [PATCH 0357/1071] SUNRPC: Get rid of the xs_error_report socket callback commit f878b657ce8e7d3673afe48110ec208a29e38c4a upstream. Chris Perl reports that we're seeing races between the wakeup call in xs_error_report and the connect attempts. Basically, Chris has shown that in certain circumstances, the call to xs_error_report causes the rpc_task that is responsible for reconnecting to wake up early, thus triggering a disconnect and retry. Since the sk->sk_error_report() calls in the socket layer are always followed by a tcp_done() in the cases where we care about waking up the rpc_tasks, just let the state_change callbacks take responsibility for those wake ups. Reported-by: Chris Perl Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 97f8918169edb4..7847344d0fa9ce 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -254,7 +254,6 @@ struct sock_xprt { void (*old_data_ready)(struct sock *, int); void (*old_state_change)(struct sock *); void (*old_write_space)(struct sock *); - void (*old_error_report)(struct sock *); }; /* @@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) transport->old_data_ready = sk->sk_data_ready; transport->old_state_change = sk->sk_state_change; transport->old_write_space = sk->sk_write_space; - transport->old_error_report = sk->sk_error_report; } static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) @@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s sk->sk_data_ready = transport->old_data_ready; sk->sk_state_change = transport->old_state_change; sk->sk_write_space = transport->old_write_space; - sk->sk_error_report = transport->old_error_report; } static void xs_reset_transport(struct sock_xprt *transport) @@ -1549,25 +1546,6 @@ static void xs_tcp_state_change(struct sock *sk) read_unlock_bh(&sk->sk_callback_lock); } -/** - * xs_error_report - callback mainly for catching socket errors - * @sk: socket - */ -static void xs_error_report(struct sock *sk) -{ - struct rpc_xprt *xprt; - - read_lock_bh(&sk->sk_callback_lock); - if (!(xprt = xprt_from_sock(sk))) - goto out; - dprintk("RPC: %s client %p...\n" - "RPC: error %d\n", - __func__, xprt, sk->sk_err); - xprt_wake_pending_tasks(xprt, -EAGAIN); -out: - read_unlock_bh(&sk->sk_callback_lock); -} - static void xs_write_space(struct sock *sk) { struct socket *sock; @@ -1867,7 +1845,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, sk->sk_user_data = xprt; sk->sk_data_ready = xs_local_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; xprt_clear_connected(xprt); @@ -1995,7 +1972,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_user_data = xprt; sk->sk_data_ready = xs_udp_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_no_check = UDP_CSUM_NORCV; sk->sk_allocation = GFP_ATOMIC; @@ -2113,7 +2089,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_data_ready = xs_tcp_data_ready; sk->sk_state_change = xs_tcp_state_change; sk->sk_write_space = xs_tcp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; /* socket options */ From a340197a85e4a27b3f974ffb6ab0308cc3f2edbc Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Oct 2012 11:35:47 -0400 Subject: [PATCH 0358/1071] SUNRPC: Clear the connect flag when socket state is TCP_CLOSE_WAIT commit d0bea455dd48da1ecbd04fedf00eb89437455fdc upstream. This is needed to ensure that we call xprt_connect() upon the next call to call_connect(). Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7847344d0fa9ce..f08e42481759bd 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1522,6 +1522,7 @@ static void xs_tcp_state_change(struct sock *sk) case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ xprt->connect_cookie++; + clear_bit(XPRT_CONNECTED, &xprt->state); xs_tcp_force_close(xprt); case TCP_CLOSING: /* From 2edc5969320d6e7f13d6d74e9bd3d8c0b8ec3684 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Oct 2012 11:40:02 -0400 Subject: [PATCH 0359/1071] Revert "SUNRPC: Ensure we close the socket on EPIPE errors too..." commit b9d2bb2ee537424a7f855e1f93eed44eb9ee0854 upstream. This reverts commit 55420c24a0d4d1fce70ca713f84aa00b6b74a70e. Now that we clear the connected flag when entering TCP_CLOSE_WAIT, the deadlock described in this commit is no longer possible. Instead, the resulting call to xs_tcp_shutdown() can interfere with pending reconnection attempts. Reported-by: Chris Perl Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index f08e42481759bd..094afc07031306 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -736,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task) dprintk("RPC: sendmsg returned unrecognized error %d\n", -status); case -ECONNRESET: - case -EPIPE: xs_tcp_shutdown(xprt); case -ECONNREFUSED: case -ENOTCONN: + case -EPIPE: clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); } From cafefcb3f8be77ef156b4b3bd52a5374b3533679 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Oct 2012 13:51:58 -0400 Subject: [PATCH 0360/1071] LOCKD: fix races in nsm_client_get commit a4ee8d978e47e79d536226dccb48991f70091168 upstream. Commit e9406db20fecbfcab646bad157b4cfdc7cadddfb (lockd: per-net NSM client creation and destruction helpers introduced) contains a nasty race on initialisation of the per-net NSM client because it doesn't check whether or not the client is set after grabbing the nsm_create_mutex. Reported-by: Nix Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/lockd/mon.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index e4fb3ba5a58a3d..fe695603e3956b 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net) return rpc_create(&args); } +static struct rpc_clnt *nsm_client_set(struct lockd_net *ln, + struct rpc_clnt *clnt) +{ + spin_lock(&ln->nsm_clnt_lock); + if (ln->nsm_users == 0) { + if (clnt == NULL) + goto out; + ln->nsm_clnt = clnt; + } + clnt = ln->nsm_clnt; + ln->nsm_users++; +out: + spin_unlock(&ln->nsm_clnt_lock); + return clnt; +} + static struct rpc_clnt *nsm_client_get(struct net *net) { - static DEFINE_MUTEX(nsm_create_mutex); - struct rpc_clnt *clnt; + struct rpc_clnt *clnt, *new; struct lockd_net *ln = net_generic(net, lockd_net_id); - spin_lock(&ln->nsm_clnt_lock); - if (ln->nsm_users) { - ln->nsm_users++; - clnt = ln->nsm_clnt; - spin_unlock(&ln->nsm_clnt_lock); + clnt = nsm_client_set(ln, NULL); + if (clnt != NULL) goto out; - } - spin_unlock(&ln->nsm_clnt_lock); - mutex_lock(&nsm_create_mutex); - clnt = nsm_create(net); - if (!IS_ERR(clnt)) { - ln->nsm_clnt = clnt; - smp_wmb(); - ln->nsm_users = 1; - } - mutex_unlock(&nsm_create_mutex); + clnt = new = nsm_create(net); + if (IS_ERR(clnt)) + goto out; + + clnt = nsm_client_set(ln, new); + if (clnt != new) + rpc_shutdown_client(new); out: return clnt; } From eeaeb30f888f0872c029b441a69d67f43e712c80 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Oct 2012 17:50:07 -0400 Subject: [PATCH 0361/1071] SUNRPC: Prevent races in xs_abort_connection() commit 4bc1e68ed6a8b59be8a79eb719be515a55c7bc68 upstream. The call to xprt_disconnect_done() that is triggered by a successful connection reset will trigger another automatic wakeup of all tasks on the xprt->pending rpc_wait_queue. In particular it will cause an early wake up of the task that called xprt_connect(). All we really want to do here is clear all the socket-specific state flags, so we split that functionality out of xs_sock_mark_closed() into a helper that can be called by xs_abort_connection() Reported-by: Chris Perl Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 094afc07031306..6a70db45c5b14f 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1459,7 +1459,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) xprt_clear_connecting(xprt); } -static void xs_sock_mark_closed(struct rpc_xprt *xprt) +static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) { smp_mb__before_clear_bit(); clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); @@ -1467,6 +1467,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt) clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); +} + +static void xs_sock_mark_closed(struct rpc_xprt *xprt) +{ + xs_sock_reset_connection_flags(xprt); /* Mark transport as closed and wake up all pending tasks */ xprt_disconnect_done(xprt); } @@ -2042,10 +2047,8 @@ static void xs_abort_connection(struct sock_xprt *transport) any.sa_family = AF_UNSPEC; result = kernel_connect(transport->sock, &any, sizeof(any), 0); if (!result) - xs_sock_mark_closed(&transport->xprt); - else - dprintk("RPC: AF_UNSPEC connect return code %d\n", - result); + xs_sock_reset_connection_flags(&transport->xprt); + dprintk("RPC: AF_UNSPEC connect return code %d\n", result); } static void xs_tcp_reuse_connection(struct sock_xprt *transport) From cb499284d1cf7de50b85fcfb3248bae2db090d14 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 24 Oct 2012 08:53:35 -0400 Subject: [PATCH 0362/1071] LOCKD: Clear ln->nsm_clnt only when ln->nsm_users is zero commit e498daa81295d02f7359af313c2b7f87e1062207 upstream. The current code is clearing it in all cases _except_ when zero. Reported-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/lockd/mon.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index fe695603e3956b..3d7e09bcc0e9ef 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -124,18 +124,16 @@ static struct rpc_clnt *nsm_client_get(struct net *net) static void nsm_client_put(struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct rpc_clnt *clnt = ln->nsm_clnt; - int shutdown = 0; + struct rpc_clnt *clnt = NULL; spin_lock(&ln->nsm_clnt_lock); - if (ln->nsm_users) { - if (--ln->nsm_users) - ln->nsm_clnt = NULL; - shutdown = !ln->nsm_users; + ln->nsm_users--; + if (ln->nsm_users == 0) { + clnt = ln->nsm_clnt; + ln->nsm_clnt = NULL; } spin_unlock(&ln->nsm_clnt_lock); - - if (shutdown) + if (clnt != NULL) rpc_shutdown_client(clnt); } From 288a8f85227007e326758197a3ad7cd56d66e3e3 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Oct 2012 13:17:43 -0700 Subject: [PATCH 0363/1071] xhci: Fix potential NULL ptr deref in command cancellation. commit 43a09f7fb01fa1e091416a2aa49b6c666458c1ee upstream. The command cancellation code doesn't check whether find_trb_seg() couldn't find the segment that contains the TRB to be canceled. This could cause a NULL pointer deference later in the function when next_trb is called. It's unlikely to happen unless something is wrong with the command ring pointers, so add some debugging in case it happens. This patch should be backported to stable kernels as old as 3.0, that contain the commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d "xHCI: handle command after aborting the command ring". Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a6e18b96f15f59..4f1e265223dd4d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, xhci->cmd_ring->dequeue, &cycle_state); + if (!cur_seg) { + xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", + xhci->cmd_ring->dequeue, + (unsigned long long) + xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, + xhci->cmd_ring->dequeue)); + xhci_debug_ring(xhci, xhci->cmd_ring); + xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); + return; + } + /* find the command trb matched by cd from command ring */ for (cmd_trb = xhci->cmd_ring->dequeue; cmd_trb != xhci->cmd_ring->enqueue; From 15e01c0ef27c323ac1a97ba50b3021eab33a96c9 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 17 Oct 2012 10:16:16 +0200 Subject: [PATCH 0364/1071] xhci: fix integer overflow commit 16b45fdf9c4e82f5d3bc53aa70737650e7c8d5ed upstream. xhci_service_interval_to_ns() returns long long to avoid an overflow. However, the type cast happens too late. The fix is to force ULL from the beginning. This patch should be backported to kernels as old as 3.5, that contain the commit e3567d2c15a7a8e2f992a5f7c7683453ca406d82 "xhci: Add Intel U1/U2 timeout policy." Signed-off-by: Oliver Neukum Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 0644f65b8d8c11..483617763d76d0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4020,7 +4020,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) static unsigned long long xhci_service_interval_to_ns( struct usb_endpoint_descriptor *desc) { - return (1 << (desc->bInterval - 1)) * 125 * 1000; + return (1ULL << (desc->bInterval - 1)) * 125 * 1000; } static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, From 11c5035c9cfb7af7cfedd42e236d52f9c6bd1c49 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 17 Oct 2012 12:17:50 +0200 Subject: [PATCH 0365/1071] xhci: endianness xhci_calculate_intel_u2_timeout commit 966e7a854177097083683176ced871558b631a12 upstream. An le16 is accessed without conversion. This patch should be backported to kernels as old as 3.5, that contain the commit e3567d2c15a7a8e2f992a5f7c7683453ca406d82 "xhci: Add Intel U1/U2 timeout policy." Signed-off-by: Oliver Neukum Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 483617763d76d0..a6e910b2bc04b8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4141,7 +4141,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev, (xhci_service_interval_to_ns(desc) > timeout_ns)) timeout_ns = xhci_service_interval_to_ns(desc); - u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000; + u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL; if (u2_del_ns > timeout_ns) timeout_ns = u2_del_ns; From 7886abd88bc7c4c145a2260844795604d569596b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 29 Sep 2012 22:23:19 +0200 Subject: [PATCH 0366/1071] sysfs: sysfs_pathname/sysfs_add_one: Use strlcat() instead of strcat() commit 66081a72517a131430dcf986775f3268aafcb546 upstream. The warning check for duplicate sysfs entries can cause a buffer overflow when printing the warning, as strcat() doesn't check buffer sizes. Use strlcat() instead. Since strlcat() doesn't return a pointer to the passed buffer, unlike strcat(), I had to convert the nested concatenation in sysfs_add_one() to an admittedly more obscure comma operator construct, to avoid emitting code for the concatenation if CONFIG_BUG is disabled. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6b0bb00d4d2b60..2fbdff6be25ce3 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) /** * sysfs_pathname - return full path to sysfs dirent * @sd: sysfs_dirent whose path we want - * @path: caller allocated buffer + * @path: caller allocated buffer of size PATH_MAX * * Gives the name "/" to the sysfs_root entry; any path returned * is relative to wherever sysfs is mounted. - * - * XXX: does no error checking on @path size */ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) { if (sd->s_parent) { sysfs_pathname(sd->s_parent, path); - strcat(path, "/"); + strlcat(path, "/", PATH_MAX); } - strcat(path, sd->s_name); + strlcat(path, sd->s_name, PATH_MAX); return path; } @@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) char *path = kzalloc(PATH_MAX, GFP_KERNEL); WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n", - (path == NULL) ? sd->s_name : - strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), - sd->s_name)); + (path == NULL) ? sd->s_name + : (sysfs_pathname(acxt->parent_sd, path), + strlcat(path, "/", PATH_MAX), + strlcat(path, sd->s_name, PATH_MAX), + path)); kfree(path); } From ab261cc53424005d6d079320c4f73344c0a1750d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 16 Oct 2012 15:29:54 -0700 Subject: [PATCH 0367/1071] Staging: android: binder: Fix memory leak on thread/process exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 675d66b0ed5fd170d6a44cf8dbb3fa56a5347bdb upstream. If a thread or process exited while a reply, one-way transaction or death notification was pending, the struct holding the pending work was leaked. Signed-off-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 574e99210c36cd..b2962831ec9e36 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2507,14 +2507,38 @@ static void binder_release_work(struct list_head *list) struct binder_transaction *t; t = container_of(w, struct binder_transaction, work); - if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) + if (t->buffer->target_node && + !(t->flags & TF_ONE_WAY)) { binder_send_failed_reply(t, BR_DEAD_REPLY); + } else { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered transaction %d\n", + t->debug_id); + t->buffer->transaction = NULL; + kfree(t); + binder_stats_deleted(BINDER_STAT_TRANSACTION); + } } break; case BINDER_WORK_TRANSACTION_COMPLETE: { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered TRANSACTION_COMPLETE\n"); kfree(w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; + case BINDER_WORK_DEAD_BINDER_AND_CLEAR: + case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { + struct binder_ref_death *death; + + death = container_of(w, struct binder_ref_death, work); + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered death notification, %p\n", + death->cookie); + kfree(death); + binder_stats_deleted(BINDER_STAT_DEATH); + } break; default: + pr_err("binder: unexpected work type, %d, not freed\n", + w->type); break; } } @@ -2984,6 +3008,7 @@ static void binder_deferred_release(struct binder_proc *proc) nodes++; rb_erase(&node->rb_node, &proc->nodes); list_del_init(&node->work.entry); + binder_release_work(&node->async_todo); if (hlist_empty(&node->refs)) { kfree(node); binder_stats_deleted(BINDER_STAT_NODE); @@ -3022,6 +3047,7 @@ static void binder_deferred_release(struct binder_proc *proc) binder_delete_ref(ref); } binder_release_work(&proc->todo); + binder_release_work(&proc->delivered_death); buffers = 0; while ((n = rb_first(&proc->allocated_buffers))) { From e4c52c43352370daf54ba0cbe9476f593d89b0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 16 Oct 2012 15:29:55 -0700 Subject: [PATCH 0368/1071] Staging: android: binder: Allow using highmem for binder buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 585650dcec88e704a19bb226a34b6a7166111623 upstream. The default kernel mapping for the pages allocated for the binder buffers is never used. Set the __GFP_HIGHMEM flag when allocating these pages so we don't needlessly use low memory pages that may be required elsewhere. Signed-off-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index b2962831ec9e36..467d493be92dff 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -655,7 +655,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; BUG_ON(*page); - *page = alloc_page(GFP_KERNEL | __GFP_ZERO); + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { pr_err("binder: %d: binder_alloc_buf failed " "for page at %p\n", proc->pid, page_addr); From 88d5e653e2282bda43459dd577f3841f6ef140bf Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Wed, 10 Oct 2012 17:42:18 -0700 Subject: [PATCH 0369/1071] staging: zram: Fix handling of incompressible pages commit c8f2f0db1d0294aaf37e8a85bea9bbc4aaf5c0fe upstream. Change 130f315a (staging: zram: remove special handle of uncompressed page) introduced a bug in the handling of incompressible pages which resulted in memory allocation failure for such pages. When a page expands on compression, say from 4K to 4K+30, we were trying to do zsmalloc(pool, 4K+30). However, the maximum size which zsmalloc can allocate is PAGE_SIZE (for obvious reasons), so such allocation requests always return failure (0). For a page that has compressed size larger than the original size (this may happen with already compressed or random data), there is no point storing the compressed version as that would take more space and would also require time for decompression when needed again. So, the fix is to store any page, whose compressed size exceeds a threshold (max_zpage_size), as-it-is i.e. without compression. Memory required for storing this uncompressed page can then be requested from zsmalloc which supports PAGE_SIZE sized allocations. Lastly, the fix checks that we do not attempt to "decompress" the page which we stored in the uncompressed form -- we just memcpy() out such pages. Signed-off-by: Nitin Gupta Reported-by: viechweg@gmail.com Reported-by: paerley@gmail.com Reported-by: wu.tommy@gmail.com Acked-by: Minchan Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 653b074035f7b1..6edefde23722b4 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, cmem = zs_map_object(zram->mem_pool, zram->table[index].handle, ZS_MM_RO); - ret = lzo1x_decompress_safe(cmem, zram->table[index].size, + if (zram->table[index].size == PAGE_SIZE) { + memcpy(uncmem, cmem, PAGE_SIZE); + ret = LZO_E_OK; + } else { + ret = lzo1x_decompress_safe(cmem, zram->table[index].size, uncmem, &clen); + } if (is_partial_io(bvec)) { memcpy(user_mem + bvec->bv_offset, uncmem + offset, @@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } - if (unlikely(clen > max_zpage_size)) + if (unlikely(clen > max_zpage_size)) { zram_stat_inc(&zram->stats.bad_compress); + src = uncmem; + clen = PAGE_SIZE; + } handle = zs_malloc(zram->mem_pool, clen); if (!handle) { From d136f0fd47d9953139381c8af74976de86eeb224 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:20 +0100 Subject: [PATCH 0370/1071] staging: comedi: das08: fix possible NULL deref during detach commit ee280d134f2e05e0172369a53fbe202dbfc527fa upstream. `das08_detach()` is called by the comedi core to clean up if either `das08_attach()` or `das08_attach_pci()` returns an error. It sets `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. This is a valid assumption if `das08_attach()` fails, but not if `das08_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `das08_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 67a914a10b55fb..d893e3b204864a 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1028,6 +1028,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev) const struct das08_board_struct *thisboard = comedi_board(dev); struct das08_private_struct *devpriv = dev->private; + if (!thisboard) + return; das08_common_detach(dev); if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) && (thisboard->bustype == isa || thisboard->bustype == pc104)) { From 8098a2e23e88e979566c78e68aec11fa21808df0 Mon Sep 17 00:00:00 2001 From: Fred Brooks Date: Tue, 2 Oct 2012 11:10:26 +0100 Subject: [PATCH 0371/1071] staging: comedi: ni_daq_700: fix dio subdevice regression commit 6681e63399926651cc29bcb9d92229b6f1cf1daa upstream. Here is a small patch to fix a problem caused by a previous patch that removed the callback function. The callback remove patch: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=1de02225358988e8fd48d1dc3fd12336bbae258a I finally booted my dev machine on the latest kernel (running Debian here so it's still on 3.2 normally) to test the ni_daq_700 driver with my test program and noticed this bug. Shift the DIO_R read result to bits 8..15 Digital direction configuration: channels 0-7 output, 8-15 input (8225 device emu as port A output, port B input, port C N/A). Signed-off-by: Fred Brooks Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_daq_700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 83016b411851f0..bcf6a656c0a44d 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -71,7 +71,7 @@ static int subdev_700_insn(struct comedi_device *dev, } data[1] = s->state & 0xff; - data[1] |= inb(dev->iobase + DIO_R); + data[1] |= inb(dev->iobase + DIO_R) << 8; return insn->n; } From 9f275003e609824e738b22caef0020d5c4a4def5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:21 +0100 Subject: [PATCH 0372/1071] staging: comedi: ni_labpc: fix possible NULL deref during detach commit 922b67c1ac53014d80649a961a2fde700cd065d8 upstream. `labpc_common_detach()` is called by the comedi core to clean up if either `labpc_attach()` (including the one in the "ni_labpc_cs" module) or `labpc_attach_pci()` returns an error. It assumes the `thisboard` macro (expanding to `((struct labpc_board_struct *)dev->board_ptr)`) is non-null. This is a valid assumption if `labpc_attach()` fails, but not if `labpc_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `labpc_common_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index ab8b787c78bbe0..d3a1d65fd636c1 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -809,6 +809,8 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot) void labpc_common_detach(struct comedi_device *dev) { + if (!thisboard) + return; if (dev->subdevices) subdev_8255_cleanup(dev, dev->subdevices + 2); #ifdef CONFIG_ISA_DMA_API From 6f9445326d4a262a863cc634fd377c5ca562e17d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:16 +0100 Subject: [PATCH 0373/1071] staging: comedi: amplc_dio200: fix possible NULL deref during detach commit dfb2540e91e1f63765bc3ff497ad0b714d774261 upstream. `dio200_detach()` is called by the comedi core to clean up if either `dio200_attach()` or `dio200_attach_pci()` return an error. It assigns `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. In the case of a previous call to `dio200_attach()` it won't be `NULL` because the comedi core will have pointed it to one of the elements of `dio200_boards[]`, but in the case of a previous call to `dio200_attach_pci()` it could be `NULL`, leading to a null pointer dereference. Check that `thisboard` is valid at the top of `dio200_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index cc8931fde839c4..aee22fdd4e40a0 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1429,6 +1429,8 @@ static void dio200_detach(struct comedi_device *dev) const struct dio200_layout_struct *layout; unsigned n; + if (!thisboard) + return; if (dev->irq) free_irq(dev->irq, dev); if (dev->subdevices) { From 3792dd12ee4419bc276cd321c8f74506a37aa93d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:19 +0100 Subject: [PATCH 0374/1071] staging: comedi: amplc_pc263: fix possible NULL deref during detach commit 1d1171ffda585c1cab7bd7cf4bd8f8fd5923fb4a upstream. `pc263_detach()` is called by the comedi core to clean up if either `pc263_attach()` or `pc263_attach_pci()` returns an error. It sets `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. This is a valid assumption if `pc263_attach()` fails, but not if `pc263_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `pc263_detach()` and return early if it is `NULL`. This is okay because no other resources need cleaning up in this case. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 8191c4e28e0a68..8c0fbd1ceea57d 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -310,8 +310,11 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev, static void pc263_detach(struct comedi_device *dev) { + const struct pc263_board *thisboard = comedi_board(dev); struct pci_dev *pcidev = comedi_to_pci_dev(dev); + if (!thisboard) + return; if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); From ec7fe3d6e91ff29ee3000e35f13f5eb3df2eca30 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:17 +0100 Subject: [PATCH 0375/1071] staging: comedi: amplc_pc236: fix invalid register access during detach commit aaeb61a97b7159ebe30b18a422d04eeabfa8790b upstream. `pc236_detach()` is called by the comedi core if it attempted to attach a device and failed. `pc236_detach()` calls `pc236_intr_disable()` if the comedi device private data pointer (`devpriv`) is non-null. This test is insufficient as `pc236_intr_disable()` accesses hardware registers and the attach routine may have failed before it has saved their I/O base addresses. Fix it by checking `dev->iobase` is non-zero before calling `pc236_intr_disable()` as that means the I/O base addresses have been saved and the hardware registers can be accessed. It also implies the comedi device private data pointer is valid, so there is no need to check it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index f50287903038bb..cfbb83b9526a10 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -577,10 +577,9 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, static void pc236_detach(struct comedi_device *dev) { - struct pc236_private *devpriv = dev->private; struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (devpriv) + if (dev->iobase) pc236_intr_disable(dev); if (dev->irq) free_irq(dev->irq, dev); From 6c04efd97dd25596a1bf80cc1c518fe7e451cc1e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:18 +0100 Subject: [PATCH 0376/1071] staging: comedi: amplc_pc236: fix possible NULL deref during detach commit 2db012bd40b889d8e5483d3daa07af04c4c109d8 upstream. `pc236_detach()` is called by the comedi core to clean up if either `pc236_attach()` or `pc236_attach_pci()` returns an error. It sets `thisboard` to the return value of `comedi_board(dev)` and assumes it is non-null. This is a valid assumption if `pc236_attach()` fails, but not if `pc236_attach_pci()` fails, leading to a possible NULL pointer dereference. Check `thisboard` at the top of `pc236_detach()` and return early if it is `NULL`. This is okay because the only other thing that could have been allocated is `dev->private` and that is freed by the comedi core, not by this function. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index cfbb83b9526a10..b46e66310d71e0 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -577,8 +577,11 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, static void pc236_detach(struct comedi_device *dev) { + const struct pc236_board *thisboard = comedi_board(dev); struct pci_dev *pcidev = comedi_to_pci_dev(dev); + if (!thisboard) + return; if (dev->iobase) pc236_intr_disable(dev); if (dev->irq) From c5a2edcb66a0f15a5313b52dd68821ec387d8091 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 24 Sep 2012 15:32:31 +0900 Subject: [PATCH 0377/1071] extcon: Unregister compat class at module unload to fix oops commit 0dc77b6dabec8fd298392018cc0de5214af2dc43 upstream. If you compile extcon with CONFIG_ANDROID and then load and unload the module you get a simple oops as the driver does not unregister its compat class and thus cannot register it again. Full trace: root@(none):~# modprobe extcon_class root@(none):~# rmmod extcon_class root@(none):~# modprobe extcon_class ------------[ cut here ]------------ WARNING: at fs/sysfs/dir.c:536 sysfs_add_one+0xde/0x100() sysfs: cannot create duplicate filename '/class/switch' Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451a00: [<602a58bc>] printk+0x0/0xa8 9f451a18: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451a28: [<6012c6de>] sysfs_add_one+0xde/0x100 9f451a50: [<601d3d90>] strcat+0x0/0x40 9f451a68: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451a90: [<6002fe32>] unblock_signals+0x0/0x84 9f451ab0: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451ac0: [<6002fe32>] unblock_signals+0x0/0x84 9f451ae8: [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70 9f451b00: [<601d3d90>] strcat+0x0/0x40 9f451b18: [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70 9f451b48: [<6012c6de>] sysfs_add_one+0xde/0x100 9f451b78: [<6012c96f>] create_dir+0x8f/0x100 9f451bc0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451bd8: [<6012cda6>] sysfs_create_dir+0xa6/0x1c0 9f451be8: [<601d89f1>] kvasprintf+0x81/0xa0 9f451bf8: [<601cf0f0>] kobject_get+0x0/0x50 9f451c18: [<601cf396>] kobject_add_internal+0x96/0x280 9f451c60: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451c78: [<601cfb93>] kobject_add+0xd3/0x140 9f451cc0: [<601cfac0>] kobject_add+0x0/0x140 9f451cd0: [<6002fe32>] unblock_signals+0x0/0x84 9f451cf8: [<6002fffc>] set_signals+0x29/0x3f 9f451d28: [<600c1de1>] kmem_cache_alloc+0xe1/0x100 9f451d78: [<601cffa0>] kobject_create_and_add+0x50/0xa0 9f451da8: [<601fbe76>] class_compat_register+0x56/0x80 9f451dc8: [] create_extcon_class+0x88/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c367 ]--- ------------[ cut here ]------------ WARNING: at lib/kobject.c:196 kobject_add_internal+0x26e/0x280() kobject_add_internal failed for switch with -EEXIST, don't try to register things with the same name in the same directory. Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451ad0: [<602a58bc>] printk+0x0/0xa8 9f451ae8: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451af8: [<601cf56e>] kobject_add_internal+0x26e/0x280 9f451b18: [<601cf140>] kobject_put+0x0/0x70 9f451b20: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451b38: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451b88: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451bc0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451bd8: [<6012cda6>] sysfs_create_dir+0xa6/0x1c0 9f451be8: [<601d89f1>] kvasprintf+0x81/0xa0 9f451bf8: [<601cf0f0>] kobject_get+0x0/0x50 9f451c18: [<601cf56e>] kobject_add_internal+0x26e/0x280 9f451c60: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451c78: [<601cfb93>] kobject_add+0xd3/0x140 9f451cc0: [<601cfac0>] kobject_add+0x0/0x140 9f451cd0: [<6002fe32>] unblock_signals+0x0/0x84 9f451cf8: [<6002fffc>] set_signals+0x29/0x3f 9f451d28: [<600c1de1>] kmem_cache_alloc+0xe1/0x100 9f451d78: [<601cffa0>] kobject_create_and_add+0x50/0xa0 9f451da8: [<601fbe76>] class_compat_register+0x56/0x80 9f451dc8: [] create_extcon_class+0x88/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c368 ]--- kobject_create_and_add: kobject_add error: -17 ------------[ cut here ]------------ WARNING: at drivers/extcon/extcon_class.c:545 create_extcon_class+0xbc/0xd0 [extcon_class]() cannot allocate Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451c80: [<602a58bc>] printk+0x0/0xa8 9f451c98: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451ca0: [<6002fe32>] unblock_signals+0x0/0x84 9f451ca8: [] create_extcon_class+0xbc/0xd0 [extcon_class] 9f451cd0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451ce8: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451d20: [<6002fe32>] unblock_signals+0x0/0x84 9f451d28: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451d48: [<6002fffc>] set_signals+0x29/0x3f 9f451d58: [<601cf172>] kobject_put+0x32/0x70 9f451d78: [<600c22c3>] kfree+0xb3/0x100 9f451da8: [<601fbe9a>] class_compat_register+0x7a/0x80 9f451dc8: [] create_extcon_class+0xbc/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c369 ]--- FATAL: Error inserting extcon_class (/lib/modules/3.6.0-rc6-00178-g811315f/kernel/drivers/extcon/extcon_class.ko): Cannot allocate memory This patch fixes this. Signed-off-by: Peter Huewe Signed-off-by: Chanwoo Choi Signed-off-by: Greg Kroah-Hartman --- drivers/extcon/extcon_class.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c index f6419f9db76c10..6e914d030a4676 100644 --- a/drivers/extcon/extcon_class.c +++ b/drivers/extcon/extcon_class.c @@ -821,6 +821,9 @@ module_init(extcon_class_init); static void __exit extcon_class_exit(void) { +#if defined(CONFIG_ANDROID) + class_compat_unregister(switch_class); +#endif class_destroy(extcon_class); } module_exit(extcon_class_exit); From 3ed2bcc63a56f5b8983ecfc4de37fa70d7e2e380 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 24 Sep 2012 15:36:24 +0900 Subject: [PATCH 0378/1071] extcon: unregister compat link on cleanup commit 824a1bc045cef278aec15bef35d8d0b59ce77856 upstream. Since extcon registers this compat link at device registration (extcon_dev_register), we should probably remove them at deregistration/cleanup. Signed-off-by: Peter Huewe Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon_class.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c index 6e914d030a4676..7dcfb7c62eec14 100644 --- a/drivers/extcon/extcon_class.c +++ b/drivers/extcon/extcon_class.c @@ -575,6 +575,10 @@ static void extcon_cleanup(struct extcon_dev *edev, bool skip) kfree(edev->cables); } +#if defined(CONFIG_ANDROID) + if (switch_class) + class_compat_remove_link(switch_class, edev->dev, NULL); +#endif device_unregister(edev->dev); put_device(edev->dev); } From 2084022fc8385c62e45b1913923384c9ec890192 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 12 Oct 2012 13:22:42 -0700 Subject: [PATCH 0379/1071] Drivers: hv: Cleanup error handling in vmbus_open() commit 1392550240aaa72ce3a094a38bd23525cd67ce60 upstream. Fix a memory leak in the error handling path in the function vmbus_open(). Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Reported-by: Jason Wang Acked-by: Jason Wang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 406537420fffdc..f4c3d28cd1fcc9 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } ret = hv_ringbuffer_init( &newchannel->inbound, in, recv_ringbuffer_size); if (ret != 0) { err = ret; - goto errorout; + goto error0; } @@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } /* Create and init the channel open message */ @@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, GFP_KERNEL); if (!open_info) { err = -ENOMEM; - goto errorout; + goto error0; } init_completion(&open_info->waitevent); @@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (userdatalen > MAX_USER_DEFINED_BYTES) { err = -EINVAL; - goto errorout; + goto error0; } if (userdatalen) @@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, sizeof(struct vmbus_channel_open_channel)); if (ret != 0) - goto cleanup; + goto error1; t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); if (t == 0) { err = -ETIMEDOUT; - goto errorout; + goto error1; } if (open_info->response.open_result.status) err = open_info->response.open_result.status; -cleanup: spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&open_info->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -228,9 +227,12 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, kfree(open_info); return err; -errorout: - hv_ringbuffer_cleanup(&newchannel->outbound); - hv_ringbuffer_cleanup(&newchannel->inbound); +error1: + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + +error0: free_pages((unsigned long)out, get_order(send_ringbuffer_size + recv_ringbuffer_size)); kfree(open_info); From 1b1a523d438e5bae152aebaff6fb404cbbb3f97c Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Tue, 9 Oct 2012 12:22:36 +0200 Subject: [PATCH 0380/1071] ehci: fix Lucid nohandoff pci quirk to be more generic with BIOS versions commit c323dc023b9501e5d09582ec7efd1d40a9001d99 upstream. BIOS vendors keep changing the BIOS versions. Only match the beginning of the string to match all Lucid tablets with board name M11JB. Signed-off-by: Anisse Astier Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 966d1484ee79a2..ead45259bf15ab 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -545,7 +545,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { /* Pegatron Lucid (Ordissimo AIRIS) */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, { } From 7fe28e296934557d1e1f5c91e29d3b93ab1a3dc5 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Tue, 9 Oct 2012 12:22:37 +0200 Subject: [PATCH 0381/1071] ehci: Add yet-another Lucid nohandoff pci quirk commit 8daf8b6086f9d575200cd0aa3797e26137255609 upstream. Board name changed on another shipping Lucid tablet. Signed-off-by: Anisse Astier Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index ead45259bf15ab..39f9e4a9a2d3f0 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -548,6 +548,13 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, + { + /* Pegatron Lucid (Ordissimo) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), + }, + }, { } }; From 8eb72a2087ba5959de22bf90b0df18cade29bb41 Mon Sep 17 00:00:00 2001 From: Michael Shigorin Date: Mon, 22 Oct 2012 12:18:56 +0300 Subject: [PATCH 0382/1071] usb-storage: add unusual_devs entry for Casio EX-N1 digital camera commit d7870af7e2e3a91b462075ec1ca669b482215187 upstream. This commit sets removable subclass for Casio EX-N1 digital camera. The patch has been tested within an ALT Linux kernel: http://git.altlinux.org/people/led/packages/?p=kernel-image-3.0.git;a=commitdiff;h=c0fd891836e89fe0c93a4d536a59216d90e4e3e7 See also https://bugzilla.kernel.org/show_bug.cgi?id=49221 Signed-off-by: Oleksandr Chumachenko Signed-off-by: Michael Shigorin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 62a31bea06346b..8f98c9a8529141 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, USB_SC_8070, USB_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, + "Casio", + "EX-N1 DigitalCamera", + USB_SC_8070, USB_PR_DEVICE, NULL, 0), + /* Submitted by Hartmut Wahl */ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, "Samsung", From d005b0ac883ef8bbd86aff81d48140ef107e50f5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:16 +0200 Subject: [PATCH 0383/1071] USB: usb-wwan: fix multiple memory leaks in error paths commit b8f0e82044c9ba40e92340c8a6d47d6bd6d819bc upstream. Fix port-data memory leak in usb-serial probe error path by moving port data allocation to port_probe. Since commit a1028f0abf ("usb: usb_wwan: replace release and disconnect with a port_remove hook") port data is deallocated in port_remove. This leaves a possibility for memory leaks if usb-serial probe fails after attach but before the port in question has been successfully registered. Note that this patch also fixes two additional memory leaks in the error path of attach should port initialisation fail for any port as the urbs were never freed and neither was the data of any of the successfully initialised ports. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipw.c | 2 +- drivers/usb/serial/option.c | 2 +- drivers/usb/serial/qcserial.c | 2 +- drivers/usb/serial/usb-wwan.h | 2 +- drivers/usb/serial/usb_wwan.c | 130 ++++++++++++++-------------------- 5 files changed, 57 insertions(+), 81 deletions(-) diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 2cb30c535839db..dfaf7f1a475b2f 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -311,8 +311,8 @@ static struct usb_serial_driver ipw_device = { .open = ipw_open, .close = ipw_close, .probe = ipw_probe, - .attach = usb_wwan_startup, .release = ipw_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .dtr_rts = ipw_dtr_rts, .write = usb_wwan_write, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a0542ca03a3fd0..1f33e34addbab6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1288,8 +1288,8 @@ static struct usb_serial_driver option_1port_device = { .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, - .attach = usb_wwan_startup, .release = option_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index bfd50779f0c9f9..f039733df186b7 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -287,8 +287,8 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, - .attach = usb_wwan_startup, .release = qc_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 1f034d2397c6c6..684739b8efd05b 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -8,7 +8,7 @@ extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on); extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port); extern void usb_wwan_close(struct usb_serial_port *port); -extern int usb_wwan_startup(struct usb_serial *serial); +extern int usb_wwan_port_probe(struct usb_serial_port *port); extern int usb_wwan_port_remove(struct usb_serial_port *port); extern int usb_wwan_write_room(struct tty_struct *tty); extern void usb_wwan_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 6855d5ed033115..2f2d074a9081e0 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -447,10 +447,12 @@ void usb_wwan_close(struct usb_serial_port *port) EXPORT_SYMBOL(usb_wwan_close); /* Helper functions used by usb_wwan_setup_urbs */ -static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, +static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, + int endpoint, int dir, void *ctx, char *buf, int len, void (*callback) (struct urb *)) { + struct usb_serial *serial = port->serial; struct urb *urb; if (endpoint == -1) @@ -470,100 +472,74 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, return urb; } -/* Setup urbs */ -static void usb_wwan_setup_urbs(struct usb_serial *serial) +int usb_wwan_port_probe(struct usb_serial_port *port) { - int i, j; - struct usb_serial_port *port; struct usb_wwan_port_private *portdata; + struct urb *urb; + u8 *buffer; + int err; + int i; - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); - - /* Do indat endpoints first */ - for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_in_endpointAddress, - USB_DIR_IN, - port, - portdata-> - in_buffer[j], - IN_BUFLEN, - usb_wwan_indat_callback); - } - - /* outdat endpoints */ - for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_out_endpointAddress, - USB_DIR_OUT, - port, - portdata-> - out_buffer - [j], - OUT_BUFLEN, - usb_wwan_outdat_callback); - } - } -} + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; -int usb_wwan_startup(struct usb_serial *serial) -{ - int i, j, err; - struct usb_serial_port *port; - struct usb_wwan_port_private *portdata; - u8 *buffer; + init_usb_anchor(&portdata->delayed); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dbg("%s: kmalloc for usb_wwan_port_private (%d) failed!.", - __func__, i); - return 1; - } - init_usb_anchor(&portdata->delayed); + for (i = 0; i < N_IN_URB; i++) { + buffer = (u8 *)__get_free_page(GFP_KERNEL); + if (!buffer) + goto bail_out_error; + portdata->in_buffer[i] = buffer; + + urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress, + USB_DIR_IN, port, + buffer, IN_BUFLEN, + usb_wwan_indat_callback); + portdata->in_urbs[i] = urb; + } + for (i = 0; i < N_OUT_URB; i++) { + if (port->bulk_out_endpointAddress == -1) + continue; - for (j = 0; j < N_IN_URB; j++) { - buffer = (u8 *) __get_free_page(GFP_KERNEL); - if (!buffer) - goto bail_out_error; - portdata->in_buffer[j] = buffer; - } + buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); + if (!buffer) + goto bail_out_error2; + portdata->out_buffer[i] = buffer; - for (j = 0; j < N_OUT_URB; j++) { - buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); - if (!buffer) - goto bail_out_error2; - portdata->out_buffer[j] = buffer; - } + urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress, + USB_DIR_OUT, port, + buffer, OUT_BUFLEN, + usb_wwan_outdat_callback); + portdata->out_urbs[i] = urb; + } - usb_set_serial_port_data(port, portdata); + usb_set_serial_port_data(port, portdata); - if (!port->interrupt_in_urb) - continue; + if (port->interrupt_in_urb) { err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (err) - dbg("%s: submit irq_in urb failed %d", __func__, err); + dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n", + __func__, err); } - usb_wwan_setup_urbs(serial); + return 0; bail_out_error2: - for (j = 0; j < N_OUT_URB; j++) - kfree(portdata->out_buffer[j]); + for (i = 0; i < N_OUT_URB; i++) { + usb_free_urb(portdata->out_urbs[i]); + kfree(portdata->out_buffer[i]); + } bail_out_error: - for (j = 0; j < N_IN_URB; j++) - if (portdata->in_buffer[j]) - free_page((unsigned long)portdata->in_buffer[j]); + for (i = 0; i < N_IN_URB; i++) { + usb_free_urb(portdata->in_urbs[i]); + free_page((unsigned long)portdata->in_buffer[i]); + } kfree(portdata); - return 1; + + return -ENOMEM; } -EXPORT_SYMBOL(usb_wwan_startup); +EXPORT_SYMBOL_GPL(usb_wwan_port_probe); int usb_wwan_port_remove(struct usb_serial_port *port) { From 34a2ee3523326ee24676077b8c796719dfcf0efd Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 1 Oct 2012 22:21:12 +0300 Subject: [PATCH 0384/1071] usb hub: send clear_tt_buffer_complete events when canceling TT clear work commit 3b6054da68f9b0d5ed6a7ed0f42a79e61904352c upstream. There is a race condition in the USB hub code with regard to handling TT clear requests that can get the HCD driver in a deadlock. Usually when an TT clear request is scheduled it will be executed immediately: <7>[ 6.077583] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us] <3>[ 6.078041] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82 <7>[ 6.078299] hub_tt_work:731 <7>[ 9.309089] usb 2-1.5: link qh1-0e01/f4d506c0 start 0 [1/2 us] <7>[ 9.324526] ehci_hcd 0000:00:1d.0: reused qh f4d4db00 schedule <7>[ 9.324539] usb 2-1.3: link qh1-0e01/f4d4db00 start 0 [1/2 us] <7>[ 9.341530] usb 1-1.1: link qh4-0e01/f397aec0 start 2 [1/2 us] <7>[ 10.116159] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us] <3>[ 10.116459] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82 <7>[ 10.116537] hub_tt_work:731 However, if a suspend operation is triggered before hub_tt_work is scheduled, hub_quiesce will cancel the work without notifying the HCD driver: <3>[ 35.033941] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d80 <5>[ 35.034022] sd 0:0:0:0: [sda] Stopping disk <7>[ 35.034039] hub 2-1:1.0: hub_suspend <7>[ 35.034067] usb 2-1: unlink qh256-0001/f3b1ab00 start 1 [1/0 us] <7>[ 35.035085] hub 1-0:1.0: hub_suspend <7>[ 35.035102] usb usb1: bus suspend, wakeup 0 <7>[ 35.035106] ehci_hcd 0000:00:1a.0: suspend root hub <7>[ 35.035298] hub 2-0:1.0: hub_suspend <7>[ 35.035313] usb usb2: bus suspend, wakeup 0 <7>[ 35.035315] ehci_hcd 0000:00:1d.0: suspend root hub <6>[ 35.250017] PM: suspend of devices complete after 216.979 msecs <6>[ 35.250822] PM: late suspend of devices complete after 0.799 msecs <7>[ 35.252343] ehci_hcd 0000:00:1d.0: wakeup: 1 <7>[ 35.262923] ehci_hcd 0000:00:1d.0: --> PCI D3hot <7>[ 35.263302] ehci_hcd 0000:00:1a.0: wakeup: 1 <7>[ 35.273912] ehci_hcd 0000:00:1a.0: --> PCI D3hot <6>[ 35.274254] PM: noirq suspend of devices complete after 23.442 msecs <6>[ 35.274975] ACPI: Preparing to enter system sleep state S3 <6>[ 35.292666] PM: Saving platform NVS memory <7>[ 35.295030] Disabling non-boot CPUs ... <6>[ 35.297351] CPU 1 is now offline <6>[ 35.300345] CPU 2 is now offline <6>[ 35.303929] CPU 3 is now offline <7>[ 35.303931] lockdep: fixing up alternatives. <6>[ 35.304825] Extended CMOS year: 2000 When the device will resume the EHCI driver will get stuck in ehci_endpoint_disable waiting for the tt_clearing flag to reset: <0>[ 47.610967] usb 2-1.3: **** DPM device timeout **** <7>[ 47.610972] f2f11c60 00000092 f2f11c0c c10624a5 00000003 f4c6e880 c1c8a4c0 c1c8a4c0 <7>[ 47.610983] 15c55698 0000000b f56b34c0 f2a45b70 f4c6e880 00000082 f2a4602c f2f11c30 <7>[ 47.610993] c10787f8 f4cac000 f2a45b70 00000000 f4cac010 f2f11c58 00000046 00000001 <7>[ 47.611004] Call Trace: <7>[ 47.611006] [] ? sched_clock_cpu+0xf5/0x160 <7>[ 47.611019] [] ? lock_release_holdtime.part.22+0x88/0xf0 <7>[ 47.611026] [] ? lock_timer_base.isra.35+0x26/0x50 <7>[ 47.611034] [] ? schedule_timeout+0x133/0x290 <7>[ 47.611044] [] schedule+0x1e/0x50 <7>[ 47.611051] [] schedule_timeout+0x138/0x290 <7>[ 47.611057] [] ? sched_clock_cpu+0xf5/0x160 <7>[ 47.611063] [] ? usleep_range+0x40/0x40 <7>[ 47.611070] [] schedule_timeout_uninterruptible+0x15/0x20 <7>[ 47.611077] [] ehci_endpoint_disable+0x64/0x160 <7>[ 47.611084] [] ? usb_hcd_flush_endpoint+0x10e/0x1d0 <7>[ 47.611092] [] ? sysfs_add_file+0x13/0x20 <7>[ 47.611100] [] usb_hcd_disable_endpoint+0x29/0x40 <7>[ 47.611107] [] usb_disable_endpoint+0x5c/0x80 <7>[ 47.611111] [] usb_disable_interface+0x37/0x50 <7>[ 47.611116] [] usb_reset_and_verify_device+0x4b0/0x640 <7>[ 47.611122] [] ? hub_port_status+0xb5/0x100 <7>[ 47.611129] [] usb_port_resume+0xd5/0x220 <7>[ 47.611136] [] generic_resume+0xf/0x30 <7>[ 47.611142] [] usb_resume+0x133/0x180 <7>[ 47.611147] [] ? usb_dev_thaw+0x10/0x10 <7>[ 47.611152] [] usb_dev_resume+0xd/0x10 <7>[ 47.611157] [] dpm_run_callback+0x40/0xb0 <7>[ 47.611164] [] ? pm_runtime_enable+0x43/0x70 <7>[ 47.611171] [] device_resume+0x1a6/0x2c0 <7>[ 47.611177] [] ? dpm_show_time+0xe0/0xe0 <7>[ 47.611183] [] async_resume+0x19/0x40 <7>[ 47.611189] [] async_run_entry_fn+0x64/0x160 <7>[ 47.611196] [] ? process_one_work+0x104/0x480 <7>[ 47.611203] [] ? process_one_work+0x10c/0x480 <7>[ 47.611209] [] process_one_work+0x180/0x480 <7>[ 47.611215] [] ? process_one_work+0x104/0x480 <7>[ 47.611220] [] ? async_schedule+0x10/0x10 <7>[ 47.611226] [] worker_thread+0x11c/0x2f0 <7>[ 47.611233] [] ? manage_workers.isra.27+0x1f0/0x1f0 <7>[ 47.611239] [] kthread+0x78/0x80 <7>[ 47.611244] [] ? timer_cpu_notify+0xd6/0x20d <7>[ 47.611253] [] ? __init_kthread_worker+0x60/0x60 <7>[ 47.611258] [] kernel_thread_helper+0x6/0xd <7>[ 47.611283] ------------[ cut here ]------------ This patch changes hub_quiesce behavior to flush the TT clear work instead of canceling it, to make sure that no TT clear request remains uncompleted before suspend. Signed-off-by: Octavian Purdila Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index bbff14318c1f69..fe7faf03d8b23a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -730,13 +730,16 @@ static void hub_tt_work(struct work_struct *work) int limit = 100; spin_lock_irqsave (&hub->tt.lock, flags); - while (--limit && !list_empty (&hub->tt.clear_list)) { + while (!list_empty(&hub->tt.clear_list)) { struct list_head *next; struct usb_tt_clear *clear; struct usb_device *hdev = hub->hdev; const struct hc_driver *drv; int status; + if (!hub->quiescing && --limit < 0) + break; + next = hub->tt.clear_list.next; clear = list_entry (next, struct usb_tt_clear, clear_list); list_del (&clear->clear_list); @@ -1201,7 +1204,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); if (hub->tt.hub) - cancel_work_sync(&hub->tt.clear_work); + flush_work_sync(&hub->tt.clear_work); } /* caller has locked the hub device */ From 226c125e2f5b479dc1fee67bbd3a84c90021c816 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:03 +0200 Subject: [PATCH 0385/1071] USB: ch341: fix port-data memory leak commit 456c5be56ed070a4d883c60b587bcc1c97a8cf3e upstream. Fix port-data memory leak by moving port data allocation to port_probe and actually implementing deallocation. Note that this driver has never even bothered to try to deallocate it's port data... Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index cabd1b15ddce93..8391d3040e71df 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -241,13 +241,11 @@ out: kfree(buffer); return r; } -/* allocate private data */ -static int ch341_attach(struct usb_serial *serial) +static int ch341_port_probe(struct usb_serial_port *port) { struct ch341_private *priv; int r; - /* private data */ priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -257,17 +255,27 @@ static int ch341_attach(struct usb_serial *serial) priv->baud_rate = DEFAULT_BAUD_RATE; priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; - r = ch341_configure(serial->dev, priv); + r = ch341_configure(port->serial->dev, priv); if (r < 0) goto error; - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; error: kfree(priv); return r; } +static int ch341_port_remove(struct usb_serial_port *port) +{ + struct ch341_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} + static int ch341_carrier_raised(struct usb_serial_port *port) { struct ch341_private *priv = usb_get_serial_port_data(port); @@ -303,7 +311,7 @@ static void ch341_close(struct usb_serial_port *port) static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); + struct ch341_private *priv = usb_get_serial_port_data(port); int r; priv->baud_rate = DEFAULT_BAUD_RATE; @@ -606,7 +614,8 @@ static struct usb_serial_driver ch341_device = { .tiocmget = ch341_tiocmget, .tiocmset = ch341_tiocmset, .read_int_callback = ch341_read_int_callback, - .attach = ch341_attach, + .port_probe = ch341_port_probe, + .port_remove = ch341_port_remove, .reset_resume = ch341_reset_resume, }; From 8d7e8206ad00c040b2075184236c325cd1ba14a2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:04 +0200 Subject: [PATCH 0386/1071] USB: digi_acceleport: fix port-data memory leak commit fb44ff854e148bc5c5982dad32da98b7a0989d2d upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the oob port is never registered as a port device and should thus be handled in attach and release. Compile-only tested. Signed-off-by: Johan Hovold Cc: Peter Berger Cc: Al Borchers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/digi_acceleport.c | 117 +++++++++++++++------------ 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b5cd838093ef58..06e8bf45ca09bf 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); static void digi_disconnect(struct usb_serial *serial); static void digi_release(struct usb_serial *serial); +static int digi_port_probe(struct usb_serial_port *port); +static int digi_port_remove(struct usb_serial_port *port); static void digi_read_bulk_callback(struct urb *urb); static int digi_read_inb_callback(struct urb *urb); static int digi_read_oob_callback(struct urb *urb); @@ -298,6 +300,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver digi_acceleport_4_device = { @@ -324,6 +328,8 @@ static struct usb_serial_driver digi_acceleport_4_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -1237,59 +1243,50 @@ static int digi_startup_device(struct usb_serial *serial) return ret; } - -static int digi_startup(struct usb_serial *serial) +static int digi_port_init(struct usb_serial_port *port, unsigned port_num) { - - int i; struct digi_port *priv; - struct digi_serial *serial_priv; - /* allocate the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) { - /* allocate port private structure */ - priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); - if (priv == NULL) { - while (--i >= 0) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* initialize port private structure */ - spin_lock_init(&priv->dp_port_lock); - priv->dp_port_num = i; - priv->dp_out_buf_len = 0; - priv->dp_write_urb_in_use = 0; - priv->dp_modem_signals = 0; - init_waitqueue_head(&priv->dp_modem_change_wait); - priv->dp_transmit_idle = 0; - init_waitqueue_head(&priv->dp_transmit_idle_wait); - priv->dp_throttled = 0; - priv->dp_throttle_restart = 0; - init_waitqueue_head(&priv->dp_flush_wait); - init_waitqueue_head(&priv->dp_close_wait); - INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); - priv->dp_port = serial->port[i]; - /* initialize write wait queue for this port */ - init_waitqueue_head(&serial->port[i]->write_wait); - - usb_set_serial_port_data(serial->port[i], priv); - } + spin_lock_init(&priv->dp_port_lock); + priv->dp_port_num = port_num; + init_waitqueue_head(&priv->dp_modem_change_wait); + init_waitqueue_head(&priv->dp_transmit_idle_wait); + init_waitqueue_head(&priv->dp_flush_wait); + init_waitqueue_head(&priv->dp_close_wait); + INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = port; - /* allocate serial private structure */ - serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL); - if (serial_priv == NULL) { - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + init_waitqueue_head(&port->write_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int digi_startup(struct usb_serial *serial) +{ + struct digi_serial *serial_priv; + int ret; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; - /* initialize serial private structure */ spin_lock_init(&serial_priv->ds_serial_lock); serial_priv->ds_oob_port_num = serial->type->num_ports; serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; - serial_priv->ds_device_started = 0; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); + if (ret) { + kfree(serial_priv); + return ret; + } + usb_set_serial_data(serial, serial_priv); return 0; @@ -1310,15 +1307,35 @@ static void digi_disconnect(struct usb_serial *serial) static void digi_release(struct usb_serial *serial) { - int i; + struct digi_serial *serial_priv; + struct digi_port *priv; + + serial_priv = usb_get_serial_data(serial); + + priv = usb_get_serial_port_data(serial_priv->ds_oob_port); + kfree(priv); - /* free the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - kfree(usb_get_serial_data(serial)); + kfree(serial_priv); } +static int digi_port_probe(struct usb_serial_port *port) +{ + unsigned port_num; + + port_num = port->number - port->serial->minor; + + return digi_port_init(port, port_num); +} + +static int digi_port_remove(struct usb_serial_port *port) +{ + struct digi_port *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static void digi_read_bulk_callback(struct urb *urb) { From e830d9c15b2b6cbc557d213c52f8d1835002c66f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 15:42:39 +0200 Subject: [PATCH 0387/1071] USB: ipw: fix interface-data memory leak in error path commit a997448c89905b80aa4022f734f03685e733d711 upstream. Move interface data allocation to attach so that it is deallocated should usb-serial probe fail. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index dfaf7f1a475b2f..8df011f8988cd6 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -209,8 +209,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) return 0; } -/* fake probe - only to allocate data structures */ -static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id) +static int ipw_attach(struct usb_serial *serial) { struct usb_wwan_intf_private *data; @@ -310,7 +309,7 @@ static struct usb_serial_driver ipw_device = { .num_ports = 1, .open = ipw_open, .close = ipw_close, - .probe = ipw_probe, + .attach = ipw_attach, .release = ipw_release, .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, From 14e6c99bfc02a84d98ee77552a328855c1db31e5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:13 +0200 Subject: [PATCH 0388/1071] USB: mct_u232: fix port-data memory leak commit a8f2ae7a3aa59079d7e7e1ddf5007f03532f458c upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the write waitqueue was initialised but never used. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 45 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a71fa0aa04066d..6801f4e10318af 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -51,7 +51,8 @@ static bool debug; * Function prototypes */ static int mct_u232_startup(struct usb_serial *serial); -static void mct_u232_release(struct usb_serial *serial); +static int mct_u232_port_probe(struct usb_serial_port *port); +static int mct_u232_port_remove(struct usb_serial_port *remove); static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port); static void mct_u232_close(struct usb_serial_port *port); static void mct_u232_dtr_rts(struct usb_serial_port *port, int on); @@ -101,7 +102,8 @@ static struct usb_serial_driver mct_u232_device = { .tiocmget = mct_u232_tiocmget, .tiocmset = mct_u232_tiocmset, .attach = mct_u232_startup, - .release = mct_u232_release, + .port_probe = mct_u232_port_probe, + .port_remove = mct_u232_port_remove, .ioctl = mct_u232_ioctl, .get_icount = mct_u232_get_icount, }; @@ -392,18 +394,8 @@ static void mct_u232_msr_to_state(unsigned int *control_state, static int mct_u232_startup(struct usb_serial *serial) { - struct mct_u232_private *priv; struct usb_serial_port *port, *rport; - priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->msr_wait); - usb_set_serial_port_data(serial->port[0], priv); - - init_waitqueue_head(&serial->port[0]->write_wait); - /* Puh, that's dirty */ port = serial->port[0]; rport = serial->port[1]; @@ -416,18 +408,31 @@ static int mct_u232_startup(struct usb_serial *serial) return 0; } /* mct_u232_startup */ +static int mct_u232_port_probe(struct usb_serial_port *port) +{ + struct mct_u232_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; -static void mct_u232_release(struct usb_serial *serial) + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int mct_u232_port_remove(struct usb_serial_port *port) { struct mct_u232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} /* mct_u232_release */ + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) { From 9e7922db1d38b0ee22355cda640c175bc4e5501a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:14 +0200 Subject: [PATCH 0389/1071] USB: mct_u232: fix broken close commit 5260e458f5eff269a43e4f1e9c47186c57b88ddb upstream. Make sure generic close is called at close. The driver relies on the generic write implementation but did not call generic close. Note that the call to kill the read urb is not redundant, as mct_u232 uses an interrupt urb from the second port as the read urb and that generic close therefore fails to kill it. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 6801f4e10318af..c088250555ba0a 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -524,12 +524,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) static void mct_u232_close(struct usb_serial_port *port) { - if (port->serial->dev) { - /* shutdown our urbs */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - } + /* + * Must kill the read urb as it is actually an interrupt urb, which + * generic close thus fails to kill. + */ + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + usb_serial_generic_close(port); } /* mct_u232_close */ From d16dbb330b8517c1df7e03c120cac572d726a5b6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 15:42:40 +0200 Subject: [PATCH 0390/1071] USB: option: fix interface-data memory leak in error path commit c2dd4a8eac7821fed2c2d19e4607d0986b53b0fe upstream. Move interface data allocation to attach so that it is deallocated should usb-serial probe fail. Note that the usb device id is stored at probe so that it can be used in attach to determine send-setup blacklisting. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 1f33e34addbab6..76a48e45d781d7 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -47,6 +47,7 @@ /* Function prototypes */ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id); +static int option_attach(struct usb_serial *serial); static void option_release(struct usb_serial *serial); static int option_send_setup(struct usb_serial_port *port); static void option_instat_callback(struct urb *urb); @@ -1288,6 +1289,7 @@ static struct usb_serial_driver option_1port_device = { .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, + .attach = option_attach, .release = option_release, .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, @@ -1337,8 +1339,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; - struct option_private *priv; struct usb_interface_descriptor *iface_desc = &serial->interface->cur_altsetting->desc; struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; @@ -1376,6 +1376,19 @@ static int option_probe(struct usb_serial *serial, iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; + /* Store device id so we can use it during attach. */ + usb_set_serial_data(serial, (void *)id); + + return 0; +} + +static int option_attach(struct usb_serial *serial) +{ + struct usb_interface_descriptor *iface_desc; + const struct usb_device_id *id; + struct usb_wwan_intf_private *data; + struct option_private *priv; + data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1386,6 +1399,10 @@ static int option_probe(struct usb_serial *serial, return -ENOMEM; } + /* Retrieve device id stored at probe. */ + id = usb_get_serial_data(serial); + iface_desc = &serial->interface->cur_altsetting->desc; + priv->bInterfaceNumber = iface_desc->bInterfaceNumber; data->private = priv; From 789a4bbd28e4e5128a66a6e35117ef9392fed867 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:15 +0200 Subject: [PATCH 0391/1071] USB: keyspan: fix NULL-pointer dereferences and memory leaks commit f79b2d0fe81eecb412dc48e87a119afc690da8e9 upstream. Fix NULL-pointer dereference at release by moving port data allocation and deallocation to port_probe and port_remove. Fix NULL-pointer dereference at disconnect by stopping port urbs at port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer accessible at disconnect or release. Note that this patch also fixes port and interface-data memory leaks in the error path of attach should port initialisation fail for any port. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 183 +++++++++++++++++------------------ drivers/usb/serial/keyspan.h | 8 ++ 2 files changed, 96 insertions(+), 95 deletions(-) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index af0b70eaf032f6..f6788d7e915bce 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1392,13 +1392,9 @@ static struct callbacks { data in device_details */ static void keyspan_setup_urbs(struct usb_serial *serial) { - int i, j; struct keyspan_serial_private *s_priv; const struct keyspan_device_details *d_details; - struct usb_serial_port *port; - struct keyspan_port_private *p_priv; struct callbacks *cback; - int endp; s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; @@ -1422,45 +1418,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial) (serial, d_details->glocont_endpoint, USB_DIR_OUT, serial, s_priv->glocont_buf, GLOCONT_BUFLEN, cback->glocont_callback); - - /* Setup endpoints for each port specific thing */ - for (i = 0; i < d_details->num_ports; i++) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - - /* Do indat endpoints first, once for each flip */ - endp = d_details->indat_endpoints[i]; - for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { - p_priv->in_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_IN, port, - p_priv->in_buffer[j], 64, - cback->indat_callback); - } - for (; j < 2; ++j) - p_priv->in_urbs[j] = NULL; - - /* outdat endpoints also have flip */ - endp = d_details->outdat_endpoints[i]; - for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { - p_priv->out_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_OUT, port, - p_priv->out_buffer[j], 64, - cback->outdat_callback); - } - for (; j < 2; ++j) - p_priv->out_urbs[j] = NULL; - - /* inack endpoint */ - p_priv->inack_urb = keyspan_setup_urb - (serial, d_details->inack_endpoints[i], USB_DIR_IN, - port, p_priv->inack_buffer, 1, cback->inack_callback); - - /* outcont endpoint */ - p_priv->outcont_urb = keyspan_setup_urb - (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, - port, p_priv->outcont_buffer, 64, - cback->outcont_callback); - } } /* usa19 function doesn't require prescaler */ @@ -2422,9 +2379,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) static int keyspan_startup(struct usb_serial *serial) { int i, err; - struct usb_serial_port *port; struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) @@ -2448,19 +2403,6 @@ static int keyspan_startup(struct usb_serial *serial) s_priv->device_details = d_details; usb_set_serial_data(serial, s_priv); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - p_priv = kzalloc(sizeof(struct keyspan_port_private), - GFP_KERNEL); - if (!p_priv) { - dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i); - return 1; - } - p_priv->device_details = d_details; - usb_set_serial_port_data(port, p_priv); - } - keyspan_setup_urbs(serial); if (s_priv->instat_urb != NULL) { @@ -2481,61 +2423,112 @@ static int keyspan_startup(struct usb_serial *serial) static void keyspan_disconnect(struct usb_serial *serial) { - int i, j; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; + struct keyspan_serial_private *s_priv; s_priv = usb_get_serial_data(serial); - /* Stop reading/writing urbs */ stop_urb(s_priv->instat_urb); stop_urb(s_priv->glocont_urb); stop_urb(s_priv->indat_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - stop_urb(p_priv->inack_urb); - stop_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - stop_urb(p_priv->in_urbs[j]); - stop_urb(p_priv->out_urbs[j]); - } - } +} + +static void keyspan_release(struct usb_serial *serial) +{ + struct keyspan_serial_private *s_priv; + + s_priv = usb_get_serial_data(serial); - /* Now free them */ usb_free_urb(s_priv->instat_urb); usb_free_urb(s_priv->indat_urb); usb_free_urb(s_priv->glocont_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - usb_free_urb(p_priv->inack_urb); - usb_free_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - usb_free_urb(p_priv->in_urbs[j]); - usb_free_urb(p_priv->out_urbs[j]); - } - } + + kfree(s_priv); } -static void keyspan_release(struct usb_serial *serial) +static int keyspan_port_probe(struct usb_serial_port *port) { - int i; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; + struct usb_serial *serial = port->serial; + struct keyspan_port_private *s_priv; + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + struct callbacks *cback; + int endp; + int port_num; + int i; s_priv = usb_get_serial_data(serial); + d_details = s_priv->device_details; - /* dbg("Freeing serial->private."); */ - kfree(s_priv); + p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); + if (!p_priv) + return -ENOMEM; - /* dbg("Freeing port->private."); */ - /* Now free per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - kfree(usb_get_serial_port_data(port)); + s_priv = usb_get_serial_data(port->serial); + p_priv->device_details = d_details; + + /* Setup values for the various callback routines */ + cback = &keyspan_callbacks[d_details->msg_format]; + + port_num = port->number - port->serial->minor; + + /* Do indat endpoints first, once for each flip */ + endp = d_details->indat_endpoints[port_num]; + for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { + p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_IN, port, + p_priv->in_buffer[i], 64, + cback->indat_callback); + } + /* outdat endpoints also have flip */ + endp = d_details->outdat_endpoints[port_num]; + for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { + p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_OUT, port, + p_priv->out_buffer[i], 64, + cback->outdat_callback); + } + /* inack endpoint */ + p_priv->inack_urb = keyspan_setup_urb(serial, + d_details->inack_endpoints[port_num], + USB_DIR_IN, port, + p_priv->inack_buffer, 1, + cback->inack_callback); + /* outcont endpoint */ + p_priv->outcont_urb = keyspan_setup_urb(serial, + d_details->outcont_endpoints[port_num], + USB_DIR_OUT, port, + p_priv->outcont_buffer, 64, + cback->outcont_callback); + + usb_set_serial_port_data(port, p_priv); + + return 0; +} + +static int keyspan_port_remove(struct usb_serial_port *port) +{ + struct keyspan_port_private *p_priv; + int i; + + p_priv = usb_get_serial_port_data(port); + + stop_urb(p_priv->inack_urb); + stop_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + stop_urb(p_priv->in_urbs[i]); + stop_urb(p_priv->out_urbs[i]); + } + + usb_free_urb(p_priv->inack_urb); + usb_free_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + usb_free_urb(p_priv->in_urbs[i]); + usb_free_urb(p_priv->out_urbs[i]); } + + kfree(p_priv); + + return 0; } MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index fe1c5d91692cd9..90a7b361d2a699 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -42,6 +42,8 @@ static void keyspan_dtr_rts (struct usb_serial_port *port, int on); static int keyspan_startup (struct usb_serial *serial); static void keyspan_disconnect (struct usb_serial *serial); static void keyspan_release (struct usb_serial *serial); +static int keyspan_port_probe(struct usb_serial_port *port); +static int keyspan_port_remove(struct usb_serial_port *port); static int keyspan_write_room (struct tty_struct *tty); static int keyspan_write (struct tty_struct *tty, @@ -562,6 +564,8 @@ static struct usb_serial_driver keyspan_1port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_2port_device = { @@ -584,6 +588,8 @@ static struct usb_serial_driver keyspan_2port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_4port_device = { @@ -606,6 +612,8 @@ static struct usb_serial_driver keyspan_4port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { From 1968e8d84329760f4722c5c3951aec28b5ece59b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:06 +0200 Subject: [PATCH 0392/1071] USB: omninet: fix port-data memory leak commit feffa7ca6008ab859dd7ab7448a5a899bf0aa98f upstream. Fix port-data memory leak by replacing attach and release with port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6f3d7051c7f415..27c9d06f82117a 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -46,8 +46,8 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static int omninet_write_room(struct tty_struct *tty); static void omninet_disconnect(struct usb_serial *serial); -static void omninet_release(struct usb_serial *serial); -static int omninet_attach(struct usb_serial *serial); +static int omninet_port_probe(struct usb_serial_port *port); +static int omninet_port_remove(struct usb_serial_port *port); static const struct usb_device_id id_table[] = { { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, @@ -64,7 +64,8 @@ static struct usb_serial_driver zyxel_omninet_device = { .description = "ZyXEL - omni.net lcd plus usb", .id_table = id_table, .num_ports = 1, - .attach = omninet_attach, + .port_probe = omninet_port_probe, + .port_remove = omninet_port_remove, .open = omninet_open, .close = omninet_close, .write = omninet_write, @@ -72,7 +73,6 @@ static struct usb_serial_driver zyxel_omninet_device = { .read_bulk_callback = omninet_read_bulk_callback, .write_bulk_callback = omninet_write_bulk_callback, .disconnect = omninet_disconnect, - .release = omninet_release, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -114,18 +114,26 @@ struct omninet_data { __u8 od_outseq; /* Sequence number for bulk_out URBs */ }; -static int omninet_attach(struct usb_serial *serial) +static int omninet_port_probe(struct usb_serial_port *port) { struct omninet_data *od; - struct usb_serial_port *port = serial->port[0]; od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); - if (!od) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", - __func__, sizeof(struct omninet_data)); + if (!od) return -ENOMEM; - } + usb_set_serial_port_data(port, od); + + return 0; +} + +static int omninet_port_remove(struct usb_serial_port *port) +{ + struct omninet_data *od; + + od = usb_get_serial_port_data(port); + kfree(od); + return 0; } @@ -291,14 +299,6 @@ static void omninet_disconnect(struct usb_serial *serial) usb_kill_urb(wport->write_urb); } - -static void omninet_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - - kfree(usb_get_serial_port_data(port)); -} - module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); From bf66cd30357174ed30c140f79b4016f4230a0066 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 15:42:41 +0200 Subject: [PATCH 0393/1071] USB: qcserial: fix interface-data memory leak in error path commit 961be09e1ead58509ed4bed0d5819a15d8613d8d upstream. Move interface data allocation to attach so that it is deallocated should usb-serial probe fail. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index f039733df186b7..93232ca73b440b 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -140,7 +140,6 @@ MODULE_DEVICE_TABLE(usb, id_table); static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; struct usb_host_interface *intf = serial->interface->cur_altsetting; struct device *dev = &serial->dev->dev; int retval = -ENODEV; @@ -156,13 +155,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) ifnum = intf->desc.bInterfaceNumber; dev_dbg(dev, "This Interface = %d\n", ifnum); - data = kzalloc(sizeof(struct usb_wwan_intf_private), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - spin_lock_init(&data->susp_lock); - if (nintf == 1) { /* QDL mode */ /* Gobi 2000 has a single altsetting, older ones have two */ @@ -255,20 +247,28 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) } } - /* Set serial->private if not returning error */ - if (retval == 0) - usb_set_serial_data(serial, data); - else - kfree(data); - return retval; } +static int qc_attach(struct usb_serial *serial) +{ + struct usb_wwan_intf_private *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&data->susp_lock); + + usb_set_serial_data(serial, data); + + return 0; +} + static void qc_release(struct usb_serial *serial) { struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - /* Free the private data allocated in qcprobe */ usb_set_serial_data(serial, NULL); kfree(priv); } @@ -287,6 +287,7 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, + .attach = qc_attach, .release = qc_release, .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, From 09d35f2c69e5f92db3ec0b8f3ce62be0c0bbacc2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:01 +0200 Subject: [PATCH 0394/1071] USB: whiteheat: fix memory leak in error path commit c129197c99550d356cf5f69b046994dd53cd1b9d upstream. Make sure command buffer is deallocated in case of errors during attach. Signed-off-by: Johan Hovold Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/whiteheat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 473635e7f5dbdf..b65ac03c437418 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -405,6 +405,7 @@ static int whiteheat_attach(struct usb_serial *serial) "%s: please contact support@connecttech.com\n", serial->type->description); kfree(result); + kfree(command); return -ENODEV; no_command_private: From 5cd933664edb0f9cb7f52c40219668267571bf40 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:02 +0200 Subject: [PATCH 0395/1071] USB: whiteheat: fix port-data memory leak commit c467206ed6bcce26c83d0435612cc4fee2527305 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the fifth port (command port) is never registered as a port device and thus should be handled in attach and release. Compile-only tested. Signed-off-by: Johan Hovold Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/whiteheat.c | 59 +++++++++++++++------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index b65ac03c437418..bd3632173d0228 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -86,6 +86,8 @@ static int whiteheat_firmware_attach(struct usb_serial *serial); /* function prototypes for the Connect Tech WhiteHEAT serial converter */ static int whiteheat_attach(struct usb_serial *serial); static void whiteheat_release(struct usb_serial *serial); +static int whiteheat_port_probe(struct usb_serial_port *port); +static int whiteheat_port_remove(struct usb_serial_port *port); static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port); static void whiteheat_close(struct usb_serial_port *port); @@ -120,6 +122,8 @@ static struct usb_serial_driver whiteheat_device = { .num_ports = 4, .attach = whiteheat_attach, .release = whiteheat_release, + .port_probe = whiteheat_port_probe, + .port_remove = whiteheat_port_remove, .open = whiteheat_open, .close = whiteheat_close, .ioctl = whiteheat_ioctl, @@ -290,15 +294,12 @@ static int whiteheat_attach(struct usb_serial *serial) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; - struct usb_serial_port *port; - struct whiteheat_private *info; struct whiteheat_hw_info *hw_info; int pipe; int ret; int alen; __u8 *command; __u8 *result; - int i; command_port = serial->port[COMMAND_PORT]; @@ -357,22 +358,6 @@ static int whiteheat_attach(struct usb_serial *serial) serial->type->description, hw_info->sw_major_rev, hw_info->sw_minor_rev); - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - - info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); - if (info == NULL) { - dev_err(&port->dev, - "%s: Out of memory for port structures\n", - serial->type->description); - goto no_private; - } - - info->mcr = 0; - - usb_set_serial_port_data(port, info); - } - command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (command_info == NULL) { @@ -409,13 +394,6 @@ static int whiteheat_attach(struct usb_serial *serial) return -ENODEV; no_command_private: - for (i = serial->num_ports - 1; i >= 0; i--) { - port = serial->port[i]; - info = usb_get_serial_port_data(port); - kfree(info); -no_private: - ; - } kfree(result); no_result_buffer: kfree(command); @@ -423,21 +401,36 @@ static int whiteheat_attach(struct usb_serial *serial) return -ENOMEM; } - static void whiteheat_release(struct usb_serial *serial) { struct usb_serial_port *command_port; - struct whiteheat_private *info; - int i; /* free up our private data for our command port */ command_port = serial->port[COMMAND_PORT]; kfree(usb_get_serial_port_data(command_port)); +} - for (i = 0; i < serial->num_ports; i++) { - info = usb_get_serial_port_data(serial->port[i]); - kfree(info); - } +static int whiteheat_port_probe(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + usb_set_serial_port_data(port, info); + + return 0; +} + +static int whiteheat_port_remove(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = usb_get_serial_port_data(port); + kfree(info); + + return 0; } static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) From f2eed28b4ba4b289f51567e19d7933be0348da55 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:11 +0200 Subject: [PATCH 0396/1071] USB: opticon: fix DMA from stack commit ea0dbebffe118724cd4df7d9b071ea8ee48d48f0 upstream. Make sure to allocate the control-message buffer dynamically as some platforms cannot do DMA from stack. Note that only the first byte of the old buffer was used. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 02cb1b7f6559b0..5ba27007fb1bed 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -158,7 +158,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, { struct usb_serial *serial = port->serial; int retval; - u8 buffer[2]; + u8 *buffer; + + buffer = kzalloc(1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; buffer[0] = val; /* Send the message to the vendor control endpoint @@ -167,6 +171,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, requesttype, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0, 0, buffer, 1, 0); + kfree(buffer); return retval; } From e16f68849ef8ccd4578047f306aface94176ea2a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:12 +0200 Subject: [PATCH 0397/1071] USB: opticon: fix memory leak in error path commit acbf0e5263de563e25f7c104868e4490b9e72b13 upstream. Fix memory leak in write error path. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 5ba27007fb1bed..623358a426d9dd 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -289,7 +289,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, if (!dr) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; - goto error; + goto error_no_dr; } dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -319,6 +319,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, return count; error: + kfree(dr); +error_no_dr: usb_free_urb(urb); error_no_urb: kfree(buffer); From 10899e1d571d11982a4bd57e2112d475429583fa Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:28:59 +0200 Subject: [PATCH 0398/1071] USB: metro-usb: fix port-data memory leak commit 50dde8686eec41bf3d7cbec7a6f76c073ab01903 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the call to metrousb_clean (close) in shutdown was redundant. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 50 +++++++++------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index d47eb06fe463b5..1fb0325f822b97 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -280,51 +280,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr return retval; } -static void metrousb_shutdown(struct usb_serial *serial) +static int metrousb_port_probe(struct usb_serial_port *port) { - int i = 0; + struct metrousb_private *metro_priv; - dev_dbg(&serial->dev->dev, "%s\n", __func__); + metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL); + if (!metro_priv) + return -ENOMEM; - /* Stop reading and writing on all ports. */ - for (i = 0; i < serial->num_ports; ++i) { - /* Close any open urbs. */ - metrousb_cleanup(serial->port[i]); + spin_lock_init(&metro_priv->lock); - /* Free memory. */ - kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); + usb_set_serial_port_data(port, metro_priv); - dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", - __func__, serial->port[i]->number); - } + return 0; } -static int metrousb_startup(struct usb_serial *serial) +static int metrousb_port_remove(struct usb_serial_port *port) { struct metrousb_private *metro_priv; - struct usb_serial_port *port; - int i = 0; - - dev_dbg(&serial->dev->dev, "%s\n", __func__); - /* Loop through the serial ports setting up the private structures. - * Currently we only use one port. */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - - /* Declare memory. */ - metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); - if (!metro_priv) - return -ENOMEM; - - /* Initialize memory. */ - spin_lock_init(&metro_priv->lock); - usb_set_serial_port_data(port, metro_priv); - - dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", - __func__, port->number); - } + metro_priv = usb_get_serial_port_data(port); + kfree(metro_priv); return 0; } @@ -423,8 +399,8 @@ static struct usb_serial_driver metrousb_device = { .close = metrousb_cleanup, .read_int_callback = metrousb_read_int_callback, .write_int_callback = metrousb_write_int_callback, - .attach = metrousb_startup, - .release = metrousb_shutdown, + .port_probe = metrousb_port_probe, + .port_remove = metrousb_port_remove, .throttle = metrousb_throttle, .unthrottle = metrousb_unthrottle, .tiocmget = metrousb_tiocmget, From bd0758d884d30c79e064db3b7d18cc1ae4899843 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:00 +0200 Subject: [PATCH 0399/1071] USB: metro-usb: fix io after disconnect commit 2ee44fbeac92c36e53779a57ee84cfee1affe418 upstream. Make sure no control urb is submitted during close after a disconnect by checking the disconnected flag. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 1fb0325f822b97..d284fb847825a5 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -188,16 +188,13 @@ static void metrousb_cleanup(struct usb_serial_port *port) { dev_dbg(&port->dev, "%s\n", __func__); - if (port->serial->dev) { - /* Shutdown any interrupt in urbs. */ - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_in_urb); - } - - /* Send deactivate cmd to device */ + usb_unlink_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); + + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); - } + mutex_unlock(&port->serial->disc_mutex); } static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) From 89133c6f9cf825de28dff95aa4e933d5349b0101 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:05 +0200 Subject: [PATCH 0400/1071] USB: mos7720: fix port-data memory leak commit 4230af572f95b3115bba1ee6fb95681f3851ab26 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that this patch also fixes a second port-data memory leak in the error path of attach, should parallel-port initialisation fail. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 62 +++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index a07dd3c8cfef3e..eb847676a35372 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -2023,9 +2023,7 @@ static int mos7720_ioctl(struct tty_struct *tty, static int mos7720_startup(struct usb_serial *serial) { - struct moschip_port *mos7720_port; struct usb_device *dev; - int i; char data; u16 product; int ret_val; @@ -2063,29 +2061,6 @@ static int mos7720_startup(struct usb_serial *serial) serial->port[1]->interrupt_in_buffer = NULL; } - - /* set up serial port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); - if (mos7720_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - return -ENOMEM; - } - - /* Initialize all port interrupt end point to port 0 int - * endpoint. Our device has only one interrupt endpoint - * common to all ports */ - serial->port[i]->interrupt_in_endpointAddress = - serial->port[0]->interrupt_in_endpointAddress; - - mos7720_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], mos7720_port); - - dbg("port number is %d", serial->port[i]->number); - dbg("serial number is %d", serial->minor); - } - - /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); @@ -2113,8 +2088,6 @@ static int mos7720_startup(struct usb_serial *serial) static void mos7720_release(struct usb_serial *serial) { - int i; - #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT /* close the parallel port */ @@ -2153,9 +2126,36 @@ static void mos7720_release(struct usb_serial *serial) kref_put(&mos_parport->ref_count, destroy_mos_parport); } #endif - /* free private structure allocated for serial port */ - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); +} + +static int mos7720_port_probe(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL); + if (!mos7720_port) + return -ENOMEM; + + /* Initialize all port interrupt end point to port 0 int endpoint. + * Our device has only one interrupt endpoint common to all ports. + */ + port->interrupt_in_endpointAddress = + port->serial->port[0]->interrupt_in_endpointAddress; + mos7720_port->port = port; + + usb_set_serial_port_data(port, mos7720_port); + + return 0; +} + +static int mos7720_port_remove(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = usb_get_serial_port_data(port); + kfree(mos7720_port); + + return 0; } static struct usb_serial_driver moschip7720_2port_driver = { @@ -2173,6 +2173,8 @@ static struct usb_serial_driver moschip7720_2port_driver = { .probe = mos77xx_probe, .attach = mos7720_startup, .release = mos7720_release, + .port_probe = mos7720_port_probe, + .port_remove = mos7720_port_remove, .ioctl = mos7720_ioctl, .tiocmget = mos7720_tiocmget, .tiocmset = mos7720_tiocmset, From 24496dfe837363e83d9f1dde5bd68372088e6f88 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:07 +0200 Subject: [PATCH 0401/1071] USB: quatech2: fix memory leak in error path commit b8a0055050b6294826171641b182c09f78f4cc63 upstream. Fix memory leak in attach error path where the read urb was never freed. Signed-off-by: Johan Hovold Cc: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 151670b6b72a98..2cd5493d611fc6 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -825,6 +825,7 @@ static int qt2_setup_urbs(struct usb_serial *serial) if (status != 0) { dev_err(&serial->dev->dev, "%s - submit read urb failed %i\n", __func__, status); + usb_free_urb(serial_priv->read_urb); return status; } From b7e9cee3e7062435521dd933ce2349a2d721e596 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:08 +0200 Subject: [PATCH 0402/1071] USB: quatech2: fix port-data memory leaks commit 40d04738491d7ac1aa708ba434ff3480ec9e1b96 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that this also fixes memory leaks in the error path of attach where the write urbs were not freed on errors. Make sure all interface-data deallocation is done in release by moving the read urb deallocation from disconnect. Note that the write urb is killed during close so that the call in disconnect was superfluous. Compile-only tested. Signed-off-by: Johan Hovold Cc: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 121 ++++++++++++++-------------------- 1 file changed, 51 insertions(+), 70 deletions(-) diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2cd5493d611fc6..e87cd59daa0a57 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -145,12 +145,12 @@ static void qt2_read_bulk_callback(struct urb *urb); static void qt2_release(struct usb_serial *serial) { - int i; + struct qt2_serial_private *serial_priv; - kfree(usb_get_serial_data(serial)); + serial_priv = usb_get_serial_data(serial); - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + usb_free_urb(serial_priv->read_urb); + kfree(serial_priv); } static inline int calc_baud_divisor(int baudrate) @@ -466,21 +466,9 @@ static void qt2_close(struct usb_serial_port *port) static void qt2_disconnect(struct usb_serial *serial) { struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); - struct qt2_port_private *port_priv; - int i; if (serial_priv->read_urb->status == -EINPROGRESS) usb_kill_urb(serial_priv->read_urb); - - usb_free_urb(serial_priv->read_urb); - - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); - usb_free_urb(port_priv->write_urb); - } } static int get_serial_info(struct usb_serial_port *port, @@ -775,11 +763,9 @@ static void qt2_read_bulk_callback(struct urb *urb) static int qt2_setup_urbs(struct usb_serial *serial) { - struct usb_serial_port *port; struct usb_serial_port *port0; struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int pcount, status; + int status; port0 = serial->port[0]; @@ -797,30 +783,6 @@ static int qt2_setup_urbs(struct usb_serial *serial) sizeof(serial_priv->read_buffer), qt2_read_bulk_callback, serial); - /* setup write_urb for each port */ - for (pcount = 0; pcount < serial->num_ports; pcount++) { - - port = serial->port[pcount]; - port_priv = usb_get_serial_port_data(port); - - port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port_priv->write_urb) { - dev_err(&serial->dev->dev, - "failed to alloc write_urb for port %i\n", - pcount); - return -ENOMEM; - } - - usb_fill_bulk_urb(port_priv->write_urb, - serial->dev, - usb_sndbulkpipe(serial->dev, - port0-> - bulk_out_endpointAddress), - port_priv->write_buffer, - sizeof(port_priv->write_buffer), - qt2_write_bulk_callback, port); - } - status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL); if (status != 0) { dev_err(&serial->dev->dev, @@ -830,14 +792,12 @@ static int qt2_setup_urbs(struct usb_serial *serial) } return 0; - } static int qt2_attach(struct usb_serial *serial) { struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int status, pcount; + int status; /* power on unit */ status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -857,26 +817,6 @@ static int qt2_attach(struct usb_serial *serial) usb_set_serial_data(serial, serial_priv); - for (pcount = 0; pcount < serial->num_ports; pcount++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) { - dev_err(&serial->dev->dev, - "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*port_priv)); - pcount--; - status = -ENOMEM; - goto attach_failed; - } - - spin_lock_init(&port_priv->lock); - spin_lock_init(&port_priv->urb_lock); - init_waitqueue_head(&port_priv->delta_msr_wait); - - port_priv->port = serial->port[pcount]; - - usb_set_serial_port_data(serial->port[pcount], port_priv); - } - status = qt2_setup_urbs(serial); if (status != 0) goto attach_failed; @@ -884,14 +824,53 @@ static int qt2_attach(struct usb_serial *serial) return 0; attach_failed: - for (/* empty */; pcount >= 0; pcount--) { - port_priv = usb_get_serial_port_data(serial->port[pcount]); - kfree(port_priv); - } kfree(serial_priv); return status; } +static int qt2_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct qt2_port_private *port_priv; + u8 bEndpointAddress; + + port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); + if (!port_priv) + return -ENOMEM; + + spin_lock_init(&port_priv->lock); + spin_lock_init(&port_priv->urb_lock); + init_waitqueue_head(&port_priv->delta_msr_wait); + port_priv->port = port; + + port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port_priv->write_urb) { + kfree(port_priv); + return -ENOMEM; + } + bEndpointAddress = serial->port[0]->bulk_out_endpointAddress; + usb_fill_bulk_urb(port_priv->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, bEndpointAddress), + port_priv->write_buffer, + sizeof(port_priv->write_buffer), + qt2_write_bulk_callback, port); + + usb_set_serial_port_data(port, port_priv); + + return 0; +} + +static int qt2_port_remove(struct usb_serial_port *port) +{ + struct qt2_port_private *port_priv; + + port_priv = usb_get_serial_port_data(port); + usb_free_urb(port_priv->write_urb); + kfree(port_priv); + + return 0; +} + static int qt2_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -1130,6 +1109,8 @@ static struct usb_serial_driver qt2_device = { .attach = qt2_attach, .release = qt2_release, .disconnect = qt2_disconnect, + .port_probe = qt2_port_probe, + .port_remove = qt2_port_remove, .dtr_rts = qt2_dtr_rts, .break_ctl = qt2_break_ctl, .tiocmget = qt2_tiocmget, From f5c21b3815667aeae65a3ec56576294c5ed751e6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:09 +0200 Subject: [PATCH 0403/1071] USB: quatech2: fix close and disconnect urb handling commit 8e512ab0b675da20e023439a5811e3f2554e6852 upstream. Kill urbs unconditionally at close and disconnect. Note that URB status is not valid outside of completion handler. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index e87cd59daa0a57..e2c5b69c7eefdf 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -425,8 +425,7 @@ static void qt2_close(struct usb_serial_port *port) port_priv->is_open = false; spin_lock_irqsave(&port_priv->urb_lock, flags); - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); + usb_kill_urb(port_priv->write_urb); port_priv->urb_in_use = false; spin_unlock_irqrestore(&port_priv->urb_lock, flags); @@ -467,8 +466,7 @@ static void qt2_disconnect(struct usb_serial *serial) { struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); - if (serial_priv->read_urb->status == -EINPROGRESS) - usb_kill_urb(serial_priv->read_urb); + usb_kill_urb(serial_priv->read_urb); } static int get_serial_info(struct usb_serial_port *port, From 38e602db5db176e642d66ab7bffabec143edc2f3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:10 +0200 Subject: [PATCH 0404/1071] USB: quatech2: fix io after disconnect commit 2f0295adf6438188c4cd0868f2b1976a2b034e1d upstream. Make sure no control urb is submitted during close after a disconnect by checking the disconnected flag. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index e2c5b69c7eefdf..ea69301d89a214 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -429,6 +429,12 @@ static void qt2_close(struct usb_serial_port *port) port_priv->urb_in_use = false; spin_unlock_irqrestore(&port_priv->urb_lock, flags); + mutex_lock(&port->serial->disc_mutex); + if (port->serial->disconnected) { + mutex_unlock(&port->serial->disc_mutex); + return; + } + /* flush the port transmit buffer */ i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -460,6 +466,7 @@ static void qt2_close(struct usb_serial_port *port) dev_err(&port->dev, "%s - close port failed %i\n", __func__, i); + mutex_unlock(&port->serial->disc_mutex); } static void qt2_disconnect(struct usb_serial *serial) From 9fd041e480fa2da73eab4d4bbba1f5738b45dc8f Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Wed, 24 Oct 2012 10:23:09 -0400 Subject: [PATCH 0405/1071] USB: serial: Fix memory leak in sierra_release() commit f7bc5051667b74c3861f79eed98c60d5c3b883f7 upstream. I found a memory leak in sierra_release() (well sierra_probe() I guess) that looses 8 bytes each time the driver releases a device. Signed-off-by: Len Sorensen Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 0274710cced5ce..15e639b045f7e5 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -961,6 +961,7 @@ static void sierra_release(struct usb_serial *serial) continue; kfree(portdata); } + kfree(serial->private); } #ifdef CONFIG_PM From d9b48922b9d6dc1c02586d36639a27917f3dbe46 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:17 +0200 Subject: [PATCH 0406/1071] USB: sierra: fix memory leak in attach error path commit 7e41f9bcdd2e813ea2a3c40db291d87ea06b559f upstream. Make sure port private data is deallocated on errors in attach. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 15e639b045f7e5..b2f34a568e13b7 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -907,7 +907,7 @@ static int sierra_startup(struct usb_serial *serial) dev_dbg(&port->dev, "%s: kmalloc for " "sierra_port_private (%d) failed!\n", __func__, i); - return -ENOMEM; + goto err; } spin_lock_init(&portdata->lock); init_usb_anchor(&portdata->active); @@ -944,6 +944,13 @@ static int sierra_startup(struct usb_serial *serial) } return 0; +err: + for (--i; i >= 0; --i) { + portdata = usb_get_serial_port_data(serial->port[i]); + kfree(portdata); + } + + return -ENOMEM; } static void sierra_release(struct usb_serial *serial) From 99ad30180d1a0de0fbe4adfd8d24085ac77e1a24 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:18 +0200 Subject: [PATCH 0407/1071] USB: sierra: fix memory leak in probe error path commit 084817d79399ab5ccab2f90a148b0369912a8369 upstream. Move interface data allocation to attach so that it is deallocated on errors in usb-serial probe. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index b2f34a568e13b7..cd0331acc80dec 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -162,7 +162,6 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; @@ -189,11 +188,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -887,11 +881,20 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { struct usb_serial_port *port; + struct sierra_intf_private *intfdata; struct sierra_port_private *portdata; struct sierra_iface_info *himemoryp = NULL; int i; u8 ifnum; + intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + + spin_lock_init(&intfdata->susp_lock); + + usb_set_serial_data(serial, intfdata); + /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -949,6 +952,7 @@ static int sierra_startup(struct usb_serial *serial) portdata = usb_get_serial_port_data(serial->port[i]); kfree(portdata); } + kfree(intfdata); return -ENOMEM; } From 7e4d20169cdd2e9fb458d5d28b515397c112047f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:19 +0200 Subject: [PATCH 0408/1071] USB: sierra: fix port-data memory leak commit f525c05babc7938cc1d4236550fd8a659fb05960 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note also that urb-count for multi-port interfaces has not been changed even though the usb-serial port number is now determined from the port and interface minor numbers. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 125 +++++++++++++++++------------------- 1 file changed, 58 insertions(+), 67 deletions(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index cd0331acc80dec..cf6d149e392250 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -880,12 +880,7 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { - struct usb_serial_port *port; struct sierra_intf_private *intfdata; - struct sierra_port_private *portdata; - struct sierra_iface_info *himemoryp = NULL; - int i; - u8 ifnum; intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); if (!intfdata) @@ -902,77 +897,71 @@ static int sierra_startup(struct usb_serial *serial) if (nmea) sierra_vsc_set_nmea(serial->dev, 1); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for " - "sierra_port_private (%d) failed!\n", - __func__, i); - goto err; - } - spin_lock_init(&portdata->lock); - init_usb_anchor(&portdata->active); - init_usb_anchor(&portdata->delayed); - ifnum = i; - /* Assume low memory requirements */ - portdata->num_out_urbs = N_OUT_URB; - portdata->num_in_urbs = N_IN_URB; - - /* Determine actual memory requirements */ - if (serial->num_ports == 1) { - /* Get interface number for composite device */ - ifnum = sierra_calc_interface(serial); - himemoryp = - (struct sierra_iface_info *)&typeB_interface_list; - if (is_himemory(ifnum, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - else { - himemoryp = - (struct sierra_iface_info *)&typeA_interface_list; - if (is_himemory(i, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - dev_dbg(&serial->dev->dev, - "Memory usage (urbs) interface #%d, in=%d, out=%d\n", - ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); - /* Set the port private data pointer */ - usb_set_serial_port_data(port, portdata); + return 0; +} + +static void sierra_release(struct usb_serial *serial) +{ + struct sierra_intf_private *intfdata; + + intfdata = usb_get_serial_data(serial); + kfree(intfdata); +} + +static int sierra_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata; + const struct sierra_iface_info *himemoryp; + u8 ifnum; + + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; + + spin_lock_init(&portdata->lock); + init_usb_anchor(&portdata->active); + init_usb_anchor(&portdata->delayed); + + /* Assume low memory requirements */ + portdata->num_out_urbs = N_OUT_URB; + portdata->num_in_urbs = N_IN_URB; + + /* Determine actual memory requirements */ + if (serial->num_ports == 1) { + /* Get interface number for composite device */ + ifnum = sierra_calc_interface(serial); + himemoryp = &typeB_interface_list; + } else { + /* This is really the usb-serial port number of the interface + * rather than the interface number. + */ + ifnum = port->number - serial->minor; + himemoryp = &typeA_interface_list; } - return 0; -err: - for (--i; i >= 0; --i) { - portdata = usb_get_serial_port_data(serial->port[i]); - kfree(portdata); + if (is_himemory(ifnum, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; } - kfree(intfdata); - return -ENOMEM; + dev_dbg(&port->dev, + "Memory usage (urbs) interface #%d, in=%d, out=%d\n", + ifnum, portdata->num_in_urbs, portdata->num_out_urbs); + + usb_set_serial_port_data(port, portdata); + + return 0; } -static void sierra_release(struct usb_serial *serial) +static int sierra_port_remove(struct usb_serial_port *port) { - int i; - struct usb_serial_port *port; struct sierra_port_private *portdata; - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (!port) - continue; - portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - kfree(portdata); - } - kfree(serial->private); + portdata = usb_get_serial_port_data(port); + kfree(portdata); + + return 0; } #ifdef CONFIG_PM @@ -1076,6 +1065,8 @@ static struct usb_serial_driver sierra_device = { .tiocmset = sierra_tiocmset, .attach = sierra_startup, .release = sierra_release, + .port_probe = sierra_port_probe, + .port_remove = sierra_port_remove, .suspend = sierra_suspend, .resume = sierra_resume, .read_int_callback = sierra_instat_callback, From f36791258f9c7da44ba15aa64f3eb284b67b9939 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 13:35:09 +0200 Subject: [PATCH 0409/1071] USB: mos7840: fix urb leak at release commit 65a4cdbb170e4ec1a7fa0e94936d47e24a17b0e8 upstream. Make sure control urb is freed at release. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 2f6da1e89bfa56..23c06fd4a157ea 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2754,6 +2754,7 @@ static void mos7840_release(struct usb_serial *serial) del_timer_sync(&mos7840_port->led_timer1); del_timer_sync(&mos7840_port->led_timer2); } + usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port->ctrl_buf); kfree(mos7840_port->dr); kfree(mos7840_port); From da0d04fd143824b6d2657c267a8a09517194370b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 13:35:10 +0200 Subject: [PATCH 0410/1071] USB: mos7840: fix port-device leak in error path commit 3eb55cc4ed88eee3b5230f66abcdbd2a91639eda upstream. The driver set the usb-serial port pointers to NULL on errors in attach, effectively preventing usb-serial core from decrementing the port ref counters and releasing the port devices and associated data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 23c06fd4a157ea..bff3f8e87987ad 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2684,7 +2684,6 @@ static int mos7840_startup(struct usb_serial *serial) kfree(mos7840_port->ctrl_buf); usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port); - serial->port[i] = NULL; } return status; } From ee52fcd83c615252a8118e146f8db61358ecdb4b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:32 +0200 Subject: [PATCH 0411/1071] USB: mos7840: remove NULL-urb submission commit 28c3ae9a8cf45f439c9a0779ebd0256e2ae72813 upstream. The private int_urb is never allocated so the submission from the control completion handler will always fail. Remove this odd piece of broken code. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index bff3f8e87987ad..dd0ea789d875b2 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -218,7 +218,6 @@ struct moschip_port { int port_num; /*Actual port number in the device(1,2,etc) */ struct urb *write_urb; /* write URB for this port */ struct urb *read_urb; /* read URB for this port */ - struct urb *int_urb; __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ char open; @@ -493,7 +492,6 @@ static void mos7840_control_callback(struct urb *urb) unsigned char *data; struct moschip_port *mos7840_port; __u8 regval = 0x0; - int result = 0; int status = urb->status; mos7840_port = urb->context; @@ -512,7 +510,7 @@ static void mos7840_control_callback(struct urb *urb) default: dbg("%s - nonzero urb status received: %d", __func__, status); - goto exit; + return; } dbg("%s urb buffer size is %d", __func__, urb->actual_length); @@ -525,17 +523,6 @@ static void mos7840_control_callback(struct urb *urb) mos7840_handle_new_msr(mos7840_port, regval); else if (mos7840_port->MsrLsr == 1) mos7840_handle_new_lsr(mos7840_port, regval); - -exit: - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) - result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); - spin_unlock(&mos7840_port->pool_lock); - if (result) { - dev_err(&urb->dev->dev, - "%s - Error %d submitting interrupt urb\n", - __func__, result); - } } static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, From b0bda710d6b48cdc54b902f6bce3470b42cfab6b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:33 +0200 Subject: [PATCH 0412/1071] USB: mos7840: remove invalid disconnect handling commit e681b66f2e19fadbe8a7e2a17900978cb6bc921f upstream. Remove private zombie flag used to signal disconnect and to prevent control urb from being submitted from interrupt urb completion handler. The control urb will not be re-submitted as both the control urb and the interrupt urb is killed on disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index dd0ea789d875b2..52e5ca7e128476 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -222,7 +222,6 @@ struct moschip_port { __u8 shadowMCR; /* last MCR value received */ char open; char open_ports; - char zombie; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ int delta_msr_cond; @@ -691,14 +690,7 @@ static void mos7840_interrupt_callback(struct urb *urb) wreg = MODEM_STATUS_REGISTER; break; } - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) { - rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); - } else { - spin_unlock(&mos7840_port->pool_lock); - return; - } - spin_unlock(&mos7840_port->pool_lock); + rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); } } } @@ -2700,9 +2692,6 @@ static void mos7840_disconnect(struct usb_serial *serial) mos7840_port = mos7840_get_port_private(serial->port[i]); dbg ("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { - spin_lock_irqsave(&mos7840_port->pool_lock, flags); - mos7840_port->zombie = 1; - spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); usb_kill_urb(mos7840_port->control_urb); } } From de7dfdace5741d91cb273b29067ee22d125eab73 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 24 Oct 2012 20:37:51 +0200 Subject: [PATCH 0413/1071] vhost: fix mergeable bufs on BE hosts commit 910a578f7e9400a78a3b13aba0b4d2df16a2cb05 upstream. We copy head count to a 16 bit field, this works by chance on LE but on BE guest gets 0. Fix it up. Signed-off-by: Michael S. Tsirkin Tested-by: Alexander Graf Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/vhost/net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 072cbbadbc3683..7f93f34b7f913e 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *net) .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE }; size_t total_len = 0; - int err, headcount, mergeable; + int err, mergeable; + s16 headcount; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; /* TODO: check that we are running from vhost_worker? */ From 4ecc39f837ce9a302bd35dc35576514036bdca01 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 17 Oct 2012 16:47:11 +0900 Subject: [PATCH 0414/1071] ARM: SAMSUNG: Add naming of s3c64xx-spi devices commit 308b3afb97dc342e9c4f958d8b4c459ae0e22bd7 upstream. Commit a5238e360b71 (spi: s3c64xx: move controller information into driver data) introduced separate device names for the different subtypes of the spi controller but forgot to set these in the relevant machines. To fix this introduce a s3c64xx_spi_setname function and populate all Samsung arches with the correct names. The function resides in a new header, as the s3c64xx-spi.h contains driver platform data and should therefore at some later point move out of the Samsung include dir. Tested on a s3c2416-based machine. Signed-off-by: Heiko Stuebner Reviewed-by: Sylwester Nawrocki [s.nawrocki@samsung.com: tested on mach-exynos] Tested-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-exynos/common.c | 5 ++++ arch/arm/mach-s3c24xx/s3c2416.c | 2 ++ arch/arm/mach-s3c24xx/s3c2443.c | 4 +++ arch/arm/mach-s5p64x0/common.c | 3 ++ arch/arm/mach-s5pc100/common.c | 3 ++ arch/arm/mach-s5pv210/common.c | 3 ++ arch/arm/plat-samsung/include/plat/spi-core.h | 30 +++++++++++++++++++ 7 files changed, 50 insertions(+) create mode 100644 arch/arm/plat-samsung/include/plat/spi-core.h diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 4eb39cdf75eab7..3e02ae6b303fe4 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include "common.h" @@ -346,6 +347,8 @@ static void __init exynos4_map_io(void) s5p_fb_setname(0, "exynos4-fb"); s5p_hdmi_setname("exynos4-hdmi"); + + s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos5_map_io(void) @@ -366,6 +369,8 @@ static void __init exynos5_map_io(void) s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); s3c_i2c2_setname("s3c2440-i2c"); + + s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos4_init_clocks(int xtal) diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index ed5a95ece9eb2d..77ee0b732237d9 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c @@ -61,6 +61,7 @@ #include #include #include +#include static struct map_desc s3c2416_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -132,6 +133,7 @@ void __init s3c2416_map_io(void) /* initialize device information early */ s3c2416_default_sdhci0(); s3c2416_default_sdhci1(); + s3c64xx_spi_setname("s3c2443-spi"); iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc)); } diff --git a/arch/arm/mach-s3c24xx/s3c2443.c b/arch/arm/mach-s3c24xx/s3c2443.c index ab648ad8fa5086..165b6a6b3daaa9 100644 --- a/arch/arm/mach-s3c24xx/s3c2443.c +++ b/arch/arm/mach-s3c24xx/s3c2443.c @@ -43,6 +43,7 @@ #include #include #include +#include static struct map_desc s3c2443_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -100,6 +101,9 @@ void __init s3c2443_map_io(void) s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull; s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull; + /* initialize device information early */ + s3c64xx_spi_setname("s3c2443-spi"); + iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc)); } diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c index 6e6a0a9d6778b0..111e404a81fd44 100644 --- a/arch/arm/mach-s5p64x0/common.c +++ b/arch/arm/mach-s5p64x0/common.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -179,6 +180,7 @@ void __init s5p6440_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); @@ -193,6 +195,7 @@ void __init s5p6450_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c index 62190865886159..cc6e561c995884 100644 --- a/arch/arm/mach-s5pc100/common.c +++ b/arch/arm/mach-s5pc100/common.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,8 @@ void __init s5pc100_map_io(void) s3c_onenand_setname("s5pc100-onenand"); s3c_fb_setname("s5pc100-fb"); s3c_cfcon_setname("s5pc100-pata"); + + s3c64xx_spi_setname("s5pc100-spi"); } void __init s5pc100_init_clocks(int xtal) diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c index 4c9e9027df9aed..a0c50efe8145f1 100644 --- a/arch/arm/mach-s5pv210/common.c +++ b/arch/arm/mach-s5pv210/common.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "common.h" @@ -196,6 +197,8 @@ void __init s5pv210_map_io(void) /* setup TV devices */ s5p_hdmi_setname("s5pv210-hdmi"); + + s3c64xx_spi_setname("s5pv210-spi"); } void __init s5pv210_init_clocks(int xtal) diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h new file mode 100644 index 00000000000000..0b9428ab3fc3d0 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/spi-core.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Heiko Stuebner + * + * 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 __PLAT_S3C_SPI_CORE_H +#define __PLAT_S3C_SPI_CORE_H + +/* These functions are only for use with the core support code, such as + * the cpu specific initialisation code + */ + +/* re-define device name depending on support. */ +static inline void s3c64xx_spi_setname(char *name) +{ +#ifdef CONFIG_S3C64XX_DEV_SPI0 + s3c64xx_device_spi0.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI1 + s3c64xx_device_spi1.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI2 + s3c64xx_device_spi2.name = name; +#endif +} + +#endif /* __PLAT_S3C_SPI_CORE_H */ From 9e9226a021af38ede5823b0610359dd817f35aa3 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Fri, 14 Sep 2012 17:01:29 +0800 Subject: [PATCH 0415/1071] ARM: at91/tc: fix typo in the DT document commit 11930c530f3edf81160e4962e363d579f5cdce7e upstream. Signed-off-by: Josh Wu Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/arm/atmel-at91.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index ecc81e36871536..d187e9f7cf1cf8 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -8,7 +8,7 @@ PIT Timer required properties: shared across all System Controller members. TC/TCLIB Timer required properties: -- compatible: Should be "atmel,-pit". +- compatible: Should be "atmel,-tcb". can be "at91rm9200" or "at91sam9x5" - reg: Should contain registers location and length - interrupts: Should contain all interrupts for the TC block From e5c182965ed38c70f0e99574041898c1f5a14c45 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 15 Oct 2012 17:30:27 +0800 Subject: [PATCH 0416/1071] ARM: at91/i2c: change id to let i2c-gpio work commit 7840487cd6298f9f931103b558290d8d98d41c49 upstream. The i2c core driver will turn the platform device ID to busnum When using platfrom device ID as -1, it means dynamically assigned the busnum. When writing code, we need to make sure the busnum, and call i2c_register_board_info(int busnum, ...) to register device if using -1, we do not know the value of busnum In order to solve this issue, set the platform device ID as a fix number Here using 0 to match the busnum used in i2c_regsiter_board_info() Signed-off-by: Bo Shen Acked-by: Jean Delvare Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Ludovic Desroches Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/at91rm9200_devices.c | 2 +- arch/arm/mach-at91/at91sam9260_devices.c | 2 +- arch/arm/mach-at91/at91sam9261_devices.c | 2 +- arch/arm/mach-at91/at91sam9263_devices.c | 2 +- arch/arm/mach-at91/at91sam9rl_devices.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 01fb7325fecce0..d5a49132ef633e 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -463,7 +463,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91rm9200_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index bce572a530ef2c..18ca240537e131 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -471,7 +471,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9260_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index bc2590d712d06b..2495de8c32bf69 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9261_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 9b6ca734f1a96e..9877963c29e77c 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -542,7 +542,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9263_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index b3d365dadef597..c82a4276b1d5ac 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9rl_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; From 60b84696738cc3fb760c26f2569c53d0d1fb0c7d Mon Sep 17 00:00:00 2001 From: Ivan Shugov Date: Wed, 24 Oct 2012 11:02:44 +0200 Subject: [PATCH 0417/1071] ARM: at91: at91sam9g10: fix SOC type detection commit 3d9a0183dd3423353e9e363bcc261c1220d05f9f upstream. Newer at91sam9g10 SoC revision can't be detected, so the kernel can't boot with this kind of kernel panic: "AT91: Impossible to detect the SOC type" CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 CPU: VIVT data cache, VIVT instruction cache Machine: Atmel AT91SAM9G10-EK Ignoring tag cmdline (using the default kernel command line) bootconsole [earlycon0] enabled Memory policy: ECC disabled, Data cache writeback Kernel panic - not syncing: AT91: Impossible to detect the SOC type [] (unwind_backtrace+0x0/0xe0) from [] (panic+0x78/0x1cc) [] (panic+0x78/0x1cc) from [] (at91_map_io+0x90/0xc8) [] (at91_map_io+0x90/0xc8) from [] (paging_init+0x564/0x6d0) [] (paging_init+0x564/0x6d0) from [] (setup_arch+0x464/0x704) [] (setup_arch+0x464/0x704) from [] (start_kernel+0x6c/0x2d4) [] (start_kernel+0x6c/0x2d4) from [<20008040>] (0x20008040) The reason for this is that the Debug Unit Chip ID Register has changed between Engineering Sample and definitive revision of the SoC. Changing the check of cidr to socid will address the problem. We do not integrate this check to the list just above because we also have to make sure that the extended id is disregarded. Signed-off-by: Ivan Shugov [nicolas.ferre@atmel.com: change commit message] Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 944bffb0899136..31bb13dd4a90d8 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_base) } /* at91sam9g10 */ - if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { + if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { at91_soc_initdata.type = AT91_SOC_SAM9G10; at91_boot_soc = at91sam9261_soc; } From a009557c905f624b230c0d6f70cf41f3d9f5bd91 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 24 Oct 2012 16:09:57 +0200 Subject: [PATCH 0418/1071] ARM: at91: fix external interrupts in non-DT case commit 738a0fd752dc60e20beeda6f2f0f62e58dc0e344 upstream. Management of external interrupts has changed but the non-DT code has not integrated these changes. Add a mask to pass external irq specification from SoC specific code to the at91_aic_init() function. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Ludovic Desroches Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/generic.h | 3 ++- arch/arm/mach-at91/irq.c | 9 +++++++-- arch/arm/mach-at91/setup.c | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index f49650677653a0..b62f560e6c75fb 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(void); extern void __init at91_init_irq_default(void); extern void __init at91_init_interrupts(unsigned int priority[]); extern void __init at91x40_init_interrupts(unsigned int priority[]); -extern void __init at91_aic_init(unsigned int priority[]); +extern void __init at91_aic_init(unsigned int priority[], + unsigned int ext_irq_mask); extern int __init at91_aic_of_init(struct device_node *node, struct device_node *parent); extern int __init at91_aic5_of_init(struct device_node *node, diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c index 1e02c0e49dccb7..febc2ee901a544 100644 --- a/arch/arm/mach-at91/irq.c +++ b/arch/arm/mach-at91/irq.c @@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node, /* * Initialize the AIC interrupt controller. */ -void __init at91_aic_init(unsigned int *priority) +void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask) { unsigned int i; int irq_base; - if (at91_aic_pm_init()) + at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs) + * sizeof(*at91_extern_irq), GFP_KERNEL); + + if (at91_aic_pm_init() || at91_extern_irq == NULL) panic("Unable to allocate bit maps\n"); + *at91_extern_irq = ext_irq_mask; + at91_aic_base = ioremap(AT91_AIC, 512); if (!at91_aic_base) panic("Unable to ioremap AIC registers\n"); diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 31bb13dd4a90d8..bd0e88cd3807d4 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -47,7 +47,7 @@ void __init at91_init_irq_default(void) void __init at91_init_interrupts(unsigned int *priority) { /* Initialize the AIC interrupt controller */ - at91_aic_init(priority); + at91_aic_init(priority, at91_extern_irq); /* Enable GPIO interrupts */ at91_gpio_irq_setup(); From c5bb11c743f93a487b2e5806ede0cb14ca92c873 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 24 Oct 2012 16:19:47 +0200 Subject: [PATCH 0419/1071] ARM: at91: fix external interrupt specification in board code commit 69e7ea04c9365626c0963ff09bbaa3a1b49e293a upstream. Since the switch to sparse irq, we have to add the NR_IRQS_LEGACY offset to static irq numbers. It has been forgotten on these SPI irq definitions in board code. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Ludovic Desroches Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/board-neocore926.c | 2 +- arch/arm/mach-at91/board-sam9261ek.c | 2 +- arch/arm/mach-at91/board-sam9263ek.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c index 18103c5d993ce2..997d35914e7716 100644 --- a/arch/arm/mach-at91/board-neocore926.c +++ b/arch/arm/mach-at91/board-neocore926.c @@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = { .max_speed_hz = 125000 * 16, .bus_num = 0, .platform_data = &ads_info, - .irq = AT91SAM9263_ID_IRQ1, + .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1, }, #endif }; diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 2269be5fa38410..17659bedf695be 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = { .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */ .bus_num = 0, .platform_data = &ads_info, - .irq = AT91SAM9261_ID_IRQ0, + .irq = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0, .controller_data = (void *) AT91_PIN_PA28, /* CS pin */ }, #endif diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 82adf581afc2eb..9e7153be454b6e 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = { .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */ .bus_num = 0, .platform_data = &ads_info, - .irq = AT91SAM9263_ID_IRQ1, + .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1, }, #endif }; From a52e181f56c22cd26444e61c0ac87222bd187564 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 1 Oct 2012 15:52:00 +0200 Subject: [PATCH 0420/1071] mac80211: connect with HT20 if HT40 is not permitted commit 3a40414f826a8f1096d9b94c4a53ef91b25ba28d upstream. Some changes to fix issues with HT40 APs in Korea and follow-up changes to allow using HT40 even if the local regulatory database disallows it caused issues with iwlwifi (and could cause issues with other devices); iwlwifi firmware would assert if you tried to connect to an AP that has an invalid configuration (e.g. using HT40- on channel 140.) Fix this, while avoiding the "Korean AP" issue by disabling HT40 and advertising HT20 to the AP when connecting. Reported-by: Florian Reitmeir Tested-by: Florian Reitmeir Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mlme.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f76b83341cf9a3..9f5f9a4365492f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3065,22 +3065,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, ht_cfreq, ht_oper->primary_chan, cbss->channel->band); ht_oper = NULL; + } else { + channel_type = NL80211_CHAN_HT20; } } - if (ht_oper) { - channel_type = NL80211_CHAN_HT20; + if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + /* + * cfg80211 already verified that the channel itself can + * be used, but it didn't check that we can do the right + * HT type, so do that here as well. If HT40 isn't allowed + * on this channel, disable 40 MHz operation. + */ - if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - switch (ht_oper->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else channel_type = NL80211_CHAN_HT40MINUS; - break; - } + break; } } From 8f645c50b625f912ee7e62687cd88c468f92ac64 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 2 Oct 2012 21:34:23 +0200 Subject: [PATCH 0421/1071] mac80211: check if key has TKIP type before updating IV commit 4045f72bcf3c293c7c5932ef001742d8bb5ded76 upstream. This patch fix corruption which can manifest itself by following crash when switching on rfkill switch with rt2x00 driver: https://bugzilla.redhat.com/attachment.cgi?id=615362 Pointer key->u.ccmp.tfm of group key get corrupted in: ieee80211_rx_h_michael_mic_verify(): /* update IV in key information to be able to detect replays */ rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32; rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16; because rt2x00 always set RX_FLAG_MMIC_STRIPPED, even if key is not TKIP. We already check type of the key in different path in ieee80211_rx_h_michael_mic_verify() function, so adding additional check here is reasonable. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/wpa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bdb53aba888e14..e72562a18bad0f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && + rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) goto update_iv; return RX_CONTINUE; From cbc71967da7f3643d668a28b26d830e672891ab0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 10 Oct 2012 22:40:23 +0200 Subject: [PATCH 0422/1071] mac80211: use ieee80211_free_txskb in a few more places commit d4fa14cd62bd078c8e3ef39283b9f237e5b2ff0f upstream. Free tx status skbs when draining power save buffers, pending frames, or when tearing down a vif. Fixes remaining conditions that can lead to hostapd/wpa_supplicant hangs when running out of socket write memory. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/iface.c | 2 +- net/mac80211/sta_info.c | 4 ++-- net/mac80211/util.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index bfb57dcc15381a..c93d3953623307 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -822,7 +822,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (info->control.vif == &sdata->vif) { __skb_unlink(skb, &local->pending[i]); - dev_kfree_skb_irq(skb); + ieee80211_free_txskb(&local->hw, skb); } } } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 06fa75ceb0251e..63882b991d3ade 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -585,7 +585,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, */ if (!skb) break; - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); } /* @@ -614,7 +614,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, local->total_ps_buffered--; ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", sta->sta.addr); - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); } /* diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 39b82fee490478..c9b52f7cb396d2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -400,7 +400,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, int queue = info->hw_queue; if (WARN_ON(!info->control.vif)) { - kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); return; } @@ -425,7 +425,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (WARN_ON(!info->control.vif)) { - kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); continue; } From 4ade7d2eedda437e2197b57e449a308e06f9bb4d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 24 Oct 2012 08:57:16 -0500 Subject: [PATCH 0423/1071] b43: Fix oops on unload when firmware not found commit f89ff6441df06abc2d95f3ef67525923032d6283 upstream. When b43 fails to find firmware when loaded, a subsequent unload will oops due to calling ieee80211_unregister_hw() when the corresponding register call was never made. Commit 2d838bb608e2d1f6cb4280e76748cb812dc822e7 fixed the same problem for b43legacy. Signed-off-by: Larry Finger Tested-by: Markus Kanet Cc: Markus Kanet Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a140165dfee051..46d9d4e513aa31 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5374,6 +5374,8 @@ static void b43_bcma_remove(struct bcma_device *core) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); @@ -5448,6 +5450,8 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); From 8668be75982558ff50873ec256abdc881a1d25ba Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 25 Oct 2012 07:25:20 +0000 Subject: [PATCH 0424/1071] tilegx: fix some issues in the SW TSO support commit 3da3fff8006c608f19a51859d44ba47ca8b41461 upstream. This change correctly computes the header length and data length in the fragments to avoid a bug where we would end up with extremely slow performance. Also adopt use of skb_frag_size() accessor. Signed-off-by: Chris Metcalf Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/tile/tilegx.c | 35 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 4e2a1628484dfb..4e9810013850ca 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb) { struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned int p_len = sh->gso_size; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int num_edescs = 0; int segment; @@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb) /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; + f_size = skb_frag_size(&sh->frags[f_id]); f_used = 0; } @@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, struct iphdr *ih; struct tcphdr *th; unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned char *data = skb->data; unsigned int ih_off, th_off, p_len; unsigned int isum_seed, tsum_seed, id, seq; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int segment; @@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, isum_seed = ((0xFFFF - ih->check) + (0xFFFF - ih->tot_len) + (0xFFFF - ih->id)); - tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len)); + tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); id = ntohs(ih->id); seq = ntohl(th->seq); @@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; + f_size = skb_frag_size(&sh->frags[f_id]); f_used = 0; } @@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, struct tile_net_priv *priv = netdev_priv(dev); struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned int p_len = sh->gso_size; gxio_mpipe_edesc_t edesc_head = { { 0 } }; gxio_mpipe_edesc_t edesc_body = { { 0 } }; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ - void *f_data = skb->data; + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ + void *f_data = skb->data + sh_len; long n; /* size of the current piece of payload */ unsigned long tx_packets = 0, tx_bytes = 0; unsigned int csum_start; @@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, /* Egress the payload. */ while (p_used < p_len) { + void *va; /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; + f_size = skb_frag_size(&sh->frags[f_id]); f_data = tile_net_frag_buf(&sh->frags[f_id]); + f_used = 0; } + va = f_data + f_used; + /* Use bytes from the current fragment. */ n = p_len - p_used; if (n > f_size - f_used) @@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, p_used += n; /* Egress a piece of the payload. */ - edesc_body.va = va_to_tile_io_addr(f_data) + f_used; + edesc_body.va = va_to_tile_io_addr(va); edesc_body.xfer_size = n; edesc_body.bound = !(p_used < p_len); gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); From 7450d9b70adc4249cfb5575b35ccb11f4b58fd1f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 11 Oct 2012 16:26:06 +0200 Subject: [PATCH 0425/1071] Bluetooth: SMP: Fix setting unknown auth_req bits commit 065a13e2cc665f6547dc7e8a9d6b6565badf940a upstream. When sending a pairing request or response we should not just blindly copy the value that the remote device sent. Instead we should at least make sure to mask out any unknown bits. This is particularly critical from the upcoming LE Secure Connections feature perspective as incorrectly indicating support for it (by copying the remote value) would cause a failure to pair with devices that support it. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/smp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8c225ef349cd73..2ac8d50861e081 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -32,6 +32,8 @@ #define SMP_TIMEOUT msecs_to_jiffies(30000) +#define AUTH_REQ_MASK 0x07 + static inline void swap128(u8 src[16], u8 dst[16]) { int i; @@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, req->max_key_size = SMP_MAX_ENC_KEY_SIZE; req->init_key_dist = 0; req->resp_key_dist = dist_keys; - req->auth_req = authreq; + req->auth_req = (authreq & AUTH_REQ_MASK); return; } @@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; rsp->init_key_dist = 0; rsp->resp_key_dist = req->resp_key_dist & dist_keys; - rsp->auth_req = authreq; + rsp->auth_req = (authreq & AUTH_REQ_MASK); } static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) From 577269ce50791085217d945d2ce5ae4b6903f3b9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 24 Oct 2012 12:10:34 +0000 Subject: [PATCH 0426/1071] qmi_wwan/cdc_ether: move Novatel 551 and E362 to qmi_wwan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f8295ec22cb0f1ee6849b862addbfa3ea9320755 upstream. These devices provide QMI and ethernet functionality via a standard CDC ethernet descriptor. But when driven by cdc_ether, the QMI functionality is unavailable because only cdc_ether can claim the USB interface. Thus blacklist the devices in cdc_ether and add their IDs to qmi_wwan, which enables both QMI and ethernet simultaneously. Signed-off-by: Dan Williams Acked-by: Greg Kroah-Hartman Acked-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/cdc_ether.c | 41 +++++++++++++++++++++++-------------- drivers/net/usb/qmi_wwan.c | 14 +++++++++++++ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index a03de71970499b..d0129827602b28 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -592,6 +592,32 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, +/* Novatel USB551L and MC551 - handled by qmi_wwan */ +{ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0xB001, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = 0, +}, + +/* Novatel E362 - handled by qmi_wwan */ +{ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0x9010, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = 0, +}, + /* * WHITELIST!!! * @@ -604,21 +630,6 @@ static const struct usb_device_id products [] = { * because of bugs/quirks in a given product (like Zaurus, above). */ { - /* Novatel USB551L */ - /* This match must come *before* the generic CDC-ETHER match so that - * we get FLAG_WWAN set on the device, since it's descriptors are - * generic CDC-ETHER. - */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = NOVATEL_VENDOR_ID, - .idProduct = 0xB001, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .driver_info = (unsigned long)&wwan_info, -}, { /* ZTE (Vodafone) K3805-Z */ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 3543c9e578247e..3585f936c6e44b 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -364,6 +364,20 @@ static const struct usb_device_id products[] = { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), .driver_info = (unsigned long)&qmi_wwan_info, }, + { /* Novatel USB551L and MC551 */ + USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&qmi_wwan_info, + }, + { /* Novatel E362 */ + USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&qmi_wwan_info, + }, /* 2. Combined interface devices matching on class+protocol */ { /* Huawei E367 and possibly others in "Windows mode" */ From cae2c0464b08ffc8b5632cc56049ae7d2b80506f Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 25 Oct 2012 22:28:12 +0200 Subject: [PATCH 0427/1071] freezer: exec should clear PF_NOFREEZE along with PF_KTHREAD commit b40a79591ca918e7b91b0d9b6abd5d00f2e88c19 upstream. flush_old_exec() clears PF_KTHREAD but forgets about PF_NOFREEZE. Signed-off-by: Oleg Nesterov Acked-by: Tejun Heo Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/exec.c b/fs/exec.c index 574cf4de4ec38b..fab2c6debb0c4e 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1110,7 +1110,8 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ set_fs(USER_DS); - current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD); + current->flags &= + ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); flush_thread(); current->personality &= ~bprm->per_clear; From 4853c29c3cd5e7d5ea41bc5edd50e16b1882c294 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 27 Sep 2012 16:35:38 +0800 Subject: [PATCH 0428/1071] dmaengine: sirf: fix a typo in dma_prep_interleaved commit 5997e089e4c3a7f0958a8fb0a54ec2b5a6f06168 upstream. either DEV_TO_MEM or MEM_TO_DEV is supported, so change OR to AND. Signed-off-by: Barry Song Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/sirf-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 434ad31174f289..35a329da97fdf8 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( unsigned long iflags; int ret; - if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { + if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) { ret = -EINVAL; goto err_dir; } From 7a263f0c7f4acdb1b58cf0e59e6a941b819bd550 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 27 Sep 2012 16:36:10 +0800 Subject: [PATCH 0429/1071] dmaengine: sirf: fix a typo in moving running dma_desc to active queue commit 26fd12209c08fe947be1828896ef4ffc5bd0e6df upstream. list_move_tail(&schan->queued, &schan->active) makes the list_empty(schan->queued) undefined, we either should change it to: list_move_tail(schan->queued.next, &schan->active) or list_move_tail(&sdesc->node, &schan->active) Signed-off-by: Barry Song Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/sirf-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 35a329da97fdf8..c4394892edab30 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, node); /* Move the first queued descriptor to active list */ - list_move_tail(&schan->queued, &schan->active); + list_move_tail(&sdesc->node, &schan->active); /* Start the DMA transfer */ writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + From fbec5144b1a52c0d81db87626e802a64fd5a9a24 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 21 Oct 2012 19:58:30 +0800 Subject: [PATCH 0430/1071] dmaengine: imx-dma: fix missing unlock on error in imxdma_xfer_desc() commit 720dfd250e48a8c7fd1b2b8645955413989c4ee0 upstream. Add the missing unlock on the error handling path in function imxdma_xfer_desc(). Signed-off-by: Wei Yongjun Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/imx-dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 5084975d793cd2..8aa91132e9ab08 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) + if (slot < 0) { + spin_unlock_irqrestore(&imxdma->lock, flags); return -EBUSY; + } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; From 44d127e0dd6e8eec8f351b766fa57ed69e18ea19 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 25 Sep 2012 16:40:12 +0200 Subject: [PATCH 0431/1071] iwlwifi: fix 6000 series channel switch command commit 8f7b8db6e0557c8437adf9371e020cd89a7e85dc upstream. The channel switch command for 6000 series devices is larger than the maximum inline command size of 320 bytes. The command is therefore refused with a warning. Fix this by allocating the command and using the NOCOPY mechanism. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/dvm/devices.c | 39 +++++++++++++--------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 349c205d5f62e2..da586206419515 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, * See iwlagn_mac_channel_switch. */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd cmd; + struct iwl6000_channel_switch_cmd *cmd; u32 switch_time_in_usec, ucode_switch_time; u16 ch; u32 tsf_low; @@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(cmd), }, + .len = { sizeof(*cmd), }, .flags = CMD_SYNC, - .data = { &cmd, }, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, }; + int err; - cmd.band = priv->band == IEEE80211_BAND_2GHZ; + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + hcmd.data[0] = cmd; + + cmd->band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", ctx->active.channel, ch); - cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = ctx->staging.flags; - cmd.rxon_filter_flags = ctx->staging.filter_flags; + cmd->channel = cpu_to_le16(ch); + cmd->rxon_flags = ctx->staging.flags; + cmd->rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, switch_count = 0; } if (switch_count <= 1) - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); else { switch_time_in_usec = vif->bss_conf.beacon_int * switch_count * TIME_UNIT; ucode_switch_time = iwl_usecs_to_beacons(priv, switch_time_in_usec, beacon_interval); - cmd.switch_time = iwl_add_beacon_time(priv, - priv->ucode_beacon_time, - ucode_switch_time, - beacon_interval); + cmd->switch_time = iwl_add_beacon_time(priv, + priv->ucode_beacon_time, + ucode_switch_time, + beacon_interval); } IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", - cmd.switch_time); - cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; + cmd->switch_time); + cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; - return iwl_dvm_send_cmd(priv, &hcmd); + err = iwl_dvm_send_cmd(priv, &hcmd); + kfree(cmd); + return err; } struct iwl_lib_ops iwl6000_lib = { From 3814f2b04c026fb39dda34ad7184ab6796f97271 Mon Sep 17 00:00:00 2001 From: Piotr Haber Date: Thu, 11 Oct 2012 14:05:15 +0200 Subject: [PATCH 0432/1071] bcma: fix unregistration of cores commit 1fffa905adffbf0d3767fc978ef09afb830275eb upstream. When cores are unregistered, entries need to be removed from cores list in a safe manner. Reported-by: Stanislaw Gruszka Reviewed-by: Arend Van Spriel Signed-off-by: Piotr Haber Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/bcma/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 758af9ccdef0fa..0059e267cfe999 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -141,9 +141,10 @@ static int bcma_register_cores(struct bcma_bus *bus) static void bcma_unregister_cores(struct bcma_bus *bus) { - struct bcma_device *core; + struct bcma_device *core, *tmp; - list_for_each_entry(core, &bus->cores, list) { + list_for_each_entry_safe(core, tmp, &bus->cores, list) { + list_del(&core->list); if (core->dev_registered) device_unregister(&core->dev); } From ceb80aec3793b4e34b84849c2823d052c91a855b Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Mon, 15 Oct 2012 14:14:32 +0000 Subject: [PATCH 0433/1071] net/wireless: ipw2200: Fix panic occurring in ipw_handle_promiscuous_tx() commit bf11315eeda510ea4fc1a2bf972d8155d31d89b4 upstream. The driver does not count space of radiotap fields when allocating skb for radiotap packet. This leads to kernel panic with the following call trace: ... [67607.676067] [] error_code+0x67/0x6c [67607.676067] [] ? skb_put+0x91/0xa0 [67607.676067] [] ? ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200] [67607.676067] [] ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200] [67607.676067] [] ipw_net_hard_start_xmit+0x8b/0x90 [ipw2200] [67607.676067] [] libipw_xmit+0x55a/0x980 [libipw] [67607.676067] [] dev_hard_start_xmit+0x218/0x4d0 ... This bug was found by VittGam. https://bugzilla.kernel.org/show_bug.cgi?id=43255 Signed-off-by: Stanislav Yakovlev Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ipw2x00/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 0df45914739489..6d1754a4bc142c 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10479,7 +10479,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, } else len = src->len; - dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); + dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC); if (!dst) continue; From b1a9fec89349d9c41ff1ab519d4bfe2bb16814b8 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 23 Oct 2012 00:55:10 +0200 Subject: [PATCH 0434/1071] cpufreq / powernow-k8: Remove usage of smp_processor_id() in preemptible code commit e4df1cbcc1f329e53a1fff7450b2229e0addff20 upstream. Commit 6889125b8b4e09c5e53e6ecab3433bed1ce198c9 (cpufreq/powernow-k8: workqueue user shouldn't migrate the kworker to another CPU) causes powernow-k8 to trigger a preempt warning, e.g.: BUG: using smp_processor_id() in preemptible [00000000] code: cpufreq/3776 caller is powernowk8_target+0x20/0x49 Pid: 3776, comm: cpufreq Not tainted 3.6.0 #9 Call Trace: [] debug_smp_processor_id+0xc7/0xe0 [] powernowk8_target+0x20/0x49 [] __cpufreq_driver_target+0x82/0x8a [] cpufreq_governor_performance+0x4e/0x54 [] __cpufreq_governor+0x8c/0xc9 [] __cpufreq_set_policy+0x1a9/0x21e [] store_scaling_governor+0x16f/0x19b [] ? cpufreq_update_policy+0x124/0x124 [] ? _raw_spin_unlock_irqrestore+0x2c/0x49 [] store+0x60/0x88 [] sysfs_write_file+0xf4/0x130 [] vfs_write+0xb5/0x151 [] sys_write+0x4a/0x71 [] system_call_fastpath+0x16/0x1b Fix this by by always using work_on_cpu(). Signed-off-by: Andreas Herrmann Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/powernow-k8.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 1a40935c85fdcc..c671369a05bf45 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1223,14 +1223,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, .relation = relation }; - /* - * Must run on @pol->cpu. cpufreq core is responsible for ensuring - * that we're bound to the current CPU and pol->cpu stays online. - */ - if (smp_processor_id() == pol->cpu) - return powernowk8_target_fn(&pta); - else - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); + return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } /* Driver entry point to verify the policy and range of frequencies */ From 4ae29d121ef48cc7f3798e69bfde93742d83c760 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 17 Oct 2012 13:50:43 +0200 Subject: [PATCH 0435/1071] Revert "ath9k_hw: Updated AR9003 tx gain table for 5GHz" commit 73b26df5fa1a6245d6fc982362518b620bc7c2fe upstream. This reverts commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd. This commit is reducing tx power by at least 10 db on some devices, e.g. the Buffalo WZR-HP-G450H. Signed-off-by: Felix Fietkau Cc: rmanohar@qca.qualcomm.com Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- .../wireless/ath/ath9k/ar9003_2p2_initvals.h | 164 +++++++++--------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 89bf94d4d8a1e1..6f7cf49eff4d0d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, - {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, - {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, - {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, - {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, - {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, - {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, - {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, - {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, - {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, + {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, + {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; From 68386f3af67948d54f423c54a4384080e6b74810 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Wed, 24 Oct 2012 14:24:44 -0500 Subject: [PATCH 0436/1071] x86, mm: Find_early_table_space based on ranges that are actually being mapped commit 844ab6f993b1d32eb40512503d35ff6ad0c57030 upstream. Current logic finds enough space for direct mapping page tables from 0 to end. Instead, we only need to find enough space to cover mr[0].start to mr[nr_range].end -- the range that is actually being mapped by init_memory_mapping() This is needed after 1bbbbe779aabe1f0768c2bf8f8c0a5583679b54a, to address the panic reported here: https://lkml.org/lkml/2012/10/20/160 https://lkml.org/lkml/2012/10/21/157 Signed-off-by: Jacob Shin Link: http://lkml.kernel.org/r/20121024195311.GB11779@jshin-Toonie Tested-by: Tom Rini Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/init.c | 70 +++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 8653b3a722be2d..bc287d62bf1eeb 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -29,36 +29,54 @@ int direct_gbpages #endif ; -static void __init find_early_table_space(unsigned long end, int use_pse, - int use_gbpages) +struct map_range { + unsigned long start; + unsigned long end; + unsigned page_size_mask; +}; + +/* + * First calculate space needed for kernel direct mapping page tables to cover + * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB + * pages. Then find enough contiguous space for those page tables. + */ +static void __init find_early_table_space(struct map_range *mr, int nr_range) { - unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; + int i; + unsigned long puds = 0, pmds = 0, ptes = 0, tables; + unsigned long start = 0, good_end; phys_addr_t base; - puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); + for (i = 0; i < nr_range; i++) { + unsigned long range, extra; - if (use_gbpages) { - unsigned long extra; + range = mr[i].end - mr[i].start; + puds += (range + PUD_SIZE - 1) >> PUD_SHIFT; - extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); - pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; - } else - pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - - tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); + if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) { + extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT); + pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT; + } else { + pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT; + } - if (use_pse) { - unsigned long extra; - - extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); + if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) { + extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT); #ifdef CONFIG_X86_32 - extra += PMD_SIZE; + extra += PMD_SIZE; #endif - ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; - } else - ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; + /* The first 2/4M doesn't use large pages. */ + if (mr[i].start < PMD_SIZE) + extra += range; + + ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; + } else { + ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; + } + } + tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); + tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); #ifdef CONFIG_X86_32 @@ -76,7 +94,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse, pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT); printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n", - end - 1, pgt_buf_start << PAGE_SHIFT, + mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT, (pgt_buf_top << PAGE_SHIFT) - 1); } @@ -85,12 +103,6 @@ void __init native_pagetable_reserve(u64 start, u64 end) memblock_reserve(start, end - start); } -struct map_range { - unsigned long start; - unsigned long end; - unsigned page_size_mask; -}; - #ifdef CONFIG_X86_32 #define NR_RANGE_MR 3 #else /* CONFIG_X86_64 */ @@ -263,7 +275,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, * nodes are discovered. */ if (!after_bootmem) - find_early_table_space(end, use_pse, use_gbpages); + find_early_table_space(mr, nr_range); for (i = 0; i < nr_range; i++) ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, From 7c34784313937286fe71089203d62d6b3e534c93 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 25 Oct 2012 15:45:26 -0700 Subject: [PATCH 0437/1071] x86, mm: Undo incorrect revert in arch/x86/mm/init.c commit f82f64dd9f485e13f29f369772d4a0e868e5633a upstream. Commit 844ab6f9 x86, mm: Find_early_table_space based on ranges that are actually being mapped added back some lines back wrongly that has been removed in commit 7b16bbf97 Revert "x86/mm: Fix the size calculation of mapping tables" remove them again. Signed-off-by: Yinghai Lu Link: http://lkml.kernel.org/r/CAE9FiQW_vuaYQbmagVnxT2DGsYc=9tNeAbdBq53sYkitPOwxSQ@mail.gmail.com Acked-by: Jacob Shin Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/init.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index bc287d62bf1eeb..d7aea41563b372 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -65,10 +65,6 @@ static void __init find_early_table_space(struct map_range *mr, int nr_range) #ifdef CONFIG_X86_32 extra += PMD_SIZE; #endif - /* The first 2/4M doesn't use large pages. */ - if (mr[i].start < PMD_SIZE) - extra += range; - ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else { ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; From 116f83b82e7272fec7f9f0f71376bdc67b159ae2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 15 Oct 2012 14:52:41 +0200 Subject: [PATCH 0438/1071] cfg80211/mac80211: avoid state mishmash on deauth commit 6863255bd0e48bc41ae5a066d5c771801e92735a upstream. Avoid situation when we are on associate state in mac80211 and on disassociate state in cfg80211. This can results on crash during modules unload (like showed on this thread: http://marc.info/?t=134373976300001&r=1&w=2) and possibly other problems. Reported-by: Pedro Francisco Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- include/net/cfg80211.h | 1 + net/mac80211/mlme.c | 5 +++-- net/wireless/mlme.c | 12 +++--------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3d254e10ff30e7..f10553c938a61a 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1217,6 +1217,7 @@ struct cfg80211_deauth_request { const u8 *ie; size_t ie_len; u16 reason_code; + bool local_state_change; }; /** diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9f5f9a4365492f..b71d46641830cd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3467,6 +3467,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[DEAUTH_DISASSOC_LEN]; + bool tx = !req->local_state_change; mutex_lock(&ifmgd->mtx); @@ -3483,11 +3484,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && ether_addr_equal(ifmgd->associated->bssid, req->bssid)) ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - req->reason_code, true, frame_buf); + req->reason_code, tx, frame_buf); else ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, - req->reason_code, true, + req->reason_code, tx, frame_buf); mutex_unlock(&ifmgd->mtx); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1cdb1d5e6b0f4b..9ea174f9868f63 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, .reason_code = reason, .ie = ie, .ie_len = ie_len, + .local_state_change = local_state_change, }; ASSERT_WDEV_LOCK(wdev); - if (local_state_change) { - if (wdev->current_bss && - ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(&wdev->current_bss->pub); - wdev->current_bss = NULL; - } - + if (local_state_change && (!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) return 0; - } return rdev->ops->deauth(&rdev->wiphy, dev, &req); } From c1f2d77769770f79d5dd9a8d7ab9615665343fd9 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 28 Sep 2012 17:55:44 -0700 Subject: [PATCH 0439/1071] efi: Defer freeing boot services memory until after ACPI init commit 785107923a83d8456bbd8564e288a24d84109a46 upstream. Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it. Signed-off-by: Josh Triplett Link: http://lkml.kernel.org/r/baaa6d44bdc4eb0c58e5d1b4ccd2c729f854ac55.1348876882.git.josh@joshtriplett.org Signed-off-by: H. Peter Anvin Cc: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi.c | 31 ++++++++++++++++++------------- include/linux/efi.h | 5 +++++ init/main.c | 3 +++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f55a4ce6dc494d..b3dbbdbd2a42b4 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_free_boot_services(void) +static void __init efi_unmap_memmap(void) +{ + if (memmap.map) { + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; + } +} + +void __init efi_free_boot_services(void) { void *p; + if (!efi_native) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + + efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) - goto out; + if (!efi_native) { + efi_unmap_memmap(); + return; + } /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -877,13 +892,6 @@ void __init efi_enter_virtual_mode(void) panic("EFI call to SetVirtualAddressMap() failed!"); } - /* - * Thankfully, it does seem that no runtime services other than - * SetVirtualAddressMap() will touch boot services code, so we can - * get rid of it all at this point - */ - efi_free_boot_services(); - /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. @@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); -out: - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; kfree(new_memmap); } diff --git a/include/linux/efi.h b/include/linux/efi.h index ec45ccd8708a85..5782114f483865 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -496,6 +496,11 @@ extern void efi_map_pal_code (void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ +#ifdef CONFIG_X86 +extern void efi_free_boot_services(void); +#else +static inline void efi_free_boot_services(void) {} +#endif extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); diff --git a/init/main.c b/init/main.c index b28673087ac006..d61ec542205c1f 100644 --- a/init/main.c +++ b/init/main.c @@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); + if (efi_enabled) + efi_free_boot_services(); + ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ From 31fd7858aab67b6c4104cd7323a69f257a170572 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 24 Oct 2012 10:00:44 -0700 Subject: [PATCH 0440/1071] x86: efi: Turn off efi_enabled after setup on mixed fw/kernel commit 5189c2a7c7769ee9d037d76c1a7b8550ccf3481c upstream. When 32-bit EFI is used with 64-bit kernel (or vice versa), turn off efi_enabled once setup is done. Beyond setup, it is normally used to determine if runtime services are available and we will have none. This will resolve issues stemming from efivars modprobe panicking on a 32/64-bit setup, as well as some reboot issues on similar setups. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45991 Reported-by: Marko Kohtala Reported-by: Maxim Kammerer Signed-off-by: Olof Johansson Acked-by: Maarten Lankhorst Cc: Matthew Garrett Signed-off-by: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/efi.h | 1 + arch/x86/kernel/setup.c | 12 ++++++++++++ arch/x86/platform/efi/efi.c | 18 ++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c9dcc181d4d1a8..029189db84dedb 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern int efi_memblock_x86_reserve_range(void); extern void efi_call_phys_prelog(void); extern void efi_call_phys_epilog(void); +extern void efi_unmap_memmap(void); #ifndef CONFIG_EFI /* diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 198e774498ec0e..3e515b457b6c66 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1047,6 +1047,18 @@ void __init setup_arch(char **cmdline_p) mcheck_init(); arch_init_ideal_nops(); + +#ifdef CONFIG_EFI + /* Once setup is done above, disable efi_enabled on mismatched + * firmware/kernel archtectures since there is no support for + * runtime services. + */ + if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { + pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); + efi_unmap_memmap(); + efi_enabled = 0; + } +#endif } #ifdef CONFIG_X86_32 diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b3dbbdbd2a42b4..72d88992f38454 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -69,11 +69,15 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; bool efi_64bit; -static bool efi_native; static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; +static inline bool efi_is_native(void) +{ + return IS_ENABLED(CONFIG_X86_64) == efi_64bit; +} + static int __init setup_noefi(char *arg) { efi_enabled = 0; @@ -419,7 +423,7 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_unmap_memmap(void) +void __init efi_unmap_memmap(void) { if (memmap.map) { early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); @@ -431,7 +435,7 @@ void __init efi_free_boot_services(void) { void *p; - if (!efi_native) + if (!efi_is_native()) return; for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -683,12 +687,10 @@ void __init efi_init(void) return; } efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; - efi_native = !efi_64bit; #else efi_phys.systab = (efi_system_table_t *) (boot_params.efi_info.efi_systab | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); - efi_native = efi_64bit; #endif if (efi_systab_init(efi_phys.systab)) { @@ -722,7 +724,7 @@ void __init efi_init(void) * that doesn't match the kernel 32/64-bit mode. */ - if (!efi_native) + if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); else if (efi_runtime_init()) { efi_enabled = 0; @@ -734,7 +736,7 @@ void __init efi_init(void) return; } #ifdef CONFIG_X86_32 - if (efi_native) { + if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } @@ -800,7 +802,7 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) { + if (!efi_is_native()) { efi_unmap_memmap(); return; } From 2865269348c0cf5448544f971d1c64afe7cdbc98 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Oct 2012 16:35:18 -0700 Subject: [PATCH 0441/1071] x86, mm: Use memblock memory loop instead of e820_RAM commit 1f2ff682ac951ed82cc043cf140d2851084512df upstream. We need to handle E820_RAM and E820_RESERVED_KERNEL at the same time. Also memblock has page aligned range for ram, so we could avoid mapping partial pages. Signed-off-by: Yinghai Lu Link: http://lkml.kernel.org/r/CAE9FiQVZirvaBMFYRfXMmWEcHbKSicQEHz4VAwUv0xFCk51ZNw@mail.gmail.com Acked-by: Jacob Shin Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/setup.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 3e515b457b6c66..5cee802dd5f446 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -920,18 +920,19 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { int i; - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; + unsigned long start, end; + unsigned long start_pfn, end_pfn; - if (ei->addr + ei->size <= 1UL << 32) - continue; + for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, + NULL) { - if (ei->type == E820_RESERVED) + end = PFN_PHYS(end_pfn); + if (end <= (1UL<<32)) continue; + start = PFN_PHYS(start_pfn); max_pfn_mapped = init_memory_mapping( - ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr, - ei->addr + ei->size); + max((1UL<<32), start), end); } /* can we preseve max_low_pfn ?*/ From d1e1f0083e6cb81df51838f8a7824436edd96a95 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 24 Aug 2012 00:27:52 +0800 Subject: [PATCH 0442/1071] pnfsblock: fix non-aligned DIO read commit f742dc4a32587bff50b13dde9d8894b96851951a upstream. For DIO read, if it is not sector aligned, we should reject it and resend via MDS. Otherwise there might be data corruption. Also teach bl_read_pagelist to handle partial page reads for DIO. Signed-off-by: Peng Tao Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/blocklayout/blocklayout.c | 77 +++++++++++++++++++------------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index f3d16adc832c7d..e5dfef55f1e72f 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -242,14 +242,6 @@ bl_end_par_io_read(void *data, int unused) schedule_work(&rdata->task.u.tk_work); } -static bool -bl_check_alignment(u64 offset, u32 len, unsigned long blkmask) -{ - if ((offset & blkmask) || (len & blkmask)) - return false; - return true; -} - static enum pnfs_try_status bl_read_pagelist(struct nfs_read_data *rdata) { @@ -260,15 +252,15 @@ bl_read_pagelist(struct nfs_read_data *rdata) sector_t isect, extent_length = 0; struct parallel_io *par; loff_t f_offset = rdata->args.offset; + size_t bytes_left = rdata->args.count; + unsigned int pg_offset, pg_len; struct page **pages = rdata->args.pages; int pg_index = rdata->args.pgbase >> PAGE_CACHE_SHIFT; + const bool is_dio = (header->dreq != NULL); dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__, rdata->pages.npages, f_offset, (unsigned int)rdata->args.count); - if (!bl_check_alignment(f_offset, rdata->args.count, PAGE_CACHE_MASK)) - goto use_mds; - par = alloc_parallel(rdata); if (!par) goto use_mds; @@ -298,36 +290,53 @@ bl_read_pagelist(struct nfs_read_data *rdata) extent_length = min(extent_length, cow_length); } } + + if (is_dio) { + pg_offset = f_offset & ~PAGE_CACHE_MASK; + if (pg_offset + bytes_left > PAGE_CACHE_SIZE) + pg_len = PAGE_CACHE_SIZE - pg_offset; + else + pg_len = bytes_left; + + f_offset += pg_len; + bytes_left -= pg_len; + isect += (pg_offset >> SECTOR_SHIFT); + } else { + pg_offset = 0; + pg_len = PAGE_CACHE_SIZE; + } + hole = is_hole(be, isect); if (hole && !cow_read) { bio = bl_submit_bio(READ, bio); /* Fill hole w/ zeroes w/o accessing device */ dprintk("%s Zeroing page for hole\n", __func__); - zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE); + zero_user_segment(pages[i], pg_offset, pg_len); print_page(pages[i]); SetPageUptodate(pages[i]); } else { struct pnfs_block_extent *be_read; be_read = (hole && cow_read) ? cow_read : be; - bio = bl_add_page_to_bio(bio, rdata->pages.npages - i, + bio = do_add_page_to_bio(bio, rdata->pages.npages - i, READ, isect, pages[i], be_read, - bl_end_io_read, par); + bl_end_io_read, par, + pg_offset, pg_len); if (IS_ERR(bio)) { header->pnfs_error = PTR_ERR(bio); bio = NULL; goto out; } } - isect += PAGE_CACHE_SECTORS; + isect += (pg_len >> SECTOR_SHIFT); extent_length -= PAGE_CACHE_SECTORS; } if ((isect << SECTOR_SHIFT) >= header->inode->i_size) { rdata->res.eof = 1; - rdata->res.count = header->inode->i_size - f_offset; + rdata->res.count = header->inode->i_size - rdata->args.offset; } else { - rdata->res.count = (isect << SECTOR_SHIFT) - f_offset; + rdata->res.count = (isect << SECTOR_SHIFT) - rdata->args.offset; } out: bl_put_extent(be); @@ -676,7 +685,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) struct bio *bio = NULL; struct pnfs_block_extent *be = NULL, *cow_read = NULL; sector_t isect, last_isect = 0, extent_length = 0; - struct parallel_io *par = NULL; + struct parallel_io *par; loff_t offset = wdata->args.offset; size_t count = wdata->args.count; unsigned int pg_offset, pg_len, saved_len; @@ -688,10 +697,6 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); - /* Check for alignment first */ - if (!bl_check_alignment(offset, count, PAGE_CACHE_MASK)) - goto out_mds; - /* At this point, wdata->pages is a (sequential) list of nfs_pages. * We want to write each, and if there is an error set pnfs_error * to have it redone using nfs. @@ -1164,32 +1169,42 @@ bl_clear_layoutdriver(struct nfs_server *server) return 0; } +static bool +is_aligned_req(struct nfs_page *req, unsigned int alignment) +{ + return IS_ALIGNED(req->wb_offset, alignment) && + IS_ALIGNED(req->wb_bytes, alignment); +} + static void bl_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) { - if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK)) + if (pgio->pg_dreq != NULL && + !is_aligned_req(req, SECTOR_SIZE)) nfs_pageio_reset_read_mds(pgio); else pnfs_generic_pg_init_read(pgio, req); } -static void -bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +static bool +bl_pg_test_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, + struct nfs_page *req) { - if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK)) - nfs_pageio_reset_write_mds(pgio); - else - pnfs_generic_pg_init_write(pgio, req); + if (pgio->pg_dreq != NULL && + !is_aligned_req(req, SECTOR_SIZE)) + return false; + + return pnfs_generic_pg_test(pgio, prev, req); } static const struct nfs_pageio_ops bl_pg_read_ops = { .pg_init = bl_pg_init_read, - .pg_test = pnfs_generic_pg_test, + .pg_test = bl_pg_test_read, .pg_doio = pnfs_generic_pg_readpages, }; static const struct nfs_pageio_ops bl_pg_write_ops = { - .pg_init = bl_pg_init_write, + .pg_init = pnfs_generic_pg_init_write, .pg_test = pnfs_generic_pg_test, .pg_doio = pnfs_generic_pg_writepages, }; From e8a8c5319cf390ab1895d78f6ffcd2c8038f0075 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 24 Aug 2012 00:27:53 +0800 Subject: [PATCH 0443/1071] pnfsblock: fix non-aligned DIO write commit 96c9eae638765c2bf2ca4f5a6325484f9bb69aa7 upstream. For DIO writes, if it is not blocksize aligned, we need to do internal serialization. It may slow down writers anyway. So we just bail them out and resend to MDS. Signed-off-by: Peng Tao Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/blocklayout/blocklayout.c | 34 +++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index e5dfef55f1e72f..10939685dd5f58 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -685,7 +685,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) struct bio *bio = NULL; struct pnfs_block_extent *be = NULL, *cow_read = NULL; sector_t isect, last_isect = 0, extent_length = 0; - struct parallel_io *par; + struct parallel_io *par = NULL; loff_t offset = wdata->args.offset; size_t count = wdata->args.count; unsigned int pg_offset, pg_len, saved_len; @@ -697,6 +697,13 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); + + if (header->dreq != NULL && + (!IS_ALIGNED(offset, NFS_SERVER(header->inode)->pnfs_blksize) || + !IS_ALIGNED(count, NFS_SERVER(header->inode)->pnfs_blksize))) { + dprintk("pnfsblock nonblock aligned DIO writes. Resend MDS\n"); + goto out_mds; + } /* At this point, wdata->pages is a (sequential) list of nfs_pages. * We want to write each, and if there is an error set pnfs_error * to have it redone using nfs. @@ -1197,6 +1204,27 @@ bl_pg_test_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, return pnfs_generic_pg_test(pgio, prev, req); } +void +bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ + if (pgio->pg_dreq != NULL && + !is_aligned_req(req, PAGE_CACHE_SIZE)) + nfs_pageio_reset_write_mds(pgio); + else + pnfs_generic_pg_init_write(pgio, req); +} + +static bool +bl_pg_test_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, + struct nfs_page *req) +{ + if (pgio->pg_dreq != NULL && + !is_aligned_req(req, PAGE_CACHE_SIZE)) + return false; + + return pnfs_generic_pg_test(pgio, prev, req); +} + static const struct nfs_pageio_ops bl_pg_read_ops = { .pg_init = bl_pg_init_read, .pg_test = bl_pg_test_read, @@ -1204,8 +1232,8 @@ static const struct nfs_pageio_ops bl_pg_read_ops = { }; static const struct nfs_pageio_ops bl_pg_write_ops = { - .pg_init = pnfs_generic_pg_init_write, - .pg_test = pnfs_generic_pg_test, + .pg_init = bl_pg_init_write, + .pg_test = bl_pg_test_write, .pg_doio = pnfs_generic_pg_writepages, }; From d724b881b05d86182ba5343e0c13e0834bb6e7bf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Oct 2012 10:11:22 -0700 Subject: [PATCH 0444/1071] Linux 3.6.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dcf132ae3f07fd..6e4a00dccb9353 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 4 +SUBLEVEL = 5 EXTRAVERSION = NAME = Terrified Chipmunk From dab43b73a7c7317f941c1314e9a77374ba8999ee Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sun, 28 Oct 2012 22:24:57 -0400 Subject: [PATCH 0445/1071] ext4: fix unjournaled inode bitmap modification commit ffb5387e85d528fb6d0d924abfa3fbf0fc484071 upstream. commit 119c0d4460b001e44b41dcf73dc6ee794b98bd31 changed ext4_new_inode() such that the inode bitmap was being modified outside a transaction, which could lead to corruption, and was discovered when journal_checksum found a bad checksum in the journal during log replay. Nix ran into this when using the journal_async_commit mount option, which enables journal checksumming. The ensuing journal replay failures due to the bad checksums led to filesystem corruption reported as the now infamous "Apparent serious progressive ext4 data corruption bug" [ Changed by tytso to only call ext4_journal_get_write_access() only when we're fairly certain that we're going to allocate the inode. ] I've tested this by mounting with journal_checksum and running fsstress then dropping power; I've also tested by hacking DM to create snapshots w/o first quiescing, which allows me to test journal replay repeatedly w/o actually power-cycling the box. Without the patch I hit a journal checksum error every time. With this fix it survives many iterations. Reported-by: Nix Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ialloc.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 8ce0076c315238..cc2d77cc3ed839 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -716,6 +716,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, "inode=%lu", ino + 1); continue; } + BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, inode_bitmap_bh); + if (err) + goto fail; ext4_lock_group(sb, group); ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); ext4_unlock_group(sb, group); @@ -729,6 +733,11 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, goto out; got: + BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); + err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); + if (err) + goto fail; + /* We may have to initialize the block bitmap if it isn't already */ if (ext4_has_group_desc_csum(sb) && gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { @@ -762,11 +771,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, goto fail; } - BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); - err = ext4_journal_get_write_access(handle, inode_bitmap_bh); - if (err) - goto fail; - BUFFER_TRACE(group_desc_bh, "get_write_access"); err = ext4_journal_get_write_access(handle, group_desc_bh); if (err) @@ -814,11 +818,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, } ext4_unlock_group(sb, group); - BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); - err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); - if (err) - goto fail; - BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); if (err) From edf5181e0804d4d484b11b4d4e8150a80a39908b Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Wed, 17 Oct 2012 17:45:36 +0900 Subject: [PATCH 0446/1071] blkcg: Fix use-after-free of q->root_blkg and q->root_rl.blkg commit 65635cbc37e011e71b208257a25e7c1078cd039b upstream. blk_put_rl() does not call blkg_put() for q->root_rl because we don't take request list reference on q->root_blkg. However, if root_blkg is once attached then detached (freed), blk_put_rl() is confused by the bogus pointer in q->root_blkg. For example, with !CONFIG_BLK_DEV_THROTTLING && CONFIG_CFQ_GROUP_IOSCHED, switching IO scheduler from cfq to deadline will cause system stall after the following warning with 3.6: > WARNING: at /work/build/linux/block/blk-cgroup.h:250 > blk_put_rl+0x4d/0x95() > Modules linked in: bridge stp llc sunrpc acpi_cpufreq freq_table mperf > ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4 > Pid: 0, comm: swapper/0 Not tainted 3.6.0 #1 > Call Trace: > [] warn_slowpath_common+0x85/0x9d > [] warn_slowpath_null+0x1a/0x1c > [] blk_put_rl+0x4d/0x95 > [] __blk_put_request+0xc3/0xcb > [] blk_finish_request+0x232/0x23f > [] ? blk_end_bidi_request+0x34/0x5d > [] blk_end_bidi_request+0x42/0x5d > [] blk_end_request+0x10/0x12 > [] scsi_io_completion+0x207/0x4d5 > [] scsi_finish_command+0xfa/0x103 > [] scsi_softirq_done+0xff/0x108 > [] blk_done_softirq+0x8d/0xa1 > [] ? > generic_smp_call_function_single_interrupt+0x9f/0xd7 > [] __do_softirq+0x102/0x213 > [] ? lock_release_holdtime+0xb6/0xbb > [] ? raise_softirq_irqoff+0x9/0x3d > [] call_softirq+0x1c/0x30 > [] do_softirq+0x4b/0xa3 > [] irq_exit+0x53/0xd5 > [] smp_call_function_single_interrupt+0x34/0x36 > [] call_function_single_interrupt+0x6f/0x80 > [] ? mwait_idle+0x94/0xcd > [] ? mwait_idle+0x8b/0xcd > [] cpu_idle+0xbb/0x114 > [] rest_init+0xc1/0xc8 > [] ? csum_partial_copy_generic+0x16c/0x16c > [] start_kernel+0x3d4/0x3e1 > [] ? kernel_init+0x1f7/0x1f7 > [] x86_64_start_reservations+0xb8/0xbd > [] x86_64_start_kernel+0x101/0x110 This patch clears q->root_blkg and q->root_rl.blkg when root blkg is destroyed. Signed-off-by: Jun'ichi Nomura Acked-by: Vivek Goyal Acked-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-cgroup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index f3b44a65fc7ad5..54f35d1c07a94a 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q) blkg_destroy(blkg); spin_unlock(&blkcg->lock); } + + /* + * root blkg is destroyed. Just clear the pointer since + * root_rl does not take reference on root blkg. + */ + q->root_blkg = NULL; + q->root_rl.blkg = NULL; } static void blkg_rcu_free(struct rcu_head *rcu_head) From 11d65f48c02dae54020c407d1cf3f2dfd44e88c0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 11 Oct 2012 09:56:35 +0300 Subject: [PATCH 0447/1071] gpio-timberdale: fix a potential wrapping issue commit d79550a7bc35c16476ebdc27c78378d8093390ec upstream. ->last_ier is an unsigned long but the high bits can't be used int the original code because the shift wraps. Signed-off-by: Dan Carpenter Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-timberdale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 031c6adf5b6515..1a3e2b9b4772f7 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier &= ~(1 << offset); + tgpio->last_ier &= ~(1UL << offset); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier |= 1 << offset; + tgpio->last_ier |= 1UL << offset; iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } From 4b4717878e2e70626855d5a6b4639a8e37599acc Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 25 Oct 2012 14:03:03 +0300 Subject: [PATCH 0448/1071] gpiolib: Don't return -EPROBE_DEFER to sysfs, or for invalid gpios commit ad2fab36d7922401c4576fb7ea9b21a47a29a17f upstream. gpios requested with invalid numbers, or gpios requested from userspace via sysfs should not try to be deferred on failure. Signed-off-by: Mathias Nyman Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpiolib.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index de0213c9d11ce1..f03ae68051d677 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class, */ status = gpio_request(gpio, "sysfs"); - if (status < 0) + if (status < 0) { + if (status == -EPROBE_DEFER) + status = -ENODEV; goto done; - + } status = gpio_export(gpio, true); if (status < 0) gpio_free(gpio); @@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label) spin_lock_irqsave(&gpio_lock, flags); - if (!gpio_is_valid(gpio)) + if (!gpio_is_valid(gpio)) { + status = -EINVAL; goto done; + } desc = &gpio_desc[gpio]; chip = desc->chip; if (chip == NULL) From 636b755668eefd3537af58e7843ef8389c4d03b6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 31 Oct 2012 11:42:03 +1100 Subject: [PATCH 0449/1071] md/raid1: Fix assembling of arrays containing Replacements. commit 02b898f2f04e418094f0093a3ad0b415bcdbe8eb upstream. setup_conf in raid1.c uses conf->raid_disks before assigning a value. It is used when including 'Replacement' devices. The consequence is that assembling an array which contains a replacement will misbehave and either not include the replacement, or not include the device being replaced. Though this doesn't lead directly to data corruption, it could lead to reduced data safety. So use mddev->raid_disks, which is initialised, instead. Bug was introduced by commit c19d57980b38a5bb613a898937a1cf85f422fb9b md/raid1: recognise replacements when assembling arrays. in 3.3, so fix is suitable for 3.3.y thru 3.6.y. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 611b5f79761826..05bb49e1364826 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2699,7 +2699,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) || disk_idx < 0) continue; if (test_bit(Replacement, &rdev->flags)) - disk = conf->mirrors + conf->raid_disks + disk_idx; + disk = conf->mirrors + mddev->raid_disks + disk_idx; else disk = conf->mirrors + disk_idx; From 0de4380ecfc63f6f3940b9ec03c36c78f008ac12 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:51 -0300 Subject: [PATCH 0450/1071] floppy: don't call alloc_ordered_workqueue inside the alloc_disk loop commit b54e1f88897bcacc2cd359f48ea3b39eaf55f084 upstream. Since commit 070ad7e ("floppy: convert to delayed work and single-thread wq"), we end up calling alloc_ordered_workqueue multiple times inside the loop, which shouldn't be intended. Besides the leak, other side effect in the current code is if blk_init_queue fails, we would end up calling unregister_blkdev even if we didn't call yet register_blkdev. Just moved the allocation of floppy_wq before the loop, and adjusted the code accordingly. Acked-by: Vivek Goyal Reviewed-by: Ben Hutchings Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/floppy.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index a7d6347aaa7913..c8d9e68a732eb8 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4138,6 +4138,10 @@ static int __init do_floppy_init(void) raw_cmd = NULL; + floppy_wq = alloc_ordered_workqueue("floppy", 0); + if (!floppy_wq) + return -ENOMEM; + for (dr = 0; dr < N_DRIVE; dr++) { disks[dr] = alloc_disk(1); if (!disks[dr]) { @@ -4145,16 +4149,10 @@ static int __init do_floppy_init(void) goto out_put_disk; } - floppy_wq = alloc_ordered_workqueue("floppy", 0); - if (!floppy_wq) { - err = -ENOMEM; - goto out_put_disk; - } - disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { err = -ENOMEM; - goto out_destroy_workq; + goto out_put_disk; } blk_queue_max_hw_sectors(disks[dr]->queue, 64); @@ -4318,8 +4316,6 @@ static int __init do_floppy_init(void) out_unreg_region: blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); platform_driver_unregister(&floppy_driver); -out_destroy_workq: - destroy_workqueue(floppy_wq); out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: @@ -4335,6 +4331,7 @@ static int __init do_floppy_init(void) } put_disk(disks[dr]); } + destroy_workqueue(floppy_wq); return err; } From d4eaaf6e3cf75c8394a36b6de67a1771da5ed2ee Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:52 -0300 Subject: [PATCH 0451/1071] floppy: do put_disk on current dr if blk_init_queue fails commit 238ab78469c6ab7845b43d5061cd3c92331b2452 upstream. If blk_init_queue fails, we do not call put_disk on the current dr (dr is decremented first in the error handling loop). Reviewed-by: Ben Hutchings Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/floppy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index c8d9e68a732eb8..1e09e998904f6b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4151,6 +4151,7 @@ static int __init do_floppy_init(void) disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { + put_disk(disks[dr]); err = -ENOMEM; goto out_put_disk; } From 6d59ab3707595e1a7b2e6051ff3f5f0dabd0ad06 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:54 -0300 Subject: [PATCH 0452/1071] floppy: properly handle failure on add_disk loop commit d60e7ec18c3fb2cbf90969ccd42889eb2d03aef9 upstream. On floppy initialization, if something failed inside the loop we call add_disk, there was no cleanup of previous iterations in the error handling. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/floppy.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 1e09e998904f6b..fe0de7e0a035b5 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4293,7 +4293,7 @@ static int __init do_floppy_init(void) err = platform_device_register(&floppy_device[drive]); if (err) - goto out_release_dma; + goto out_remove_drives; err = device_create_file(&floppy_device[drive].dev, &dev_attr_cmos); @@ -4311,6 +4311,15 @@ static int __init do_floppy_init(void) out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); +out_remove_drives: + while (drive--) { + if ((allowed_drive_mask & (1 << drive)) && + fdc_state[FDC(drive)].version != FDC_NONE) { + del_gendisk(disks[drive]); + device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); + platform_device_unregister(&floppy_device[drive]); + } + } out_release_dma: if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); From a407c28651969f9e34fd51ea0415886b70e5c991 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 8 Oct 2012 20:37:30 -0700 Subject: [PATCH 0453/1071] rbd: reset BACKOFF if unable to re-queue commit 588377d6199034c36d335e7df5818b731fea072c upstream. If ceph_fault() is unable to queue work after a delay, it sets the BACKOFF connection flag so con_work() will attempt to do so. In con_work(), when BACKOFF is set, if queue_delayed_work() doesn't result in newly-queued work, it simply ignores this condition and proceeds as if no backoff delay were desired. There are two problems with this--one of which is a bug. The first problem is simply that the intended behavior is to back off, and if we aren't able queue the work item to run after a delay we're not doing that. The only reason queue_delayed_work() won't queue work is if the provided work item is already queued. In the messenger, this means that con_work() is already scheduled to be run again. So if we simply set the BACKOFF flag again when this occurs, we know the next con_work() call will again attempt to hold off activity on the connection until after the delay. The second problem--the bug--is a leak of a reference count. If queue_delayed_work() returns 0 in con_work(), con->ops->put() drops the connection reference held on entry to con_work(). However, processing is (was) allowed to continue, and at the end of the function a second con->ops->put() is called. This patch fixes both problems. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 159aa8bef9e7fe..cad0d17ec45e5f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2300,10 +2300,11 @@ static void con_work(struct work_struct *work) mutex_unlock(&con->mutex); return; } else { - con->ops->put(con); dout("con_work %p FAILED to back off %lu\n", con, con->delay); + set_bit(CON_FLAG_BACKOFF, &con->flags); } + goto done; } if (con->state == CON_STATE_STANDBY) { From b6f8fbbad7bf2511aea493b0dc7be92e3b5c5a8d Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 24 Oct 2012 16:12:58 -0700 Subject: [PATCH 0454/1071] libceph: avoid NULL kref_put when osd reset races with alloc_msg commit 9bd952615a42d7e2ce3fa2c632e808e804637a1a upstream. The ceph_on_in_msg_alloc() method drops con->mutex while it allocates a message. If that races with a timeout that resends a zillion messages and resets the connection, and the ->alloc_msg() method returns a NULL message, it will call ceph_msg_put(NULL) and BUG. Fix by only calling put if msg is non-NULL. Fixes http://tracker.newdream.net/issues/3142 Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index cad0d17ec45e5f..3ef1759403b411 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2750,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); if (con->state != CON_STATE_OPEN) { - ceph_msg_put(msg); + if (msg) + ceph_msg_put(msg); return -EAGAIN; } con->in_msg = msg; From aeb469d6f6b311f531df80d25a82b297cffc4569 Mon Sep 17 00:00:00 2001 From: David Zafman Date: Thu, 18 Oct 2012 14:01:43 -0700 Subject: [PATCH 0455/1071] ceph: fix dentry reference leak in encode_fh() commit 52eb5a900a9863a8b77a895f770e5d825c8e02c6 upstream. Call to d_find_alias() needs a corresponding dput() This fixes http://tracker.newdream.net/issues/3271 Signed-off-by: David Zafman Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/export.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 02ce90972d81ca..9349bb37a2fe68 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, *max_len = handle_length; type = 255; } + if (dentry) + dput(dentry); return type; } From 1ad6768c537d57fec3dcb249cd384332cfacfe24 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 20 Sep 2012 17:42:25 +0800 Subject: [PATCH 0456/1071] ceph: Fix oops when handling mdsmap that decreases max_mds commit 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5 upstream. When i >= newmap->m_max_mds, ceph_mdsmap_get_addr(newmap, i) return NULL. Passing NULL to memcmp() triggers oops. Signed-off-by: Yan, Zheng Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index a5a735422aa7a4..1bcf712655d90a 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2625,7 +2625,8 @@ static void check_new_map(struct ceph_mds_client *mdsc, ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "", session_state_name(s->s_state)); - if (memcmp(ceph_mdsmap_get_addr(oldmap, i), + if (i >= newmap->m_max_mds || + memcmp(ceph_mdsmap_get_addr(oldmap, i), ceph_mdsmap_get_addr(newmap, i), sizeof(struct ceph_entity_addr))) { if (s->s_state == CEPH_MDS_SESSION_OPENING) { From 343c7f0dcb36f71bc4edfc602eb8c20faf88fa65 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 24 Sep 2012 20:59:48 -0700 Subject: [PATCH 0457/1071] libceph: check for invalid mapping commit d63b77f4c552cc3a20506871046ab0fcbc332609 upstream. If we encounter an invalid (e.g., zeroed) mapping, return an error and avoid a divide by zero. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/osd_client.h | 2 +- include/linux/ceph/osdmap.h | 6 +++--- net/ceph/osd_client.c | 32 ++++++++++++++++++++------------ net/ceph/osdmap.c | 18 ++++++++++++++++-- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index cedfb1a8434a11..d9b880e977e62f 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -207,7 +207,7 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg); -extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc, +extern int ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_file_layout *layout, u64 snapid, u64 off, u64 *plen, u64 *bno, diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h index 311ef8d6aa9efc..e88a620b9f8aae 100644 --- a/include/linux/ceph/osdmap.h +++ b/include/linux/ceph/osdmap.h @@ -109,9 +109,9 @@ extern struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, extern void ceph_osdmap_destroy(struct ceph_osdmap *map); /* calculate mapping of a file extent to an object */ -extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, - u64 off, u64 *plen, - u64 *bno, u64 *oxoff, u64 *oxlen); +extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, + u64 off, u64 *plen, + u64 *bno, u64 *oxoff, u64 *oxlen); /* calculate mapping of object to a placement group */ extern int ceph_calc_object_layout(struct ceph_object_layout *ol, diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 42119c05e82c02..f7b56e23988c62 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -52,7 +52,7 @@ static int op_has_extent(int op) op == CEPH_OSD_OP_WRITE); } -void ceph_calc_raw_layout(struct ceph_osd_client *osdc, +int ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_file_layout *layout, u64 snapid, u64 off, u64 *plen, u64 *bno, @@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; u64 orig_len = *plen; u64 objoff, objlen; /* extent in object */ + int r; reqhead->snapid = cpu_to_le64(snapid); /* object extent? */ - ceph_calc_file_object_mapping(layout, off, plen, bno, - &objoff, &objlen); + r = ceph_calc_file_object_mapping(layout, off, plen, bno, + &objoff, &objlen); + if (r < 0) + return r; if (*plen < orig_len) dout(" skipping last %llu, final file extent %llu~%llu\n", orig_len - *plen, off, *plen); @@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", *bno, objoff, objlen, req->r_num_pages); - + return 0; } EXPORT_SYMBOL(ceph_calc_raw_layout); @@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout); * * fill osd op in request message. */ -static void calc_layout(struct ceph_osd_client *osdc, - struct ceph_vino vino, - struct ceph_file_layout *layout, - u64 off, u64 *plen, - struct ceph_osd_request *req, - struct ceph_osd_req_op *op) +static int calc_layout(struct ceph_osd_client *osdc, + struct ceph_vino vino, + struct ceph_file_layout *layout, + u64 off, u64 *plen, + struct ceph_osd_request *req, + struct ceph_osd_req_op *op) { u64 bno; + int r; - ceph_calc_raw_layout(osdc, layout, vino.snap, off, - plen, &bno, req, op); + r = ceph_calc_raw_layout(osdc, layout, vino.snap, off, + plen, &bno, req, op); + if (r < 0) + return r; snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno); req->r_oid_len = strlen(req->r_oid); + + return r; } /* diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 3124b71a888362..5433fb0eb3c685 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -984,7 +984,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, * for now, we write only a single su, until we can * pass a stride back to the caller. */ -void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, +int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, u64 off, u64 *plen, u64 *ono, u64 *oxoff, u64 *oxlen) @@ -998,11 +998,17 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen, osize, su); + if (su == 0 || sc == 0) + goto invalid; su_per_object = osize / su; + if (su_per_object == 0) + goto invalid; dout("osize %u / su %u = su_per_object %u\n", osize, su, su_per_object); - BUG_ON((su & ~PAGE_MASK) != 0); + if ((su & ~PAGE_MASK) != 0) + goto invalid; + /* bl = *off / su; */ t = off; do_div(t, su); @@ -1030,6 +1036,14 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, *plen = *oxlen; dout(" obj extent %llu~%llu\n", *oxoff, *oxlen); + return 0; + +invalid: + dout(" invalid layout\n"); + *ono = 0; + *oxoff = 0; + *oxlen = 0; + return -EINVAL; } EXPORT_SYMBOL(ceph_calc_file_object_mapping); From b7639e25716afc0211bcc14006a4af4e9e9bc2b9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Oct 2012 10:25:51 -0500 Subject: [PATCH 0458/1071] ceph: avoid 32-bit page index overflow commit 6285bc231277419255f3498d3eb5ddc9f8e7fe79 upstream. A pgoff_t is defined (by default) to have type (unsigned long). On architectures such as i686 that's a 32-bit type. The ceph address space code was attempting to produce 64 bit offsets by shifting a page's index by PAGE_CACHE_SHIFT, but the result was not what was desired because the shift occurred before the result got promoted to 64 bits. Fix this by converting all uses of page->index used in this way to use the page_offset() macro, which ensures the 64-bit result has the intended value. This fixes http://tracker.newdream.net/issues/3112 Reported-by: Mohamed Pakkeer Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/addr.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 452e71a1b75388..1ced2d83a83a49 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -205,7 +205,7 @@ static int readpage_nounlock(struct file *filp, struct page *page) dout("readpage inode %p file %p page %p index %lu\n", inode, filp, page, page->index); err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout, - page->index << PAGE_CACHE_SHIFT, &len, + (u64) page_offset(page), &len, ci->i_truncate_seq, ci->i_truncate_size, &page, 1, 0); if (err == -ENOENT) @@ -286,7 +286,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) int nr_pages = 0; int ret; - off = page->index << PAGE_CACHE_SHIFT; + off = (u64) page_offset(page); /* count pages */ next_index = page->index; @@ -426,7 +426,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) struct ceph_inode_info *ci; struct ceph_fs_client *fsc; struct ceph_osd_client *osdc; - loff_t page_off = page->index << PAGE_CACHE_SHIFT; + loff_t page_off = page_offset(page); int len = PAGE_CACHE_SIZE; loff_t i_size; int err = 0; @@ -817,8 +817,7 @@ static int ceph_writepages_start(struct address_space *mapping, /* ok */ if (locked_pages == 0) { /* prepare async write request */ - offset = (unsigned long long)page->index - << PAGE_CACHE_SHIFT; + offset = (u64) page_offset(page); len = wsize; req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, @@ -1180,7 +1179,7 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct inode *inode = vma->vm_file->f_dentry->d_inode; struct page *page = vmf->page; struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; - loff_t off = page->index << PAGE_CACHE_SHIFT; + loff_t off = page_offset(page); loff_t size, len; int ret; From 0813e85449a343a214462346f146f7b0f6a2053d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 31 Oct 2012 20:52:42 +0100 Subject: [PATCH 0459/1071] USB: mos7840: fix port-data memory leak commit 80c00750f0c9867a65b30a17880939b6bc660a77 upstream. Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible. Note that the indentation was kept intact using a do-while(0) in order to facilitate review. A follow-up patch will remove it. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 198 +++++++++++++---------------------- 1 file changed, 71 insertions(+), 127 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 52e5ca7e128476..5311819170d96f 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2405,52 +2405,43 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) return mos7840_num_ports; } -/**************************************************************************** - * mos7840_startup - ****************************************************************************/ - -static int mos7840_startup(struct usb_serial *serial) +static int mos7840_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct moschip_port *mos7840_port; - struct usb_device *dev; - int i, status; + int status; + int pnum; __u16 Data; - if (!serial) { - dbg("%s", "Invalid Handler"); - return -1; - } - - dev = serial->dev; - /* we set up the pointers to the endpoints in the mos7840_open * * function, as the structures aren't created yet. */ - /* set up port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - dbg ("mos7840_startup: configuring port %d............", i); + pnum = port->number - serial->minor; + + /* FIXME: remove do-while(0) loop used to keep stable patch minimal. + */ + do { + dbg("mos7840_startup: configuring port %d............", pnum); mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); if (mos7840_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - status = -ENOMEM; - i--; /* don't follow NULL pointer cleaning up */ - goto error; + dev_err(&port->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; } /* Initialize all port interrupt end point to port 0 int * endpoint. Our device has only one interrupt end point * common to all port */ - mos7840_port->port = serial->port[i]; - mos7840_set_port_private(serial->port[i], mos7840_port); + mos7840_port->port = port; + mos7840_set_port_private(port, mos7840_port); spin_lock_init(&mos7840_port->pool_lock); /* minor is not initialised until later by * usb-serial.c:get_free_serial() and cannot therefore be used * to index device instances */ - mos7840_port->port_num = i + 1; - dbg ("serial->port[i]->number = %d", serial->port[i]->number); - dbg ("serial->port[i]->serial->minor = %d", serial->port[i]->serial->minor); + mos7840_port->port_num = pnum + 1; + dbg("port->number = %d", port->number); + dbg("port->serial->minor = %d", port->serial->minor); dbg ("mos7840_port->port_num = %d", mos7840_port->port_num); dbg ("serial->minor = %d", serial->minor); @@ -2480,10 +2471,10 @@ static int mos7840_startup(struct usb_serial *serial) mos7840_port->DcrRegOffset = 0x1c; } mos7840_dump_serial_port(mos7840_port); - mos7840_set_port_private(serial->port[i], mos7840_port); + mos7840_set_port_private(port, mos7840_port); /* enable rx_disable bit in control register */ - status = mos7840_get_reg_sync(serial->port[i], + status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); if (status < 0) { dbg("Reading ControlReg failed status-0x%x", status); @@ -2491,12 +2482,13 @@ static int mos7840_startup(struct usb_serial *serial) } else dbg("ControlReg Reading success val is %x, status%d", Data, status); + Data |= 0x08; /* setting driver done bit */ Data |= 0x04; /* sp1_bit to have cts change reflect in modem status reg */ /* Data |= 0x20; //rx_disable bit */ - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); if (status < 0) { dbg("Writing ControlReg failed(rx_disable) status-0x%x", status); @@ -2508,7 +2500,7 @@ static int mos7840_startup(struct usb_serial *serial) /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3 */ Data = 0x01; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (mos7840_port->DcrRegOffset + 0), Data); if (status < 0) { dbg("Writing DCR0 failed status-0x%x", status); @@ -2517,7 +2509,7 @@ static int mos7840_startup(struct usb_serial *serial) dbg("DCR0 Writing success status%d", status); Data = 0x05; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (mos7840_port->DcrRegOffset + 1), Data); if (status < 0) { dbg("Writing DCR1 failed status-0x%x", status); @@ -2526,7 +2518,7 @@ static int mos7840_startup(struct usb_serial *serial) dbg("DCR1 Writing success status%d", status); Data = 0x24; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (mos7840_port->DcrRegOffset + 2), Data); if (status < 0) { dbg("Writing DCR2 failed status-0x%x", status); @@ -2536,7 +2528,7 @@ static int mos7840_startup(struct usb_serial *serial) /* write values in clkstart0x0 and clkmulti 0x20 */ Data = 0x0; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); if (status < 0) { dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x", status); @@ -2545,7 +2537,7 @@ static int mos7840_startup(struct usb_serial *serial) dbg("CLK_START_VALUE_REGISTER Writing success status%d", status); Data = 0x20; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); if (status < 0) { dbg("Writing CLK_MULTI_REGISTER failed status-0x%x", @@ -2557,7 +2549,7 @@ static int mos7840_startup(struct usb_serial *serial) /* write value 0x0 to scratchpad register */ Data = 0x00; - status = mos7840_set_uart_reg(serial->port[i], + status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); if (status < 0) { dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x", @@ -2572,7 +2564,7 @@ static int mos7840_startup(struct usb_serial *serial) && (serial->num_ports == 2)) { Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (ZLP_REG1 + ((__u16)mos7840_port->port_num)), Data); dbg("ZLIP offset %x", @@ -2580,14 +2572,14 @@ static int mos7840_startup(struct usb_serial *serial) ((__u16) mos7840_port->port_num))); if (status < 0) { dbg("Writing ZLP_REG%d failed status-0x%x", - i + 2, status); + pnum + 2, status); break; } else dbg("ZLP_REG%d Writing success status%d", - i + 2, status); + pnum + 2, status); } else { Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], + status = mos7840_set_reg_sync(port, (__u16) (ZLP_REG1 + ((__u16)mos7840_port->port_num) - 0x1), Data); dbg("ZLIP offset %x", @@ -2595,11 +2587,11 @@ static int mos7840_startup(struct usb_serial *serial) ((__u16) mos7840_port->port_num) - 0x1)); if (status < 0) { dbg("Writing ZLP_REG%d failed status-0x%x", - i + 1, status); + pnum + 1, status); break; } else dbg("ZLP_REG%d Writing success status%d", - i + 1, status); + pnum + 1, status); } mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -2636,105 +2628,58 @@ static int mos7840_startup(struct usb_serial *serial) mos7840_port->led_flag = false; /* Turn off LED */ - mos7840_set_led_sync(serial->port[i], + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); } - } - dbg ("mos7840_startup: all ports configured..........."); + } while (0); - /* Zero Length flag enable */ - Data = 0x0f; - status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); - if (status < 0) { - dbg("Writing ZLP_REG5 failed status-0x%x", status); - goto error; - } else - dbg("ZLP_REG5 Writing success status%d", status); - - /* setting configuration feature to one */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); + if (pnum == serial->num_ports - 1) { + dbg("mos7840_startup: all ports configured..........."); + + /* Zero Length flag enable */ + Data = 0x0f; + status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); + if (status < 0) { + dbg("Writing ZLP_REG5 failed status-0x%x", status); + goto error; + } else + dbg("ZLP_REG5 Writing success status%d", status); + + /* setting configuration feature to one */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + 0x03, 0x00, 0x01, 0x00, NULL, 0x00, + MOS_WDR_TIMEOUT); + } return 0; error: - for (/* nothing */; i >= 0; i--) { - mos7840_port = mos7840_get_port_private(serial->port[i]); + kfree(mos7840_port->dr); + kfree(mos7840_port->ctrl_buf); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port); - kfree(mos7840_port->dr); - kfree(mos7840_port->ctrl_buf); - usb_free_urb(mos7840_port->control_urb); - kfree(mos7840_port); - } return status; } -/**************************************************************************** - * mos7840_disconnect - * This function is called whenever the device is removed from the usb bus. - ****************************************************************************/ - -static void mos7840_disconnect(struct usb_serial *serial) +static int mos7840_port_remove(struct usb_serial_port *port) { - int i; - unsigned long flags; struct moschip_port *mos7840_port; - if (!serial) { - dbg("%s", "Invalid Handler"); - return; - } - - /* check for the ports to be closed,close the ports and disconnect */ + mos7840_port = mos7840_get_port_private(port); - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ + if (mos7840_port->has_led) { + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - dbg ("mos7840_port %d = %p", i, mos7840_port); - if (mos7840_port) { - usb_kill_urb(mos7840_port->control_urb); - } + del_timer_sync(&mos7840_port->led_timer1); + del_timer_sync(&mos7840_port->led_timer2); } -} + usb_kill_urb(mos7840_port->control_urb); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port->ctrl_buf); + kfree(mos7840_port->dr); + kfree(mos7840_port); -/**************************************************************************** - * mos7840_release - * This function is called when the usb_serial structure is freed. - ****************************************************************************/ - -static void mos7840_release(struct usb_serial *serial) -{ - int i; - struct moschip_port *mos7840_port; - - if (!serial) { - dbg("%s", "Invalid Handler"); - return; - } - - /* check for the ports to be closed,close the ports and disconnect */ - - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ - - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - dbg("mos7840_port %d = %p", i, mos7840_port); - if (mos7840_port) { - if (mos7840_port->has_led) { - /* Turn off LED */ - mos7840_set_led_sync(mos7840_port->port, - MODEM_CONTROL_REGISTER, 0x0300); - - del_timer_sync(&mos7840_port->led_timer1); - del_timer_sync(&mos7840_port->led_timer2); - } - usb_free_urb(mos7840_port->control_urb); - kfree(mos7840_port->ctrl_buf); - kfree(mos7840_port->dr); - kfree(mos7840_port); - } - } + return 0; } static struct usb_serial_driver moschip7840_4port_device = { @@ -2762,9 +2707,8 @@ static struct usb_serial_driver moschip7840_4port_device = { .tiocmget = mos7840_tiocmget, .tiocmset = mos7840_tiocmset, .get_icount = mos7840_get_icount, - .attach = mos7840_startup, - .disconnect = mos7840_disconnect, - .release = mos7840_release, + .port_probe = mos7840_port_probe, + .port_remove = mos7840_port_remove, .read_bulk_callback = mos7840_bulk_in_callback, .read_int_callback = mos7840_interrupt_callback, }; From 7b746b16909444af2d207b010b89885591ea54d0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 31 Oct 2012 20:48:54 +0100 Subject: [PATCH 0460/1071] USB: iuu_phoenix: fix backported patches Fix two memory leaks involving dbgbuf that were introduced in port-probe error paths when backporting the following port-data fixes from v3.7 (which doesn't have dbgbuf): 0978c94 USB: iuu_phoenix: fix sysfs-attribute creation 5363655 USB: iuu_phoenix: fix port-data memory leak Reported-by: Fengguang Wu Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index cdf0f994e883a5..8d3692bef861f8 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -105,7 +105,7 @@ static int iuu_port_probe(struct usb_serial_port *port) } priv->dbgbuf = kzalloc(256, GFP_KERNEL); - if (!priv->writebuf) { + if (!priv->dbgbuf) { kfree(priv->writebuf); kfree(priv->buf); kfree(priv); @@ -120,6 +120,7 @@ static int iuu_port_probe(struct usb_serial_port *port) ret = iuu_create_sysfs_attrs(port); if (ret) { + kfree(priv->dbgbuf); kfree(priv->writebuf); kfree(priv->buf); kfree(priv); From 16d6c35cfbed79472c8e2ae2df5b4935c2ac588b Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 30 Oct 2012 10:38:06 +0100 Subject: [PATCH 0461/1071] USB: io_edgeport: remove unused variable The stable commit 12ddc74e8e25107eda81aceb74e3311c1480b381 ("USB: io_edgeport: fix port-data memory leak") left one variable unused: drivers/usb/serial/io_edgeport.c: In function 'edge_release': drivers/usb/serial/io_edgeport.c:3155:6: warning: unused variable 'i' [-Wunused-variable] Remove this unused variable. Signed-off-by: Paul Bolle Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index dca27a5269f765..6c22679aa776a6 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -3152,7 +3152,6 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); - int i; dbg("%s", __func__); From aa927fcb2d23c7f0b1e350335eb822f5179c49a9 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 11 Oct 2012 13:41:32 -0700 Subject: [PATCH 0462/1071] qla2xxx: Update target lookup session tables when a target session changes commit c8292d1da53fa60c7516ab03a9d83f7ea266d335 upstream. It is possible for the target code to change the loop_id or s_id of a target session in reaction to an FC fabric change. However, the session structures are stored in tables that are indexed by these two keys, and if we just change the session structure but leave the pointers to it in the old places in the table, havoc can ensue. For example, a new session might come along that should go in the old slot in the table and overwrite the old session pointer. To handle this, add a new tgt_ops->update_sess() method that also updates the "by loop_id" and "by s_id" lookup tables when a session changes, so that the keys where a session pointer is stored in these tables always matches the keys in the session structure itself. (nab: Drop unnecessary double inversion with FCF_CONF_COMP_SUPPORTED usage) Signed-off-by: Roland Dreier Cc: Chad Dupuis Cc: Arun Easi Cc: Saurav Kashyap Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_target.c | 25 +++++----- drivers/scsi/qla2xxx/qla_target.h | 1 + drivers/scsi/qla2xxx/tcm_qla2xxx.c | 73 ++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 41b74ba8d4e584..515c250fc6ac40 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, int pmap_len; fc_port_t *fcport; int global_resets; + unsigned long flags; retry: global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); @@ -625,10 +626,10 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); + spin_unlock_irqrestore(&ha->hardware_lock, flags); res = true; @@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess( qlt_undelete_sess(sess); kref_get(&sess->se_sess->sess_kref); - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); + if (sess->local && !local) sess->local = 0; spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess( */ kref_get(&sess->se_sess->sess_kref); - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED); BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007, "Reappeared sess %p\n", sess); } - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); } if (sess && sess->local) { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 170af157121409..bad749561ec2ae 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl { int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, void *, uint8_t *, uint16_t); + void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool); struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, const uint16_t); struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 4752f65a9272a6..7fa0672f414e0d 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1468,6 +1468,78 @@ static int tcm_qla2xxx_check_initiator_node_acl( return 0; } +static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, + uint16_t loop_id, bool conf_compl_supported) +{ + struct qla_tgt *tgt = sess->tgt; + struct qla_hw_data *ha = tgt->ha; + struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; + struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; + struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, + struct tcm_qla2xxx_nacl, se_node_acl); + u32 key; + + + if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24) + pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n", + sess, + sess->port_name[0], sess->port_name[1], + sess->port_name[2], sess->port_name[3], + sess->port_name[4], sess->port_name[5], + sess->port_name[6], sess->port_name[7], + sess->loop_id, loop_id, + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, + s_id.b.domain, s_id.b.area, s_id.b.al_pa); + + if (sess->loop_id != loop_id) { + /* + * Because we can shuffle loop IDs around and we + * update different sessions non-atomically, we might + * have overwritten this session's old loop ID + * already, and we might end up overwriting some other + * session that will be updated later. So we have to + * be extra careful and we can't warn about those things... + */ + if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl) + lport->lport_loopid_map[sess->loop_id].se_nacl = NULL; + + lport->lport_loopid_map[loop_id].se_nacl = se_nacl; + + sess->loop_id = loop_id; + } + + if (sess->s_id.b24 != s_id.b24) { + key = (((u32) sess->s_id.b.domain << 16) | + ((u32) sess->s_id.b.area << 8) | + ((u32) sess->s_id.b.al_pa)); + + if (btree_lookup32(&lport->lport_fcport_map, key)) + WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl, + "Found wrong se_nacl when updating s_id %x:%x:%x\n", + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + else + WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n", + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + + key = (((u32) s_id.b.domain << 16) | + ((u32) s_id.b.area << 8) | + ((u32) s_id.b.al_pa)); + + if (btree_lookup32(&lport->lport_fcport_map, key)) { + WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n", + s_id.b.domain, s_id.b.area, s_id.b.al_pa); + btree_update32(&lport->lport_fcport_map, key, se_nacl); + } else { + btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC); + } + + sess->s_id = s_id; + nacl->nport_id = key; + } + + sess->conf_compl_supported = conf_compl_supported; +} + /* * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. */ @@ -1478,6 +1550,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .free_cmd = tcm_qla2xxx_free_cmd, .free_mcmd = tcm_qla2xxx_free_mcmd, .free_session = tcm_qla2xxx_free_session, + .update_sess = tcm_qla2xxx_update_sess, .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl, .find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id, .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, From c7b3b9dff21b8beb7f3f49719b58495d4f744379 Mon Sep 17 00:00:00 2001 From: Bernhard Kohl Date: Wed, 24 Oct 2012 15:53:58 +0200 Subject: [PATCH 0463/1071] target: reintroduce some obsolete SCSI-2 commands commit 1a1ff38c4cebf23be8bf0009a76b082a13bd25cb upstream. With kernel 3.6 some obsolete SCSI-2 commands including SEEK_10 have have been removed by commit 1fd032ee10d2816c947f5d5b9abda95e728f0a8f "target: move code for CDB emulation". There are still clients out there which use these old SCSI-2 commands. This mainly happens when running VMs with legacy guest systems, connected via SCSI command pass-through to iSCSI targets. Make them happy and return status GOOD. Many real SCSI disks or external iSCSI storage devices still support these old commands. So let's make LIO backward compatible as well. This patch adds support for the previously removed SEEK_10 and additionally the SEEK_6 and REZERO_UNIT commands. Signed-off-by: Bernhard Kohl Reviewed-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_sbc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a9dd9469e3bd4e..323e1922508320 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -128,6 +128,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd) return 0; } +static int sbc_emulate_noop(struct se_cmd *cmd) +{ + target_complete_cmd(cmd, GOOD); + return 0; +} + static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) { return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; @@ -524,6 +530,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) size = 0; cmd->execute_cmd = sbc_emulate_verify; break; + case REZERO_UNIT: + case SEEK_6: + case SEEK_10: + /* + * There are still clients out there which use these old SCSI-2 + * commands. This mainly happens when running VMs with legacy + * guest systems, connected via SCSI command pass-through to + * iSCSI targets. Make them happy and return status GOOD. + */ + size = 0; + cmd->execute_cmd = sbc_emulate_noop; + break; default: ret = spc_parse_cdb(cmd, &size); if (ret) From 2ec0fe7bd41bd500e58702291edc5f7285ada81e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 26 Oct 2012 15:35:45 -0700 Subject: [PATCH 0464/1071] target: Fix double-free of se_cmd in target_complete_tmr_failure commit e13d5fef88c40b87c8430f8274c3a9ca32ef90bc upstream. Fabric drivers currently expect to internally release se_cmd in the event of a TMR failure during target_submit_tmr(), which means the immediate call to transport_generic_free_cmd() after TFO->queue_tm_rsp() from within target_complete_tmr_failure() workqueue context is wrong. This is done as some fabrics expect TMR operations to be acknowledged before releasing the descriptor, so the assumption that core is releasing se_cmd associated TMR memory is incorrect. This fixes a OOPs where transport_generic_free_cmd() was being called more than once. This bug was originally observed with tcm_qla2xxx fabric ports. Signed-off-by: Nicholas Bellinger Cc: Christoph Hellwig Cc: Roland Dreier Cc: Andy Grover Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_transport.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 269f54488397bd..7502660abee50a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1553,7 +1553,6 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); - transport_generic_free_cmd(se_cmd, 0); } /** From b2c70f388db2633fdbfe14f28d2133dd580fbb33 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 19 Oct 2012 13:28:46 +0200 Subject: [PATCH 0465/1071] HID: microsoft: fix invalid rdesc for 3k kbd commit 3ccc60f9d8c39180c205dba1a020735bda1b2491 upstream. Microsoft Digital Media Keyboard 3000 has two interfaces, and the second one has a report descriptor with a bug. The second collection says: 05 01 -- global; usage page -- 01 -- Generic Desktop Controls 09 80 -- local; usage -- 80 -- System Control a1 01 -- main; collection -- 01 -- application 85 03 -- global; report ID -- 03 19 00 -- local; Usage Minimum -- 00 29 ff -- local; Usage Maximum -- ff 15 00 -- global; Logical Minimum -- 0 26 ff 00 -- global; Logical Maximum -- ff 81 00 -- main; input c0 -- main; End Collection I.e. it makes us think that there are all kinds of usages of system control. That the keyboard is a not only a keyboard, but also a joystick, mouse, gamepad, keypad, etc. The same as for the Wireless Desktop Receiver, this should be Physical Min/Max. So fix that appropriately. References: https://bugzilla.novell.com/show_bug.cgi?id=776834 Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-microsoft.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index e5c699b6c6f306..38999898d04193 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -29,22 +29,30 @@ #define MS_RDESC 0x08 #define MS_NOGET 0x10 #define MS_DUPLICATE_USAGES 0x20 +#define MS_RDESC_3K 0x40 -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + /* + * Microsoft Wireless Desktop Receiver (Model 1028) has + * 'Usage Min/Max' where it ought to have 'Physical Min/Max' + */ if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } + /* the same as above (s/usage/physical/) */ + if ((quirks & MS_RDESC_3K) && *rsize == 106 && + !memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, + &rdesc[94], 4)) { + rdesc[94] = 0x35; + rdesc[96] = 0x45; + } return rdesc; } @@ -193,7 +201,7 @@ static const struct hid_device_id ms_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), .driver_data = MS_PRESENTER }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), - .driver_data = MS_ERGONOMY }, + .driver_data = MS_ERGONOMY | MS_RDESC_3K }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), From 783250d700a2ab8d12040dec188b291328e13225 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 29 Oct 2012 09:03:07 +1000 Subject: [PATCH 0466/1071] drm/nouveau: silence modesetting spam on pre-gf8 chipsets commit cee59f15a60cc6269a25e3f6fbf1a577d6ab8115 upstream. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nv04_dac.c | 8 ++++---- drivers/gpu/drm/nouveau/nv04_dfp.c | 6 +++--- drivers/gpu/drm/nouveau/nv04_tv.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 38f19479417c89..09ac2753896110 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -210,7 +210,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { - NV_INFO(dev, "Load detected on head A\n"); + NV_DEBUG(dev, "Load detected on head A\n"); return connector_status_connected; } @@ -323,7 +323,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (nv17_dac_sample_load(encoder) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_INFO(dev, "Load detected on output %c\n", + NV_DEBUG(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); return connector_status_connected; } else { @@ -398,7 +398,7 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -447,7 +447,7 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on vga encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index c2675623b7cdf1..89640f211401ce 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,7 +476,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -519,7 +519,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", mode, nv_encoder->dcb->index); if (was_powersaving && is_powersaving_dpms(mode)) @@ -564,7 +564,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dfp_update_backlight(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 3eb605ddfd031b..4de1fbeb8497fb 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -69,7 +69,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) struct nv04_mode_state *state = &dev_priv->mode_reg; uint8_t crtc1A; - NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on TV encoder (output %d)\n", mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -162,7 +162,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } From 83dc21544384ae8db01cc1c1a159ae6594444534 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 1 Nov 2012 16:16:31 +1000 Subject: [PATCH 0467/1071] drm/nouveau: fix suspend/resume when in headless mode Backport of fixes from upstream commit: 9430738d80223a1cd791a2baa74fa170d3df1262 Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_drv.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 9a36f5f39b0644..1fcc69a77f6427 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -188,11 +188,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - NV_INFO(dev, "Disabling display...\n"); - nouveau_display_fini(dev); + if (dev->mode_config.num_crtc) { + NV_INFO(dev, "Disabling display...\n"); + nouveau_display_fini(dev); - NV_INFO(dev, "Disabling fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); + NV_INFO(dev, "Disabling fbcon...\n"); + nouveau_fbcon_set_suspend(dev, 1); + } NV_INFO(dev, "Unpinning framebuffer(s)...\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -359,10 +361,12 @@ nouveau_pci_resume(struct pci_dev *pdev) NV_ERROR(dev, "Could not pin/map cursor.\n"); } - nouveau_fbcon_set_suspend(dev, 0); - nouveau_fbcon_zfill_all(dev); + if (dev->mode_config.num_crtc) { + nouveau_fbcon_set_suspend(dev, 0); + nouveau_fbcon_zfill_all(dev); - nouveau_display_init(dev); + nouveau_display_init(dev); + } /* Force CLUT to get re-loaded during modeset */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { From 8c1118a286324e4c16352b317f4531e82ede021a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 1 Nov 2012 16:16:32 +1000 Subject: [PATCH 0468/1071] drm/nouveau: headless mode by default if pci class != vga display This is to prevent nouveau from taking over the console on headless boards such as Tesla. Backport of upstream commit: e412e95a268fa8544858ebfe066826b290430d51 Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_drv.c | 2 -- drivers/gpu/drm/nouveau/nouveau_state.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 1fcc69a77f6427..a06eb3d58a5d4f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -488,9 +488,7 @@ static int __init nouveau_init(void) #ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) nouveau_modeset = 0; - else #endif - nouveau_modeset = 1; } if (!nouveau_modeset) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index c61014442aa931..f5e95846b4c8ef 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -50,6 +50,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; + u32 pclass = dev->pdev->class >> 8; switch (dev_priv->chipset & 0xf0) { case 0x00: @@ -428,7 +429,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) } /* headless mode */ - if (nouveau_modeset == 2) { + if (nouveau_modeset == 2 || + (nouveau_modeset < 0 && pclass != PCI_CLASS_DISPLAY_VGA)) { engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nouveau_stub_init; From 3820288942d1c1524c3ee85cbf503fee1533cfc3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Nov 2012 09:57:06 +0100 Subject: [PATCH 0469/1071] Linux 3.6.6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6e4a00dccb9353..471b83c4e34473 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 5 +SUBLEVEL = 6 EXTRAVERSION = NAME = Terrified Chipmunk From 601a0cc3fedf6b731c6f5050f542db810c03033e Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Wed, 24 Oct 2012 12:39:02 +0100 Subject: [PATCH 0470/1071] xen/gntdev: don't leak memory from IOCTL_GNTDEV_MAP_GRANT_REF commit a67baeb77375199bbd842fa308cb565164dd1f19 upstream. map->kmap_ops allocated in gntdev_alloc_map() wasn't freed by gntdev_put_map(). Add a gntdev_free_map() helper function to free everything allocated by gntdev_alloc_map(). Signed-off-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/gntdev.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 7f1241608489de..9a113b714b47d9 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv, #endif } +static void gntdev_free_map(struct grant_map *map) +{ + if (map == NULL) + return; + + if (map->pages) + free_xenballooned_pages(map->count, map->pages); + kfree(map->pages); + kfree(map->grants); + kfree(map->map_ops); + kfree(map->unmap_ops); + kfree(map->kmap_ops); + kfree(map); +} + static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) { struct grant_map *add; @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) return add; err: - kfree(add->pages); - kfree(add->grants); - kfree(add->map_ops); - kfree(add->unmap_ops); - kfree(add->kmap_ops); - kfree(add); + gntdev_free_map(add); return NULL; } @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map) evtchn_put(map->notify.event); } - if (map->pages) { - if (!use_ptemod) - unmap_grant_pages(map, 0, map->count); - - free_xenballooned_pages(map->count, map->pages); - } - kfree(map->pages); - kfree(map->grants); - kfree(map->map_ops); - kfree(map->unmap_ops); - kfree(map); + if (map->pages && !use_ptemod) + unmap_grant_pages(map, 0, map->count); + gntdev_free_map(map); } /* ------------------------------------------------------------------ */ From 3f7a06d68337171fef9f8e7621a6d73777385619 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 31 Oct 2012 12:38:31 -0400 Subject: [PATCH 0471/1071] xen/mmu: Use Xen specific TLB flush instead of the generic one. commit 95a7d76897c1e7243d4137037c66d15cbf2cce76 upstream. As Mukesh explained it, the MMUEXT_TLB_FLUSH_ALL allows the hypervisor to do a TLB flush on all active vCPUs. If instead we were using the generic one (which ends up being xen_flush_tlb) we end up making the MMUEXT_TLB_FLUSH_LOCAL hypercall. But before we make that hypercall the kernel will IPI all of the vCPUs (even those that were asleep from the hypervisor perspective). The end result is that we needlessly wake them up and do a TLB flush when we can just let the hypervisor do it correctly. This patch gives around 50% speed improvement when migrating idle guest's from one host to another. Oracle-bug: 14630170 Tested-by: Jingjie Jiang Suggested-by: Mukesh Rathor Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/mmu.c | 21 ++++++++++++++++++++- include/trace/events/xen.h | 8 ++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 5141d808e7519d..dde1a3fc465a6d 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1215,6 +1215,25 @@ unsigned long xen_read_cr2_direct(void) return this_cpu_read(xen_vcpu_info.arch.cr2); } +void xen_flush_tlb_all(void) +{ + struct mmuext_op *op; + struct multicall_space mcs; + + trace_xen_mmu_flush_tlb_all(0); + + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); + + op = mcs.args; + op->cmd = MMUEXT_TLB_FLUSH_ALL; + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + + preempt_enable(); +} static void xen_flush_tlb(void) { struct mmuext_op *op; @@ -2366,7 +2385,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, err = 0; out: - flush_tlb_all(); + xen_flush_tlb_all(); return err; } diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 15ba03bdd7c69e..d06b6da5c1e3e1 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); +TRACE_EVENT(xen_mmu_flush_tlb_all, + TP_PROTO(int x), + TP_ARGS(x), + TP_STRUCT__entry(__array(char, x, 0)), + TP_fast_assign((void)x), + TP_printk("%s", "") + ); + TRACE_EVENT(xen_mmu_flush_tlb, TP_PROTO(int x), TP_ARGS(x), From c1f904197f775a3e88486e64d2802a142bbdfd0a Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 31 Oct 2012 22:30:54 +0000 Subject: [PATCH 0472/1071] ixgbe: PTP get_ts_info missing software support commit 50f8d35de8ba4af311ea1176c534e8b73bb198e5 upstream. This patch corrects the ethtool get_ts_info functon which did not state that software timestamping was supported, even though it is. Signed-off-by: Jacob Keller Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 56b20d17d0e4c5..116f0e901bee23 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev, case ixgbe_mac_X540: case ixgbe_mac_82599EB: info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; From e097213a658d3eda65f8cf1a6851eb4e4b6a10b9 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Tue, 30 Oct 2012 23:39:10 -0700 Subject: [PATCH 0473/1071] Input: tsc40 - remove wrong announcement of pressure support commit 32ed1911fc79908d704023317d4ddeb3883fd07e upstream. The tsc40 driver announces it supports the pressure event, but will never send one. The announcement will cause tslib to wait for such events and sending all touch events with a pressure of 0. Removing the announcement will make tslib fall back to emulating the pressure on touch events so everything works as expected. Signed-off-by: Rolf Eike Beer Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/tsc40.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 63209aaa55f01f..eb96f168fb9d53 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) __set_bit(BTN_TOUCH, input_dev->keybit); input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); - input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0); serio_set_drvdata(serio, ptsc); From cd585fb70b89fb57f8dffb03a2a72c30f81f5da6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Oct 2012 00:31:11 +0200 Subject: [PATCH 0474/1071] ath9k: fix stale pointers potentially causing access to free'd skbs commit 8c6e30936a7893a85f6222084f0f26aceb81137a upstream. bf->bf_next is only while buffers are chained as part of an A-MPDU in the tx queue. When a tid queue is flushed (e.g. on tearing down an aggregation session), frames can be enqueued again as normal transmission, without bf_next being cleared. This can lead to the old pointer being dereferenced again later. This patch might fix crashes and "Failed to stop TX DMA!" messages. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 423a9f375d1d42..15cef8df2bdf1b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) } bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + bf->bf_next = NULL; list_del(&bf->list); spin_unlock_bh(&sc->tx.txbuflock); @@ -1774,6 +1775,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, list_add_tail(&bf->list, &bf_head); bf->bf_state.bf_type = 0; + bf->bf_next = NULL; bf->bf_lastbf = bf; ath_tx_fill_desc(sc, bf, txq, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_head, false); From ec3559970271fe2b28f731dd8bf32c3ef5c0bc02 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Mon, 29 Oct 2012 13:25:20 +0100 Subject: [PATCH 0475/1071] ath9k: Test for TID only in BlockAcks while checking tx status commit 6fe7cc71bbf3a0bc28c9cec3c00bc11e81344412 upstream. The ath9k xmit functions for AMPDUs can send frames as non-aggregate in case only one frame is currently available. The client will then answer using a normal Ack instead of a BlockAck. This acknowledgement has no TID stored and therefore the hardware is not able to provide us the corresponding TID. The TID set by the hardware in the tx status descriptor has to be seen as undefined and not as a valid TID value for normal acknowledgements. Doing otherwise results in a massive amount of retransmissions and stalls of connections. Users may experience low bandwidth and complete connection stalls in environments with transfers using multiple TIDs. This regression was introduced in b11b160defc48e4daa283f785192ea3a23a51f8e ("ath9k: validate the TID in the tx status information"). Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich Acked-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 15cef8df2bdf1b..88b6acc04f48f0 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -394,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true; + bool rc_update = true, isba; struct ieee80211_tx_rate rates[4]; struct ath_frame_info *fi; int nframes; @@ -438,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(an, tidno); seq_first = tid->seq_start; + isba = ts->ts_flags & ATH9K_TX_BA; /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted + * + * Only BlockAcks have a TID and therefore normal Acks cannot be + * checked */ - if (tidno != ts->tid) + if (isba && tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); From 9fc9d86a23e2b5eb411c33d3bb8a8ee9a06f34d0 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 25 Oct 2012 09:51:39 +0200 Subject: [PATCH 0476/1071] rt2800: validate step value for temperature compensation commit bf7e1abe434ba9e22e8dc04a4cba4ab504b788b8 upstream. Some hardware has correct (!= 0xff) value of tssi_bounds[4] in the EEPROM, but step is equal to 0xff. This results on ridiculous delta calculations and completely broke TX power settings. Reported-and-tested-by: Pavel Lucik Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b93516d832fb56..1345bdd46f386d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2395,7 +2395,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) /* * Check if temperature compensation is supported. */ - if (tssi_bounds[4] == 0xff) + if (tssi_bounds[4] == 0xff || step == 0xff) return 0; /* From 3a62d0ff8b88d2ee9fe26f466a36d2145e6ac923 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:44 -0700 Subject: [PATCH 0477/1071] target: Don't return success from module_init() if setup fails commit 0d0f9dfb31e0a6c92063e235417b42df185b3275 upstream. If the call to core_dev_release_virtual_lun0() fails, then nothing sets ret to anything other than 0, so even though everything is torn down and freed, target_core_init_configfs() will seem to succeed and the module will be loaded. Fix this by passing the return value on up the chain. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_configfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 06aca11a94f220..ac0b69f93a5d72 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3214,7 +3214,8 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - if (core_dev_setup_virtual_lun0() < 0) + ret = core_dev_setup_virtual_lun0(); + if (ret < 0) goto out; return 0; From 323ef3123473ecaa03d248082e4107f0cc48b871 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:45 -0700 Subject: [PATCH 0478/1071] target: Avoid integer overflow in se_dev_align_max_sectors() commit 3e03989b5868acf69a391a424dc71fcd6cc48167 upstream. The expression (max_sectors * block_size) might overflow a u32 (indeed, since iblock sets max_hw_sectors to UINT_MAX, it is guaranteed to overflow and end up with a much-too-small result in many common cases). Fix this by doing an equivalent calculation that doesn't require multiplication. While we're touching this code, avoid splitting a printk format across two lines and use pr_info(...) instead of printk(KERN_INFO ...). Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_device.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 9fc9a6006ca082..68d4c10e720cc8 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev) static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) { - u32 tmp, aligned_max_sectors; + u32 aligned_max_sectors; + u32 alignment; /* * Limit max_sectors to a PAGE_SIZE aligned value for modern * transport_allocate_data_tasks() operation. */ - tmp = rounddown((max_sectors * block_size), PAGE_SIZE); - aligned_max_sectors = (tmp / block_size); - if (max_sectors != aligned_max_sectors) { - printk(KERN_INFO "Rounding down aligned max_sectors from %u" - " to %u\n", max_sectors, aligned_max_sectors); - return aligned_max_sectors; - } + alignment = max(1ul, PAGE_SIZE / block_size); + aligned_max_sectors = rounddown(max_sectors, alignment); + + if (max_sectors != aligned_max_sectors) + pr_info("Rounding down aligned max_sectors from %u to %u\n", + max_sectors, aligned_max_sectors); - return max_sectors; + return aligned_max_sectors; } void se_dev_set_default_attribs( From 10b43f97a965ccb8ec6c0e7a841eecceb4326f83 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:46 -0700 Subject: [PATCH 0479/1071] iscsi-target: Fix missed wakeup race in TX thread commit d5627acba9ae584cf4928af19f7ddf5f6837de32 upstream. The sleeping code in iscsi_target_tx_thread() is susceptible to the classic missed wakeup race: - TX thread finishes handle_immediate_queue() and handle_response_queue(), thinks both queues are empty. - Another thread adds a queue entry and does wake_up_process(), which does nothing because the TX thread is still awake. - TX thread does schedule_timeout() and sleeps forever. In practice this can kill an iSCSI connection if for example an initiator does single-threaded writes and the target misses the wakeup window when queueing an R2T; in this case the connection will be stuck until the initiator loses patience and does some task management operation (or kills the connection entirely). Fix this by converting to wait_event_interruptible(), which does not suffer from this sort of race. Signed-off-by: Roland Dreier Cc: Andy Grover Cc: Hannes Reinecke Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 4 +++- drivers/target/iscsi/iscsi_target_core.h | 1 + drivers/target/iscsi/iscsi_target_login.c | 1 + drivers/target/iscsi/iscsi_target_util.c | 22 ++++++++++++++++++++-- drivers/target/iscsi/iscsi_target_util.h | 1 + 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index dd4fce20ea886c..6b6f50a3e013e0 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3735,7 +3735,9 @@ int iscsi_target_tx_thread(void *arg) */ iscsit_thread_check_cpumask(conn, current, 1); - schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); + wait_event_interruptible(conn->queues_wq, + !iscsit_conn_all_queues_empty(conn) || + ts->status == ISCSI_THREAD_SET_RESET); if ((ts->status == ISCSI_THREAD_SET_RESET) || signal_pending(current)) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index a90294f8498cc3..1d63d566ef7a9a 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -486,6 +486,7 @@ struct iscsi_tmr_req { }; struct iscsi_conn { + wait_queue_head_t queues_wq; /* Authentication Successful for this connection */ u8 auth_complete; /* State connection is currently in */ diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 6aba4395e8d8ff..7b643ab03092ea 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -45,6 +45,7 @@ extern spinlock_t sess_idr_lock; static int iscsi_login_init_conn(struct iscsi_conn *conn) { + init_waitqueue_head(&conn->queues_wq); INIT_LIST_HEAD(&conn->conn_list); INIT_LIST_HEAD(&conn->conn_cmd_list); INIT_LIST_HEAD(&conn->immed_queue_list); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index b42cdeb153df6e..552f45a9fabf3c 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue( atomic_set(&conn->check_immediate_queue, 1); spin_unlock_bh(&conn->immed_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) @@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue( atomic_inc(&cmd->response_queue_count); spin_unlock_bh(&conn->response_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) @@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue( } } +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) +{ + bool empty; + + spin_lock_bh(&conn->immed_queue_lock); + empty = list_empty(&conn->immed_queue_list); + spin_unlock_bh(&conn->immed_queue_lock); + + if (!empty) + return empty; + + spin_lock_bh(&conn->response_queue_lock); + empty = list_empty(&conn->response_queue_list); + spin_unlock_bh(&conn->response_queue_lock); + + return empty; +} + void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) { struct iscsi_queue_req *qr, *qr_tmp; diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index e1c729b8a1c5bc..2ff9bbc5cafb70 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_ extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8); extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *); extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); extern void iscsit_release_cmd(struct iscsi_cmd *); extern void iscsit_free_cmd(struct iscsi_cmd *); From f2679244f79202bed2173078da75f62d0c28ae0a Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Wed, 31 Oct 2012 10:24:02 -0700 Subject: [PATCH 0480/1071] target: Fix incorrect usage of nested IRQ spinlocks in ABORT_TASK path commit ab74b3d62f05192bf8fb8f169e7999d1183b2e08 upstream. This patch changes core_tmr_abort_task() to use spin_lock -> spin_unlock around se_cmd->t_state_lock while spin_lock_irqsave is held via se_sess->sess_cmd_lock. Signed-off-by: Steve Hodgson Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_tmr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 1c59a3c23b2c1b..be75c4331a9222 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -140,15 +140,15 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %u\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - spin_lock_irq(&se_cmd->t_state_lock); + spin_lock(&se_cmd->t_state_lock); if (se_cmd->transport_state & CMD_T_COMPLETE) { printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); goto out; } se_cmd->transport_state |= CMD_T_ABORTED; - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); list_del_init(&se_cmd->se_cmd_list); kref_get(&se_cmd->cmd_kref); From c9cf63d6c6ed89271909d290689d55f53a62e8d3 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 31 Oct 2012 22:04:26 -0700 Subject: [PATCH 0481/1071] target: Re-add explict zeroing of INQUIRY bounce buffer memory commit dea5f0998aa82bdeca260b87c653db11e91329b2 upstream. This patch fixes a regression in spc_emulate_inquiry() code where the local scope bounce buffer was no longer getting it's memory zeroed, causing various problems with SCSI initiators that depend upon areas of INQUIRY EVPD=0x83 payload having been zeroed. This bug was introduced with the following v3.7-rc1 patch + CC'ed stable commit: commit ffe7b0e9326d9c68f5688bef691dd49f1e0d3651 Author: Paolo Bonzini Date: Fri Sep 7 17:30:38 2012 +0200 target: support zero allocation length in INQUIRY Go ahead and re-add the missing memset of bounce buffer memory to be copied into the outgoing se_cmd descriptor kmapped SGL payload. Reported-by: Kelsey Prantis Cc: Kelsey Prantis Cc: Paolo Bonzini Cc: Andy Grover Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_spc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 9229bd9ad61b3d..6fd434d3d7e477 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) unsigned char buf[SE_INQUIRY_BUF]; int p, ret; + memset(buf, 0, SE_INQUIRY_BUF); + if (dev == tpg->tpg_virt_lun0.lun_se_dev) buf[0] = 0x3f; /* Not connected */ else From fb86b3646c134640e9043a03b5972d07d09b86fe Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 17 Oct 2012 13:56:19 +0200 Subject: [PATCH 0482/1071] cfg80211: fix antenna gain handling commit c4a9fafc77a5318f5ed26c509bbcddf03e18c201 upstream. No driver initializes chan->max_antenna_gain to something sensible, and the only place where it is being used right now is inside ath9k. This leads to ath9k potentially using less tx power than it can use, which can decrease performance/range in some rare cases. Rather than going through every single driver, this patch initializes chan->orig_mag in wiphy_register(), ignoring whatever value the driver left in there. If a driver for some reason wishes to limit it independent from regulatory rulesets, it can do so internally. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index dcd64d5b07aadf..5797032e346619 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -506,8 +506,7 @@ int wiphy_register(struct wiphy *wiphy) for (i = 0; i < sband->n_channels; i++) { sband->channels[i].orig_flags = sband->channels[i].flags; - sband->channels[i].orig_mag = - sband->channels[i].max_antenna_gain; + sband->channels[i].orig_mag = INT_MAX; sband->channels[i].orig_mpwr = sband->channels[i].max_power; sband->channels[i].band = band; From eb0c3c845ee8fa519141c31f56fa2aaa902917c7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 25 Oct 2012 21:51:59 +0200 Subject: [PATCH 0483/1071] wireless: drop invalid mesh address extension frames commit 7dd111e8ee10cc6816669eabcad3334447673236 upstream. The mesh header can have address extension by a 4th or a 5th and 6th address, but never both. Drop such frames in 802.11 -> 802.3 conversion along with any frames that have the wrong extension. Reviewed-by: Javier Cardona Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/util.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/wireless/util.c b/net/wireless/util.c index 994e2f0cc7a8a1..5b88ff2d6a67ec 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -312,18 +312,15 @@ EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) { int ae = meshhdr->flags & MESH_FLAGS_AE; - /* 7.1.3.5a.2 */ + /* 802.11-2012, 8.2.4.7.3 */ switch (ae) { + default: case 0: return 6; case MESH_FLAGS_AE_A4: return 12; case MESH_FLAGS_AE_A5_A6: return 18; - case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): - return 24; - default: - return 6; } } @@ -373,6 +370,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A4) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), @@ -397,6 +396,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A5_A6) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A4) skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), From f7d0737b4c3912713a6fb381cde2e375c2ad4f0c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 24 Oct 2012 14:19:53 +0200 Subject: [PATCH 0484/1071] mac80211: use blacklist for duplicate IE check commit 9690fb169b433a66485c808e4fc352b8a0f8d866 upstream. Instead of the current whitelist which accepts duplicates only for the quiet and vendor IEs, use a blacklist of all IEs (that we currently parse) that can't be duplicated. This avoids detecting a beacon as corrupt in the future when new IEs are added that can be duplicated. Signed-off-by: Paul Stewart Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/util.c | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index c9b52f7cb396d2..1cfe6d56dcfa8c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -637,13 +637,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, break; } - if (id != WLAN_EID_VENDOR_SPECIFIC && - id != WLAN_EID_QUIET && - test_bit(id, seen_elems)) { - elems->parse_error = true; - left -= elen; - pos += elen; - continue; + switch (id) { + case WLAN_EID_SSID: + case WLAN_EID_SUPP_RATES: + case WLAN_EID_FH_PARAMS: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_CF_PARAMS: + case WLAN_EID_TIM: + case WLAN_EID_IBSS_PARAMS: + case WLAN_EID_CHALLENGE: + case WLAN_EID_RSN: + case WLAN_EID_ERP_INFO: + case WLAN_EID_EXT_SUPP_RATES: + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_HT_OPERATION: + case WLAN_EID_VHT_CAPABILITY: + case WLAN_EID_VHT_OPERATION: + case WLAN_EID_MESH_ID: + case WLAN_EID_MESH_CONFIG: + case WLAN_EID_PEER_MGMT: + case WLAN_EID_PREQ: + case WLAN_EID_PREP: + case WLAN_EID_PERR: + case WLAN_EID_RANN: + case WLAN_EID_CHANNEL_SWITCH: + case WLAN_EID_EXT_CHANSWITCH_ANN: + case WLAN_EID_COUNTRY: + case WLAN_EID_PWR_CONSTRAINT: + case WLAN_EID_TIMEOUT_INTERVAL: + if (test_bit(id, seen_elems)) { + elems->parse_error = true; + left -= elen; + pos += elen; + continue; + } + break; } if (calc_crc && id < 64 && (filter & (1ULL << id))) From f93b7f659e82603aaf64cce070b189f2aefcf41f Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Wed, 24 Oct 2012 12:43:30 -0700 Subject: [PATCH 0485/1071] mac80211: Only process mesh config header on frames that RA_MATCH commit 555cb715be8ef98b8ec362b23dfc254d432a35b1 upstream. Doing otherwise is wrong, and may wreak havoc on the mpp tables, specially if the frame is encrypted. Reported-by: Chaoxing Lin Signed-off-by: Javier Cardona Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0cb4edee6af5a4..3a194145c4d761 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1857,7 +1857,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) return RX_DROP_MONITOR; - if (!ieee80211_is_data(hdr->frame_control)) + if (!ieee80211_is_data(hdr->frame_control) || + !(status->rx_flags & IEEE80211_RX_RA_MATCH)) return RX_CONTINUE; if (!mesh_hdr->ttl) @@ -1901,9 +1902,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) } skb_set_queue_mapping(skb, q); - if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) - goto out; - if (!--mesh_hdr->ttl) { IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); return RX_DROP_MONITOR; From b954e1eecf9986c3ad62baa25a6939ac89d073da Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 25 Oct 2012 11:10:18 -0700 Subject: [PATCH 0486/1071] mac80211: don't inspect Sequence Control field on control frames commit f7fbf70ee9db6da6033ae50d100e017ac1f26555 upstream. Per IEEE Std. 802.11-2012, Sec 8.2.4.4.1, the sequence Control field is not present in control frames. We noticed this problem when processing Block Ack Requests. Signed-off-by: Javier Cardona Signed-off-by: Javier Lopez Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3a194145c4d761..1840ab56d0e7fb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1422,6 +1422,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *)rx->skb->data; fc = hdr->frame_control; + + if (ieee80211_is_ctl(fc)) + return RX_CONTINUE; + sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; From f630e56c8b16bb9dbbf92a1f30034d5cecf635ea Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 24 Oct 2012 18:29:49 +0200 Subject: [PATCH 0487/1071] DRM/Radeon: Fix Load Detection on legacy primary DAC. commit 83325d072185899b706de2956170b246585aaec9 upstream. An uninitialized variable led to broken load detection. Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index d16f50f696d937..dd402bb127a85e 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -651,6 +651,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; WREG32(RADEON_DAC_CNTL, tmp); + tmp = dac_macro_cntl; tmp &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B); From f9f1e4bbbde4036cd178cdd121f72a6d547502e4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 1 Nov 2012 13:47:09 +1000 Subject: [PATCH 0488/1071] drm/udl: fix stride issues scanning out stride != width*bpp commit 3916e1d71b62b120888aa50bcc8d9a6200fc19a7 upstream. When buffer sharing with the i915 and using a 1680x1050 monitor, the i915 gives is a 6912 buffer for the 6720 width, the code doesn't render this properly as it uses one value to set the base address for reading from the vmap and for where to start on the device. This fixes it by calculating the values correctly for the device and for the pixmap. No idea how I haven't seen this before now. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_drv.h | 2 +- drivers/gpu/drm/udl/udl_fb.c | 12 +++++++----- drivers/gpu/drm/udl/udl_transfer.c | 5 +++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index fccd361f7b50b4..87aa5f5d3c8865 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev, int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, u32 byte_width, int *ident_ptr, int *sent_ptr); int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index ce9a61179925cd..6f6ca50ada5856 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info, list_for_each_entry(cur, &fbdefio->pagelist, lru) { if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), - &urb, (char *) info->fix.smem_start, - &cmd, cur->index << PAGE_SHIFT, - PAGE_SIZE, &bytes_identical, &bytes_sent)) + &urb, (char *) info->fix.smem_start, + &cmd, cur->index << PAGE_SHIFT, + cur->index << PAGE_SHIFT, + PAGE_SIZE, &bytes_identical, &bytes_sent)) goto error; bytes_rendered += PAGE_SIZE; } @@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, for (i = y; i < y + height ; i++) { const int line_offset = fb->base.pitches[0] * i; const int byte_offset = line_offset + (x * bpp); - + const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); if (udl_render_hline(dev, bpp, &urb, (char *) fb->obj->vmapping, - &cmd, byte_offset, width * bpp, + &cmd, byte_offset, dev_byte_offset, + width * bpp, &bytes_identical, &bytes_sent)) goto error; } diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index b9320e2608dd55..fc1134416bccdb 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16( */ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, + u32 byte_width, int *ident_ptr, int *sent_ptr) { const u8 *line_start, *line_end, *next_pixel; - u32 base16 = 0 + (byte_offset / bpp) * 2; + u32 base16 = 0 + (device_byte_offset / bpp) * 2; struct urb *urb = *urb_ptr; u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; From 278cfcce7ee7805f570a3732f66c0fa8328d60c6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 21 Oct 2012 12:52:39 +0200 Subject: [PATCH 0489/1071] drm/i915: clear the entire sdvo infoframe buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b6e0e543f75729f207b9c72b0162ae61170635b2 upstream. Like in the case of native hdmi, which is fixed already in commit adf00b26d18e1b3570451296e03bcb20e4798cdd Author: Paulo Zanoni Date: Tue Sep 25 13:23:34 2012 -0300 drm/i915: make sure we write all the DIP data bytes we need to clear the entire sdvo buffer to avoid upsetting the display. Since infoframe buffer writing is now a bit more elaborate, extract it into it's own function. This will be useful if we ever get around to properly update the ELD for sdvo. Also #define proper names for the two buffer indexes with fixed usage. v2: Cite the right commit above, spotted by Paulo Zanoni. v3: I'm too stupid to paste the right commit. v4: Ben Hutchings noticed that I've failed to handle an underflow in my loop logic, breaking it for i >= length + 8. Since I've just lost C programmer license, use his solution. Also, make the frustrated 0-base buffer size a notch more clear. Reported-and-tested-by: Jürg Billeter Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732 Cc: Paulo Zanoni Cc: Ben Hutchings Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_sdvo.c | 62 +++++++++++++++++--------- drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 + 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 123afd357611a6..20cb52dfcb5a06 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -882,6 +882,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) } #endif +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, + unsigned if_index, uint8_t tx_rate, + uint8_t *data, unsigned length) +{ + uint8_t set_buf_index[2] = { if_index, 0 }; + uint8_t hbuf_size, tmp[8]; + int i; + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_INDEX, + set_buf_index, 2)) + return false; + + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, + &hbuf_size, 1)) + return false; + + /* Buffer size is 0 based, hooray! */ + hbuf_size++; + + DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", + if_index, length, hbuf_size); + + for (i = 0; i < hbuf_size; i += 8) { + memset(tmp, 0, 8); + if (i < length) + memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_DATA, + tmp, 8)) + return false; + } + + return intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_TXRATE, + &tx_rate, 1); +} + static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) { struct dip_infoframe avi_if = { @@ -889,11 +928,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) .ver = DIP_VERSION_AVI, .len = DIP_LEN_AVI, }; - uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; - uint8_t set_buf_index[2] = { 1, 0 }; uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; - uint64_t *data = (uint64_t *)sdvo_data; - unsigned i; intel_dip_infoframe_csum(&avi_if); @@ -903,22 +938,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) sdvo_data[3] = avi_if.checksum; memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_INDEX, - set_buf_index, 2)) - return false; - - for (i = 0; i < sizeof(sdvo_data); i += 8) { - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_DATA, - data, 8)) - return false; - data++; - } - - return intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_TXRATE, - &tx_rate, 1); + return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, + SDVO_HBUF_TX_VSYNC, + sdvo_data, sizeof(sdvo_data)); } static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee4347..770bdd6ecd9fb9 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { #define SDVO_CMD_SET_AUDIO_STAT 0x91 #define SDVO_CMD_GET_AUDIO_STAT 0x92 #define SDVO_CMD_SET_HBUF_INDEX 0x93 + #define SDVO_HBUF_INDEX_ELD 0 + #define SDVO_HBUF_INDEX_AVI_IF 1 #define SDVO_CMD_GET_HBUF_INDEX 0x94 #define SDVO_CMD_GET_HBUF_INFO 0x95 #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 From f21ebfa4b5fbf5ae1fa5ae92d1e49f31db54de83 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 22 Oct 2012 12:55:55 +0200 Subject: [PATCH 0490/1071] drm/i915: fix overlay on i830M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a9193983f4f292a82a00c72971c17ec0ee8c6c15 upstream. The overlay on the i830M has a peculiar failure mode: It works the first time around after boot-up, but consistenly hangs the second time it's used. Chris Wilson has dug out a nice errata: "1.5.12 Clock Gating Disable for Display Register Address Offset: 06200h–06203h "Bit 3 Ovrunit Clock Gating Disable. 0 = Clock gating controlled by unit enabling logic 1 = Disable clock gating function DevALM Errata ALM049: Overlay Clock Gating Must be Disabled: Overlay & L2 Cache clock gating must be disabled in order to prevent device hangs when turning off overlay.SW must turn off Ovrunit clock gating (6200h) and L2 Cache clock gating (C8h)." Now I've nowhere found that 0xc8 register and hence couldn't apply the l2 cache workaround. But I've remembered that part of the magic that the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache allocations so that the overlay scaler has some scratch space. And while pondering how that could explain the hang the 2nd time we enable the overlay, I've remembered that the old ums overlay code did _not_ issue the OVERLAY_OFF cmd. And indeed, disabling the OFF cmd results in the overlay working flawlessly, so I guess we can workaround the lack of the above workaround by simply never disabling the overlay engine once it's enabled. Note that we have the first part of the above w/a already implemented in i830_init_clock_gating - leave that as-is to avoid surprises. v2: Add a comment in the code. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827 Tested-by: Rhys Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_overlay.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 830d0dd610e127..cf49a57e2700c3 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -431,9 +431,17 @@ static int intel_overlay_off(struct intel_overlay *overlay) intel_ring_emit(ring, flip_addr); intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); /* turn overlay off */ - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); - intel_ring_emit(ring, flip_addr); - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + if (IS_I830(dev)) { + /* Workaround: Don't disable the overlay fully, since otherwise + * it dies on the next OVERLAY_ON cmd. */ + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_NOOP); + } else { + intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + intel_ring_emit(ring, flip_addr); + intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + } intel_ring_advance(ring); return intel_overlay_do_wait_request(overlay, request, From ec17483485122fbae70bb40d77aa1f0cf1916df2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 26 Oct 2012 12:06:41 +0100 Subject: [PATCH 0491/1071] drm/i915: Only kick out vesafb if we takeover the fbcon with KMS commit 1623392af9da983f3ad088a75076c9da05e5600d upstream. Otherwise we may remove the only console for a nomodeset system. We became more aggressive in our kicking with commit e188719a2891f01b3100dca4ae3a055fb5a7ab52 Author: Daniel Vetter Date: Tue Jun 12 11:28:17 2012 +0200 drm/i915: kick any firmware framebuffers before claiming the gtt Reported-and-tested-by: monnier@iro.umontreal.ca Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54615 Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 914c0dfabe6048..0969a7cbbba3bb 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1484,7 +1484,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto put_gmch; } - i915_kick_out_firmware_fb(dev_priv); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + i915_kick_out_firmware_fb(dev_priv); pci_set_master(dev->pdev); From 1d45cb149a2ad467d5454a01ec60bff38b0ddfe4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Oct 2012 00:33:36 +0200 Subject: [PATCH 0492/1071] mac80211: check management frame header length commit 4a4f1a5808c8bb0b72a4f6e5904c53fb8c9cd966 upstream. Due to pskb_may_pull() checking the skb length, all non-management frames are checked on input whether their 802.11 header is fully present. Also add that check for management frames and remove a check that is now duplicate. This prevents accessing skb data beyond the frame end. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1840ab56d0e7fb..3d8089b7fb5f39 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1430,7 +1430,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) frag = sc & IEEE80211_SCTL_FRAG; if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || - (rx->skb)->len < 24 || is_multicast_ether_addr(hdr->addr1))) { /* not fragmented */ goto out; @@ -2867,10 +2866,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) local->dot11ReceivedFragmentCount++; - if (ieee80211_is_mgmt(fc)) - err = skb_linearize(skb); - else + if (ieee80211_is_mgmt(fc)) { + /* drop frame if too short for header */ + if (skb->len < ieee80211_hdrlen(fc)) + err = -ENOBUFS; + else + err = skb_linearize(skb); + } else { err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); + } if (err) { dev_kfree_skb(skb); From 1db96611d45adcc0db12e8f16f78337757cc932e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Oct 2012 00:36:40 +0200 Subject: [PATCH 0493/1071] mac80211: verify that skb data is present commit 9b395bc3be1cebf0144a127c7e67d56dbdac0930 upstream. A number of places in the mesh code don't check that the frame data is present and in the skb header when trying to access. Add those checks and the necessary pskb_may_pull() calls. This prevents accessing data that doesn't actually exist. To do this, export ieee80211_get_mesh_hdrlen() to be able to use it in mac80211. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- include/net/cfg80211.h | 9 +++++++++ net/mac80211/rx.c | 32 +++++++++++++++++++++++++++++++- net/wireless/util.c | 3 ++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f10553c938a61a..fb5204bc5c0ee7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2632,6 +2632,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); */ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); +/** + * ieee80211_get_mesh_hdrlen - get mesh extension header length + * @meshhdr: the mesh extension header, only the flags field + * (first byte) will be accessed + * Returns the length of the extension header, which is always at + * least 6 bytes and at most 18 if address 5 and 6 are present. + */ +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); + /** * DOC: Data path helpers * diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3d8089b7fb5f39..6bd9ff8a834974 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -491,6 +491,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_action(hdr->frame_control)) { u8 category; + + /* make sure category field is present */ + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) + return RX_DROP_MONITOR; + mgmt = (struct ieee80211_mgmt *)hdr; category = mgmt->u.action.category; if (category != WLAN_CATEGORY_MESH_ACTION && @@ -1852,6 +1857,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *) skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); + + /* make sure fixed part of mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, hdrlen + 6)) + return RX_DROP_MONITOR; + + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + + /* make sure full mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, + hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) + return RX_DROP_MONITOR; + + /* reload pointers */ + hdr = (struct ieee80211_hdr *) skb->data; mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); /* frame is in RMC, don't forward */ @@ -1875,9 +1894,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(hdr->addr1)) { mpp_addr = hdr->addr3; proxied_addr = mesh_hdr->eaddr1; - } else { + } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { + /* has_a4 already checked in ieee80211_rx_mesh_check */ mpp_addr = hdr->addr4; proxied_addr = mesh_hdr->eaddr2; + } else { + return RX_DROP_MONITOR; } rcu_read_lock(); @@ -2314,6 +2336,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_SELF_PROTECTED: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.self_prot.action_code))) + break; + switch (mgmt->u.action.u.self_prot.action_code) { case WLAN_SP_MESH_PEERING_OPEN: case WLAN_SP_MESH_PEERING_CLOSE: @@ -2332,6 +2358,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_MESH_ACTION: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.mesh_action.action_code))) + break; + if (!ieee80211_vif_is_mesh(&sdata->vif)) break; if (mesh_action_is_path_sel(mgmt) && diff --git a/net/wireless/util.c b/net/wireless/util.c index 5b88ff2d6a67ec..09afde73c8e186 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -309,7 +309,7 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) } EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); -static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) { int ae = meshhdr->flags & MESH_FLAGS_AE; /* 802.11-2012, 8.2.4.7.3 */ @@ -323,6 +323,7 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) return 18; } } +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype) From 3a817522b33cb42171cd36f5fa77fa40f447f351 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Oct 2012 00:41:23 +0200 Subject: [PATCH 0494/1071] mac80211: make sure data is accessible in EAPOL check commit 6dbda2d00d466225f9db1dc695ff852443f28832 upstream. The code to allow EAPOL frames even when the station isn't yet marked associated needs to check that the incoming frame is long enough and due to paged RX it also can't assume skb->data contains the right data, it must use skb_copy_bits(). Fix this to avoid using data that doesn't really exist. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6bd9ff8a834974..37fe5cec58e638 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -848,14 +848,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) */ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && ieee80211_is_data_present(hdr->frame_control)) { - u16 ethertype; - u8 *payload; - - payload = rx->skb->data + - ieee80211_hdrlen(hdr->frame_control); - ethertype = (payload[6] << 8) | payload[7]; - if (cpu_to_be16(ethertype) == - rx->sdata->control_port_protocol) + unsigned int hdrlen; + __be16 ethertype; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + + if (rx->skb->len < hdrlen + 8) + return RX_DROP_MONITOR; + + skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); + if (ethertype == rx->sdata->control_port_protocol) return RX_CONTINUE; } From 0355494503b5922528b72a129de874bbe526f9c7 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Fri, 26 Oct 2012 18:54:25 +0200 Subject: [PATCH 0495/1071] mac80211: fix SSID copy on IBSS JOIN commit badecb001a310408d3473b1fc2ed5aefd0bc92a9 upstream. The 'ssid' field of the cfg80211_ibss_params is a u8 pointer and its length is likely to be less than IEEE80211_MAX_SSID_LEN most of the time. This patch fixes the ssid copy in ieee80211_ibss_join() by using the SSID length to prevent it from reading beyond the string. Signed-off-by: Antonio Quartulli [rewrapped commit message, small rewording] Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5746d62faba195..327aa076c2bb89 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1074,7 +1074,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; sdata->u.ibss.ibss_join_req = jiffies; - memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); + memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); sdata->u.ibss.ssid_len = params->ssid_len; mutex_unlock(&sdata->u.ibss.mtx); From ce91677037f6eea25a03616d70e0e31ba1e129de Mon Sep 17 00:00:00 2001 From: Scott Mayhew Date: Tue, 16 Oct 2012 13:22:19 -0400 Subject: [PATCH 0496/1071] nfsv3: Make v3 mounts fail with ETIMEDOUTs instead EIO on mountd timeouts commit acce94e68a0f346115fd41cdc298197d2d5a59ad upstream. In very busy v3 environment, rpc.mountd can respond to the NULL procedure but not the MNT procedure in a timely manner causing the MNT procedure to time out. The problem is the mount system call returns EIO which causes the mount to fail, instead of ETIMEDOUT, which would cause the mount to be retried. This patch sets the RPC_TASK_SOFT|RPC_TASK_TIMEOUT flags to the rpc_call_sync() call in nfs_mount() which causes ETIMEDOUT to be returned on timed out connections. Signed-off-by: Steve Dickson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/mount_clnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 8e65c7f1f87c52..015f71f8f62c27 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info) else msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; - status = rpc_call_sync(mnt_clnt, &msg, 0); + status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT); rpc_shutdown_client(mnt_clnt); if (status < 0) From 122532c9e1706da34036b688fb70c36c49ce2e44 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 21 Oct 2012 19:23:52 +0100 Subject: [PATCH 0497/1071] nfs: Show original device name verbatim in /proc/*/mount{s,info} commit 97a54868262da1629a3e65121e65b8e8c4419d9f upstream. Since commit c7f404b ('vfs: new superblock methods to override /proc/*/mount{s,info}'), nfs_path() is used to generate the mounted device name reported back to userland. nfs_path() always generates a trailing slash when the given dentry is the root of an NFS mount, but userland may expect the original device name to be returned verbatim (as it used to be). Make this canonicalisation optional and change the callers accordingly. [jrnieder@gmail.com: use flag instead of bool argument] Reported-and-tested-by: Chris Hiestand Reference: http://bugs.debian.org/669314 Signed-off-by: Ben Hutchings Signed-off-by: Jonathan Nieder Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/internal.h | 5 +++-- fs/nfs/namespace.c | 19 ++++++++++++++----- fs/nfs/nfs4namespace.c | 3 ++- fs/nfs/super.c | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 31fdb03225cd0e..e794deeada24dd 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -353,8 +353,9 @@ extern void nfs_sb_active(struct super_block *sb); extern void nfs_sb_deactive(struct super_block *sb); /* namespace.c */ +#define NFS_PATH_CANONICAL 1 extern char *nfs_path(char **p, struct dentry *dentry, - char *buffer, ssize_t buflen); + char *buffer, ssize_t buflen, unsigned flags); extern struct vfsmount *nfs_d_automount(struct path *path); struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *, struct nfs_fh *, struct nfs_fattr *); @@ -491,7 +492,7 @@ static inline char *nfs_devname(struct dentry *dentry, char *buffer, ssize_t buflen) { char *dummy; - return nfs_path(&dummy, dentry, buffer, buflen); + return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL); } /* diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 655925373b9161..dd057bc6b65b28 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; * @dentry - pointer to dentry * @buffer - result buffer * @buflen - length of buffer + * @flags - options (see below) * * Helper function for constructing the server pathname * by arbitrary hashed dentry. @@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; * This is mainly for use in figuring out the path on the * server side when automounting on top of an existing partition * and in generating /proc/mounts and friends. + * + * Supported flags: + * NFS_PATH_CANONICAL: ensure there is exactly one slash after + * the original device (export) name + * (if unset, the original name is returned verbatim) */ -char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) +char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, + unsigned flags) { char *end; int namelen; @@ -74,7 +81,7 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) rcu_read_unlock(); goto rename_retry; } - if (*end != '/') { + if ((flags & NFS_PATH_CANONICAL) && *end != '/') { if (--buflen < 0) { spin_unlock(&dentry->d_lock); rcu_read_unlock(); @@ -91,9 +98,11 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) return end; } namelen = strlen(base); - /* Strip off excess slashes in base string */ - while (namelen > 0 && base[namelen - 1] == '/') - namelen--; + if (flags & NFS_PATH_CANONICAL) { + /* Strip off excess slashes in base string */ + while (namelen > 0 && base[namelen - 1] == '/') + namelen--; + } buflen -= namelen; if (buflen < 0) { spin_unlock(&dentry->d_lock); diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 017b4b01a69c7a..c077b254ec9cb2 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end) static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) { char *limit; - char *path = nfs_path(&limit, dentry, buffer, buflen); + char *path = nfs_path(&limit, dentry, buffer, buflen, + NFS_PATH_CANONICAL); if (!IS_ERR(path)) { char *path_component = nfs_path_component(path, limit); if (path_component) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b8eda700584bfb..d8d73969c07b1d 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -765,7 +765,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root) int err = 0; if (!page) return -ENOMEM; - devname = nfs_path(&dummy, root, page, PAGE_SIZE); + devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0); if (IS_ERR(devname)) err = PTR_ERR(devname); else From 25ca7c2dea345aad2e10c07789fa9faea0cc7325 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 29 Oct 2012 18:53:23 -0400 Subject: [PATCH 0498/1071] NFSv4: nfs4_locku_done must release the sequence id commit 2b1bc308f492589f7d49012ed24561534ea2be8c upstream. If the state recovery machinery is triggered by the call to nfs4_async_handle_error() then we can deadlock. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d5a0cf15d3cbde..430798837a876c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4390,6 +4390,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) rpc_restart_call_prepare(task); } + nfs_release_seqid(calldata->arg.seqid); } static void nfs4_locku_prepare(struct rpc_task *task, void *data) From 48d959bea289f9d7d41f432f37048e54661e97f8 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 29 Oct 2012 18:37:40 -0400 Subject: [PATCH 0499/1071] NFSv4.1: We must release the sequence id when we fail to get a session slot commit 2240a9e2d013d8269ea425b73e1d7a54c7bc141f upstream. If we do not release the sequence id in cases where we fail to get a session slot, then we can deadlock if we hit a recovery scenario. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 430798837a876c..8ce449212fbb4b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1499,9 +1499,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, - &data->o_res.seq_res, task)) - return; - rpc_call_start(task); + &data->o_res.seq_res, + task) != 0) + nfs_release_seqid(data->o_arg.seqid); + else + rpc_call_start(task); return; unlock_no_action: rcu_read_unlock(); @@ -2182,9 +2184,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), &calldata->arg.seq_args, &calldata->res.seq_res, - task)) - goto out; - rpc_call_start(task); + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); out: dprintk("%s: done!\n", __func__); } @@ -4407,9 +4410,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) calldata->timestamp = jiffies; if (nfs4_setup_sequence(calldata->server, &calldata->arg.seq_args, - &calldata->res.seq_res, task)) - return; - rpc_call_start(task); + &calldata->res.seq_res, + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); } static const struct rpc_call_ops nfs4_locku_ops = { @@ -4554,7 +4559,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) /* Do we need to do an open_to_lock_owner? */ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) - return; + goto out_release_lock_seqid; data->arg.open_stateid = &state->stateid; data->arg.new_lock_owner = 1; data->res.open_seqid = data->arg.open_seqid; @@ -4563,10 +4568,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->server, &data->arg.seq_args, - &data->res.seq_res, task)) + &data->res.seq_res, + task) == 0) { + rpc_call_start(task); return; - rpc_call_start(task); - dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); + } + nfs_release_seqid(data->arg.open_seqid); +out_release_lock_seqid: + nfs_release_seqid(data->arg.lock_seqid); + dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); } static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) From 4ea7934b02fb03f2ca32c1fa254d4b2e929b9e8e Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 30 Oct 2012 16:06:35 -0400 Subject: [PATCH 0500/1071] NFS: Wait for session recovery to finish before returning commit 399f11c3d872bd748e1575574de265a6304c7c43 upstream. Currently, we will schedule session recovery and then return to the caller of nfs4_handle_exception. This works for most cases, but causes a hang on the following test case: Client Server ------ ------ Open file over NFS v4.1 Write to file Expire client Try to lock file The server will return NFS4ERR_BADSESSION, prompting the client to schedule recovery. However, the client will continue placing lock attempts and the open recovery never seems to be scheduled. The simplest solution is to wait for session recovery to run before retrying the lock. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8ce449212fbb4b..7bff8718c252e7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -331,8 +331,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc dprintk("%s ERROR: %d Reset session\n", __func__, errorcode); nfs4_schedule_session_recovery(clp->cl_session, errorcode); - exception->retry = 1; - break; + goto wait_on_recovery; #endif /* defined(CONFIG_NFS_V4_1) */ case -NFS4ERR_FILE_OPEN: if (exception->timeout > HZ) { From 1f7fbc9c3bec1d1657d2f9f44e653e3a91d39fab Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 31 Oct 2012 12:16:01 +1100 Subject: [PATCH 0501/1071] NFS: fix bug in legacy DNS resolver. commit 8d96b10639fb402357b75b055b1e82a65ff95050 upstream. The DNS resolver's use of the sunrpc cache involves a 'ttl' number (relative) rather that a timeout (absolute). This confused me when I wrote commit c5b29f885afe890f953f7f23424045cdad31d3e4 "sunrpc: use seconds since boot in expiry cache" and I managed to break it. The effect is that any TTL is interpreted as 0, and nothing useful gets into the cache. This patch removes the use of get_expiry() - which really expects an expiry time - and uses get_uint() instead, treating the int correctly as a ttl. This fixes a regression that has been present since 2.6.37, causing certain NFS accesses in certain environments to incorrectly fail. Reported-by: Chuck Lever Tested-by: Chuck Lever Signed-off-by: NeilBrown Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/dns_resolve.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 31c26c4dcc2381..ca4b11ec87a292 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) { char buf1[NFS_DNS_HOSTNAME_MAXLEN+1]; struct nfs_dns_ent key, *item; - unsigned long ttl; + unsigned int ttl; ssize_t len; int ret = -EINVAL; @@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) key.namelen = len; memset(&key.h, 0, sizeof(key.h)); - ttl = get_expiry(&buf); + if (get_uint(&buf, &ttl) < 0) + goto out; if (ttl == 0) goto out; key.h.expiry_time = ttl + seconds_since_boot(); From d736f6b4c9b302f5a4712ca81d06f8a9cd07a658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Wed, 17 Oct 2012 14:53:04 +0200 Subject: [PATCH 0502/1071] batman-adv: Fix broadcast packet CRC calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7f112af40fecf5399b61e69ffc6b55a9d82789f7 upstream. So far the crc16 checksum for a batman-adv broadcast data packet, received on a batman-adv hard interface, was calculated over zero bytes of its content leading to many incoming broadcast data packets wrongly being dropped (60-80% packet loss). This patch fixes this issue by calculating the crc16 over the actual, complete broadcast payload. The issue is a regression introduced by ("batman-adv: add broadcast duplicate check"). Signed-off-by: Linus Lüssing Acked-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Greg Kroah-Hartman --- net/batman-adv/bridge_loop_avoidance.c | 8 ++++---- net/batman-adv/routing.c | 8 +++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 6705d35b17cef3..e7b577743192db 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1205,8 +1205,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) /** * batadv_bla_check_bcast_duplist * @bat_priv: the bat priv with all the soft interface information - * @bcast_packet: originator mac address - * @hdr_size: maximum length of the frame + * @bcast_packet: encapsulated broadcast frame plus batman header + * @bcast_packet_len: length of encapsulated broadcast frame plus batman header * * check if it is on our broadcast list. Another gateway might * have sent the same packet because it is connected to the same backbone, @@ -1219,14 +1219,14 @@ int batadv_bla_init(struct batadv_priv *bat_priv) */ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, struct batadv_bcast_packet *bcast_packet, - int hdr_size) + int bcast_packet_len) { int i, length, curr; uint8_t *content; uint16_t crc; struct batadv_bcast_duplist_entry *entry; - length = hdr_size - sizeof(*bcast_packet); + length = bcast_packet_len - sizeof(*bcast_packet); content = (uint8_t *)bcast_packet; content += sizeof(*bcast_packet); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index bc2b88bbea1fb5..f861b7c2310a82 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1136,8 +1136,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, spin_unlock_bh(&orig_node->bcast_seqno_lock); + /* keep skb linear for crc calculation */ + if (skb_linearize(skb) < 0) + goto out; + + bcast_packet = (struct batadv_bcast_packet *)skb->data; + /* check whether this has been sent by another originator before */ - if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) + if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len)) goto out; /* rebroadcast packet */ From d3f95ba0cf4317f16d9dbb311fe6f817caf1cf7f Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Mon, 29 Oct 2012 17:35:00 +0000 Subject: [PATCH 0503/1071] drm: restore open_count if drm_setup fails commit 0f1cb1bd94a9c967cd4ad3de51cfdabe61eb5dcc upstream. If drm_setup (called at first open) fails, the whole open call has failed, so we should not keep the open_count incremented. Signed-off-by: Ilija Hadzic Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_fops.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 5062eec673f16e..5e3f29183bde66 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -135,8 +135,11 @@ int drm_open(struct inode *inode, struct file *filp) retcode = drm_open_helper(inode, filp, dev); if (!retcode) { atomic_inc(&dev->counts[_DRM_STAT_OPENS]); - if (!dev->open_count++) + if (!dev->open_count++) { retcode = drm_setup(dev); + if (retcode) + dev->open_count--; + } } if (!retcode) { mutex_lock(&dev->struct_mutex); From 14239ff83f3c9bde5d86fbb40c1cf039378fe6a7 Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Mon, 29 Oct 2012 17:35:01 +0000 Subject: [PATCH 0504/1071] drm: set dev_mapping before calling drm_open_helper commit fdb40a08ef7bc970899c3a1f471165f9c22763a1 upstream. Some drivers (specifically vmwgfx) look at dev_mapping in their open hook, so we have to set dev->dev_mapping earlier in the process. Reference: http://lists.freedesktop.org/archives/dri-devel/2012-October/029420.html Signed-off-by: Ilija Hadzic Reported-by: Thomas Hellstrom Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_fops.c | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 5e3f29183bde66..7aff5c7e4258f3 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp) int minor_id = iminor(inode); struct drm_minor *minor; int retcode = 0; + int need_setup = 0; + struct address_space *old_mapping; minor = idr_find(&drm_minors_idr, minor_id); if (!minor) @@ -132,26 +134,37 @@ int drm_open(struct inode *inode, struct file *filp) if (drm_device_is_unplugged(dev)) return -ENODEV; + if (!dev->open_count++) + need_setup = 1; + mutex_lock(&dev->struct_mutex); + old_mapping = dev->dev_mapping; + if (old_mapping == NULL) + dev->dev_mapping = &inode->i_data; + /* ihold ensures nobody can remove inode with our i_data */ + ihold(container_of(dev->dev_mapping, struct inode, i_data)); + inode->i_mapping = dev->dev_mapping; + filp->f_mapping = dev->dev_mapping; + mutex_unlock(&dev->struct_mutex); + retcode = drm_open_helper(inode, filp, dev); - if (!retcode) { - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); - if (!dev->open_count++) { - retcode = drm_setup(dev); - if (retcode) - dev->open_count--; - } - } - if (!retcode) { - mutex_lock(&dev->struct_mutex); - if (dev->dev_mapping == NULL) - dev->dev_mapping = &inode->i_data; - /* ihold ensures nobody can remove inode with our i_data */ - ihold(container_of(dev->dev_mapping, struct inode, i_data)); - inode->i_mapping = dev->dev_mapping; - filp->f_mapping = dev->dev_mapping; - mutex_unlock(&dev->struct_mutex); + if (retcode) + goto err_undo; + atomic_inc(&dev->counts[_DRM_STAT_OPENS]); + if (need_setup) { + retcode = drm_setup(dev); + if (retcode) + goto err_undo; } + return 0; +err_undo: + mutex_lock(&dev->struct_mutex); + filp->f_mapping = old_mapping; + inode->i_mapping = old_mapping; + iput(container_of(dev->dev_mapping, struct inode, i_data)); + dev->dev_mapping = old_mapping; + mutex_unlock(&dev->struct_mutex); + dev->open_count--; return retcode; } EXPORT_SYMBOL(drm_open); From 2553761e062594503006a7fad70ec0c25eadeb30 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 5 Nov 2012 21:54:39 +0100 Subject: [PATCH 0505/1071] hwmon: (w83627ehf) Force initial bank selection commit 3300fb4f88688029fff8dfb9ec0734f6e4cba3e7 upstream. Don't assume bank 0 is selected at device probe time. This may not be the case. Force bank selection at first register access to guarantee that we read the right registers upon driver loading. Signed-off-by: Jean Delvare Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83627ehf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 1821b7423d5b77..de3c7e04c3b5b2 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) mutex_init(&data->lock); mutex_init(&data->update_lock); data->name = w83627ehf_device_names[sio_data->kind]; + data->bank = 0xff; /* Force initial bank selection */ platform_set_drvdata(pdev, data); /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ From e3c3705cfd328885a6fc8a265c5949fbd243a2f7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:39:51 +0100 Subject: [PATCH 0506/1071] ALSA: PCM: Fix some races at disconnection commit 9b0573c07f278e9888c352aa9724035c75784ea0 upstream. Fix races at PCM disconnection: - while a PCM device is being opened or closed - while the PCM state is being changed without lock in prepare, hw_params, hw_free ops Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/pcm.c | 7 ++++++- sound/core/pcm_native.c | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 1a3070b4e5b5fc..099f3fdd120ada 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1086,11 +1086,15 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) if (list_empty(&pcm->list)) goto unlock; + mutex_lock(&pcm->open_mutex); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { + snd_pcm_stream_lock_irq(substream); if (substream->runtime) substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + snd_pcm_stream_unlock_irq(substream); + } list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_disconnect(pcm); } @@ -1106,6 +1110,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) } snd_unregister_device(devtype, pcm->card, pcm->device); } + mutex_unlock(&pcm->open_mutex); unlock: mutex_unlock(®ister_mutex); return 0; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 53b5ada8f7c36f..f0306435146c01 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) return usecs; } +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) +{ + snd_pcm_stream_lock_irq(substream); + if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) + substream->runtime->status->state = state; + snd_pcm_stream_unlock_irq(substream); +} + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, runtime->boundary *= 2; snd_pcm_timer_resolution_change(substream); - runtime->status->state = SNDRV_PCM_STATE_SETUP; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, /* hardware might be unusable from this time, so we force application to retry to set the correct hardware parameter settings */ - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); if (substream->ops->hw_free != NULL) substream->ops->hw_free(substream); return err; @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) return -EBADFD; if (substream->ops->hw_free) result = substream->ops->hw_free(substream); - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); pm_qos_remove_request(&substream->latency_pm_qos_req); return result; } @@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) { struct snd_pcm_runtime *runtime = substream->runtime; runtime->control->appl_ptr = runtime->status->hw_ptr; - runtime->status->state = SNDRV_PCM_STATE_PREPARED; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); } static struct action_ops snd_pcm_action_prepare = { From 35522de8494e895c621794f313a1c0526f1c18bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:39:52 +0100 Subject: [PATCH 0507/1071] ALSA: usb-audio: Fix races at disconnection commit 978520b75f0a1ce82b17e1e8186417250de6d545 upstream. Close some races at disconnection of a USB audio device by adding the chip->shutdown_mutex and chip->shutdown check at appropriate places. The spots to put bandaids are: - PCM prepare, hw_params and hw_free - where the usb device is accessed for communication or get speed, in mixer.c and others; the device speed is now cached in subs->speed instead of accessing to chip->dev The accesses in PCM open and close don't need the mutex protection because these are already handled in the core PCM disconnection code. The autosuspend/autoresume codes are still uncovered by this patch because of possible mutex deadlocks. They'll be covered by the upcoming change to rwsem. Also the mixer codes are untouched, too. These will be fixed in another patch, too. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.h | 1 + sound/usb/mixer.c | 65 ++++++++++++++++++++++++++++++---------------- sound/usb/pcm.c | 45 ++++++++++++++++++++++---------- sound/usb/proc.c | 4 +-- sound/usb/stream.c | 1 + 5 files changed, 79 insertions(+), 37 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index d9d2b5a3bf2fcb..6e262c594d2753 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -125,6 +125,7 @@ struct snd_usb_substream { struct snd_usb_endpoint *data_endpoint; struct snd_usb_endpoint *sync_endpoint; unsigned long flags; + unsigned int speed; /* USB_SPEED_XXX */ u64 formats; /* format bitmasks (all or'ed) */ unsigned int num_formats; /* number of supported audio formats (list) */ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fe56c9da38e9e6..c2ef11ccd66a4f 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v unsigned char buf[2]; int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; int timeout = 10; - int err; + int idx = 0, err; err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; + mutex_lock(&chip->shutdown_mutex); while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= val_len) { + validx, idx, buf, val_len) >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - snd_usb_autosuspend(cval->mixer->chip); - return 0; + err = 0; + goto out; } } - snd_usb_autosuspend(cval->mixer->chip); snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); - return -EINVAL; + request, validx, idx, cval->val_type); + err = -EINVAL; + + out: + mutex_unlock(&chip->shutdown_mutex); + snd_usb_autosuspend(cval->mixer->chip); + return err; } static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) @@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ unsigned char *val; - int ret, size; + int idx = 0, ret, size; __u8 bRequest; if (request == UAC_GET_CUR) { @@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + mutex_lock(&chip->shutdown_mutex); + if (chip->shutdown) + ret = -ENODEV; + else { + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, size); + validx, idx, buf, size); + } + mutex_unlock(&chip->shutdown_mutex); snd_usb_autosuspend(chip); if (ret < 0) { error: snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); + request, validx, idx, cval->val_type); return ret; } @@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, { struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2]; - int val_len, err, timeout = 10; + int idx = 0, val_len, err, timeout = 10; if (cval->mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - while (timeout-- > 0) + mutex_lock(&chip->shutdown_mutex); + while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= 0) { - snd_usb_autosuspend(chip); - return 0; + validx, idx, buf, val_len) >= 0) { + err = 0; + goto out; } - snd_usb_autosuspend(chip); + } snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); - return -EINVAL; + request, validx, idx, cval->val_type, buf[0], buf[1]); + err = -EINVAL; + + out: + mutex_unlock(&chip->shutdown_mutex); + snd_usb_autosuspend(chip); + return err; } static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index f782ce19bf5aa1..0de406a798f62a 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream unsigned int hwptr_done; subs = (struct snd_usb_substream *)substream->runtime->private_data; + if (subs->stream->chip->shutdown) + return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; substream->runtime->delay = snd_usb_pcm_delay(subs, @@ -471,8 +473,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, changed = subs->cur_audiofmt != fmt || subs->period_bytes != params_period_bytes(hw_params) || subs->cur_rate != rate; + + mutex_lock(&subs->stream->chip->shutdown_mutex); + if (subs->stream->chip->shutdown) { + ret = -ENODEV; + goto unlock; + } if ((ret = set_format(subs, fmt)) < 0) - return ret; + goto unlock; if (subs->cur_rate != rate) { struct usb_host_interface *alts; @@ -481,12 +489,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, alts = &iface->altsetting[fmt->altset_idx]; ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate); if (ret < 0) - return ret; + goto unlock; subs->cur_rate = rate; } if (changed) { - mutex_lock(&subs->stream->chip->shutdown_mutex); /* format changed */ stop_endpoints(subs, 0, 0, 0); ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, @@ -497,8 +504,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, if (subs->sync_endpoint) ret = snd_usb_endpoint_set_params(subs->sync_endpoint, hw_params, fmt, NULL); -unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); } if (ret == 0) { @@ -506,6 +511,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->altset_idx = fmt->altset_idx; } +unlock: + mutex_unlock(&subs->stream->chip->shutdown_mutex); return ret; } @@ -522,8 +529,10 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_rate = 0; subs->period_bytes = 0; mutex_lock(&subs->stream->chip->shutdown_mutex); - stop_endpoints(subs, 0, 1, 1); - deactivate_endpoints(subs); + if (!subs->stream->chip->shutdown) { + stop_endpoints(subs, 0, 1, 1); + deactivate_endpoints(subs); + } mutex_unlock(&subs->stream->chip->shutdown_mutex); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -537,14 +546,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usb_substream *subs = runtime->private_data; + int ret = 0; if (! subs->cur_audiofmt) { snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); return -ENXIO; } - if (snd_BUG_ON(!subs->data_endpoint)) - return -EIO; + mutex_lock(&subs->stream->chip->shutdown_mutex); + if (subs->stream->chip->shutdown) { + ret = -ENODEV; + goto unlock; + } + if (snd_BUG_ON(!subs->data_endpoint)) { + ret = -EIO; + goto unlock; + } /* some unit conversions in runtime */ subs->data_endpoint->maxframesize = @@ -562,9 +579,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* for playback, submit the URBs now; otherwise, the first hwptr_done * updates for all URBs would happen at the same time when starting */ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - return start_endpoints(subs, 1); + ret = start_endpoints(subs, 1); - return 0; + unlock: + mutex_unlock(&subs->stream->chip->shutdown_mutex); + return ret; } static struct snd_pcm_hardware snd_usb_hardware = @@ -617,7 +636,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, return 0; } /* check whether the period time is >= the data packet interval */ - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { + if (subs->speed != USB_SPEED_FULL) { ptime = 125 * (1 << fp->datainterval); if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); @@ -895,7 +914,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre return err; param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) + if (subs->speed == USB_SPEED_FULL) /* full speed devices have fixed data packet interval */ ptmin = 1000; if (ptmin == 1000) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index ebc1a5b5b3f1ba..d218f763501fcd 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } snd_iprintf(buffer, "\n"); } - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) + if (subs->speed != USB_SPEED_FULL) snd_iprintf(buffer, " Data packet interval: %d us\n", 125 * (1 << fp->datainterval)); // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); @@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs, return; snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", - snd_usb_get_speed(subs->dev) == USB_SPEED_FULL + subs->speed == USB_SPEED_FULL ? get_full_speed_hz(ep->freqm) : get_high_speed_hz(ep->freqm), ep->freqm >> 16, ep->freqm & 0xffff); diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 083ed81160e58b..1de0c8c002a8a2 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->direction = stream; subs->dev = as->chip->dev; subs->txfr_quirk = as->chip->txfr_quirk; + subs->speed = snd_usb_get_speed(subs->dev); snd_usb_set_pcm_ops(as->pcm, stream); From d8bd61294823b6e6604fc91217f9306685e11924 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:39:53 +0100 Subject: [PATCH 0508/1071] ALSA: usb-audio: Use rwsem for disconnect protection commit 34f3c89fda4fba9fe689db22253ca8db2f5e6386 upstream. Replace mutex with rwsem for codec->shutdown protection so that concurrent accesses are allowed. Also add the protection to snd_usb_autosuspend() and snd_usb_autoresume(), too. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.c | 12 ++++++++---- sound/usb/mixer.c | 12 ++++++------ sound/usb/pcm.c | 12 ++++++------ sound/usb/usbaudio.h | 2 +- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 4a469f0cb6d475..486b4a67772d3a 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, } mutex_init(&chip->mutex); - mutex_init(&chip->shutdown_mutex); + init_rwsem(&chip->shutdown_rwsem); chip->index = idx; chip->dev = dev; chip->card = card; @@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, card = chip->card; mutex_lock(®ister_mutex); - mutex_lock(&chip->shutdown_mutex); + down_write(&chip->shutdown_rwsem); chip->shutdown = 1; chip->num_interfaces--; if (chip->num_interfaces <= 0) { @@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - mutex_unlock(&chip->shutdown_mutex); + up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - mutex_unlock(&chip->shutdown_mutex); + up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); } } @@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) { int err = -ENODEV; + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) err = usb_autopm_get_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); return err; } void snd_usb_autosuspend(struct snd_usb_audio *chip) { + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) usb_autopm_put_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); } static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c2ef11ccd66a4f..298070e8f2d4e3 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -292,7 +292,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { if (chip->shutdown) break; @@ -310,7 +310,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v err = -EINVAL; out: - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(cval->mixer->chip); return err; } @@ -337,7 +337,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); if (chip->shutdown) ret = -ENODEV; else { @@ -346,7 +346,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, idx, buf, size); } - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); if (ret < 0) { @@ -453,7 +453,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { if (chip->shutdown) break; @@ -471,7 +471,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = -EINVAL; out: - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); return err; } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0de406a798f62a..ee3c15c546e035 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -474,7 +474,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->period_bytes != params_period_bytes(hw_params) || subs->cur_rate != rate; - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (subs->stream->chip->shutdown) { ret = -ENODEV; goto unlock; @@ -512,7 +512,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, } unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return ret; } @@ -528,12 +528,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (!subs->stream->chip->shutdown) { stop_endpoints(subs, 0, 1, 1); deactivate_endpoints(subs); } - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -553,7 +553,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) return -ENXIO; } - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (subs->stream->chip->shutdown) { ret = -ENODEV; goto unlock; @@ -582,7 +582,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) ret = start_endpoints(subs, 1); unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return ret; } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b8233ebe250f88..ef42797f56fb56 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,7 +37,7 @@ struct snd_usb_audio { struct usb_interface *pm_intf; u32 usb_id; struct mutex mutex; - struct mutex shutdown_mutex; + struct rw_semaphore shutdown_rwsem; unsigned int shutdown:1; unsigned int probing:1; unsigned int autosuspended:1; From 62edb372be14b3b7d6d80eaaa99d40134b53118d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:39:54 +0100 Subject: [PATCH 0509/1071] ALSA: usb-audio: Fix races at disconnection in mixer_quirks.c commit 888ea7d5ac6815ba16b3b3a20f665a92c7af6724 upstream. Similar like the previous commit, cover with chip->shutdown_rwsem and chip->shutdown checks. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/mixer_quirks.c | 58 +++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 690000db0ec01b..ae2b7143522097 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (value > 1) return -EINVAL; changed = value != mixer->audigy2nx_leds[index]; + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) { + err = -ENODEV; + goto out; + } if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, @@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, value, index + 2, NULL, 0); + out: + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->audigy2nx_leds[index] = value; @@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, for (i = 0; jacks[i].name; ++i) { snd_iprintf(buffer, "%s: ", jacks[i].name); - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = 0; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_rcvctrlpipe(mixer->chip->dev, 0), UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, jacks[i].unitid << 8, buf, 3); + up_read(&mixer->chip->shutdown_rwsem); if (err == 3 && (buf[0] == 3 || buf[0] == 6)) snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); else @@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, else new_status = old_status & ~0x02; changed = new_status != old_status; - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, 50, 0, &new_status, 1); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->xonar_u1_status = new_status; @@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u8 tmp; + int ret; - int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0, cpu_to_le16(wIndex), &tmp, sizeof(tmp), 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u16 wValue = ucontrol->value.integer.value[0]; + int ret; - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, cpu_to_le16(wValue), cpu_to_le16(wIndex), NULL, 0, 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, return -EINVAL; - err = snd_usb_ctl_msg(chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; @@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, if (!pval->is_cached) { /* Read current value */ - err = snd_usb_ctl_msg(chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; @@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, if (cur_val != new_val) { value[0] = new_val; value[1] = 0; - err = snd_usb_ctl_msg(chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; From f3ae49909bdf42b42f6ca619ff910366536e0f84 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:39:55 +0100 Subject: [PATCH 0510/1071] ALSA: Add a reference counter to card instance commit a0830dbd4e42b38aefdf3fb61ba5019a1a99ea85 upstream. For more strict protection for wild disconnections, a refcount is introduced to the card instance, and let it up/down when an object is referred via snd_lookup_*() in the open ops. The free-after-last-close check is also changed to check this refcount instead of the empty list, too. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- include/sound/core.h | 3 +++ sound/core/compress_offload.c | 9 +++++-- sound/core/control.c | 3 +++ sound/core/hwdep.c | 5 +++- sound/core/init.c | 50 +++++++++++++++++++++-------------- sound/core/oss/mixer_oss.c | 10 +++++-- sound/core/oss/pcm_oss.c | 2 ++ sound/core/pcm_native.c | 9 +++++-- sound/core/rawmidi.c | 6 ++++- sound/core/sound.c | 11 ++++++-- sound/core/sound_oss.c | 10 +++++-- 11 files changed, 86 insertions(+), 32 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index bc056687f647f7..93896ad1fcdd70 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -132,6 +132,7 @@ struct snd_card { int shutdown; /* this card is going down */ int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; + atomic_t refcount; /* refcount for disconnection */ struct device *dev; /* device assigned to this card */ struct device *card_dev; /* cardX object for sysfs */ @@ -189,6 +190,7 @@ struct snd_minor { const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ struct device *dev; /* device for sysfs */ + struct snd_card *card_ptr; /* assigned card instance */ }; /* return a device pointer linked to each sound device as a parent */ @@ -295,6 +297,7 @@ int snd_card_info_done(void); int snd_component_add(struct snd_card *card, const char *component); int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); +void snd_card_unref(struct snd_card *card); #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index eb60cb8dbb8a6f..d5103f78a336ca 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f) if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); + snd_card_unref(compr->card); return -EINVAL; } data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) + if (!data) { + snd_card_unref(compr->card); return -ENOMEM; + } data->stream.ops = compr->ops; data->stream.direction = dirn; data->stream.private_data = compr->private_data; @@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); if (!runtime) { kfree(data); + snd_card_unref(compr->card); return -ENOMEM; } runtime->state = SNDRV_PCM_STATE_OPEN; @@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) kfree(runtime); kfree(data); } - return ret; + snd_card_unref(compr->card); + return 0; } static int snd_compr_free(struct inode *inode, struct file *f) diff --git a/sound/core/control.c b/sound/core/control.c index 2487a6bb1c545a..151597b431af4b 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) write_lock_irqsave(&card->ctl_files_rwlock, flags); list_add_tail(&ctl->list, &card->ctl_files); write_unlock_irqrestore(&card->ctl_files_rwlock, flags); + snd_card_unref(card); return 0; __error: @@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(card, file); __error1: + if (card) + snd_card_unref(card); return err; } diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 75ea16f35b1aa1..53a6ba5ad615a5 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) if (hw == NULL) return -ENODEV; - if (!try_module_get(hw->card->module)) + if (!try_module_get(hw->card->module)) { + snd_card_unref(hw->card); return -EFAULT; + } init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); @@ -148,6 +150,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); + snd_card_unref(hw->card); return err; } diff --git a/sound/core/init.c b/sound/core/init.c index d8ec849af128ed..7b012d15c2cf15 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid, spin_lock_init(&card->files_lock); INIT_LIST_HEAD(&card->files_list); init_waitqueue_head(&card->shutdown_sleep); + atomic_set(&card->refcount, 0); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card) return 0; } +/** + * snd_card_unref - release the reference counter + * @card: the card instance + * + * Decrements the reference counter. When it reaches to zero, wake up + * the sleeper and call the destructor if needed. + */ +void snd_card_unref(struct snd_card *card) +{ + if (atomic_dec_and_test(&card->refcount)) { + wake_up(&card->shutdown_sleep); + if (card->free_on_last_close) + snd_card_do_free(card); + } +} +EXPORT_SYMBOL(snd_card_unref); + int snd_card_free_when_closed(struct snd_card *card) { - int free_now = 0; - int ret = snd_card_disconnect(card); - if (ret) - return ret; + int ret; - spin_lock(&card->files_lock); - if (list_empty(&card->files_list)) - free_now = 1; - else - card->free_on_last_close = 1; - spin_unlock(&card->files_lock); + atomic_inc(&card->refcount); + ret = snd_card_disconnect(card); + if (ret) { + atomic_dec(&card->refcount); + return ret; + } - if (free_now) + card->free_on_last_close = 1; + if (atomic_dec_and_test(&card->refcount)) snd_card_do_free(card); return 0; } @@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card) return ret; /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, list_empty(&card->files_list)); + wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); snd_card_do_free(card); return 0; } @@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENODEV; } list_add(&mfile->list, &card->files_list); + atomic_inc(&card->refcount); spin_unlock(&card->files_lock); return 0; } @@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add); int snd_card_file_remove(struct snd_card *card, struct file *file) { struct snd_monitor_file *mfile, *found = NULL; - int last_close = 0; spin_lock(&card->files_lock); list_for_each_entry(mfile, &card->files_list, list) { @@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) break; } } - if (list_empty(&card->files_list)) - last_close = 1; spin_unlock(&card->files_lock); - if (last_close) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } if (!found) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; } kfree(found); + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 18297f7f2c5582..05395aaeaa32a4 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) SNDRV_OSS_DEVICE_TYPE_MIXER); if (card == NULL) return -ENODEV; - if (card->mixer_oss == NULL) + if (card->mixer_oss == NULL) { + snd_card_unref(card); return -ENODEV; + } err = snd_card_file_add(card, file); - if (err < 0) + if (err < 0) { + snd_card_unref(card); return err; + } fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); if (fmixer == NULL) { snd_card_file_remove(card, file); + snd_card_unref(card); return -ENOMEM; } fmixer->card = card; @@ -68,6 +73,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) if (!try_module_get(card->module)) { kfree(fmixer); snd_card_file_remove(card, file); + snd_card_unref(card); return -EFAULT; } return 0; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd937..2529e01538e932 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2457,6 +2457,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(pcm->card, file); __error1: + if (pcm) + snd_card_unref(pcm->card); return err; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f0306435146c01..95043e32776a93 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1641,6 +1641,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) write_unlock_irq(&snd_pcm_link_rwlock); up_write(&snd_pcm_link_rwsem); _nolock: + snd_card_unref(substream1->pcm->card); fput(file); if (res < 0) kfree(group); @@ -2115,7 +2116,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_PLAYBACK); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + snd_card_unref(pcm->card); + return err; } static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2126,7 +2129,9 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_CAPTURE); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + snd_card_unref(pcm->card); + return err; } static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ebf6e49ad3d461..7d4f62ab67111f 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; - if (!try_module_get(rmidi->card->module)) + if (!try_module_get(rmidi->card->module)) { + snd_card_unref(rmidi->card); return -ENXIO; + } mutex_lock(&rmidi->open_mutex); card = rmidi->card; @@ -440,6 +442,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) #endif file->private_data = rawmidi_file; mutex_unlock(&rmidi->open_mutex); + snd_card_unref(rmidi->card); return 0; __error: @@ -447,6 +450,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) __error_card: mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); + snd_card_unref(rmidi->card); return err; } diff --git a/sound/core/sound.c b/sound/core/sound.c index 28f35593a75046..7c0640eeee521d 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -99,6 +99,10 @@ static void snd_request_other(int minor) * * Checks that a minor device with the specified type is registered, and returns * its user data pointer. + * + * This function increments the reference counter of the card instance + * if an associated instance with the given minor number and type is found. + * The caller must call snd_card_unref() appropriately later. */ void *snd_lookup_minor_data(unsigned int minor, int type) { @@ -109,9 +113,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_mutex); mreg = snd_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_mutex); return private_data; @@ -276,6 +282,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_mutex); #ifdef CONFIG_SND_DYNAMIC_MINORS minor = snd_find_free_minor(type); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index e9528333e36d01..e1d79ee3590650 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -40,6 +40,9 @@ static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; static DEFINE_MUTEX(sound_oss_mutex); +/* NOTE: This function increments the refcount of the associated card like + * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately + */ void *snd_lookup_oss_minor_data(unsigned int minor, int type) { struct snd_minor *mreg; @@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_oss_mutex); mreg = snd_oss_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_oss_mutex); return private_data; @@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_oss_mutex); snd_oss_minors[minor] = preg; minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); From 4a9f39ed6496dd4483ae5010e0848d45a89fd278 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:39:56 +0100 Subject: [PATCH 0511/1071] ALSA: Avoid endless sleep after disconnect commit 0914f7961babbf28aaa2f19b453951fb4841c03f upstream. When disconnect callback is called, each component should wake up sleepers and check card->shutdown flag for avoiding the endless sleep blocking the proper resource release. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/control.c | 2 ++ sound/core/hwdep.c | 7 +++++++ sound/core/oss/pcm_oss.c | 4 ++++ sound/core/pcm.c | 6 +++++- sound/core/pcm_native.c | 8 ++++++++ sound/core/rawmidi.c | 20 ++++++++++++++++++++ 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/sound/core/control.c b/sound/core/control.c index 151597b431af4b..daa4fc8872f3af 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1436,6 +1436,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, spin_unlock_irq(&ctl->read_lock); schedule(); remove_wait_queue(&ctl->change_sleep, &wait); + if (ctl->card->shutdown) + return -ENODEV; if (signal_pending(current)) return -ERESTARTSYS; spin_lock_irq(&ctl->read_lock); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 53a6ba5ad615a5..3f7f6628cf7b17 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -131,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); schedule(); mutex_lock(&hw->open_mutex); + if (hw->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -462,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) mutex_unlock(®ister_mutex); return -EINVAL; } + mutex_lock(&hwdep->open_mutex); + wake_up(&hwdep->open_wait); #ifdef CONFIG_SND_OSSEMUL if (hwdep->ossreg) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del_init(&hwdep->list); + mutex_unlock(&hwdep->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 2529e01538e932..f337b66a020b5b 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 099f3fdd120ada..e30e1be30a2147 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1087,12 +1087,16 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) goto unlock; mutex_lock(&pcm->open_mutex); + wake_up(&pcm->open_wait); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { snd_pcm_stream_lock_irq(substream); - if (substream->runtime) + if (substream->runtime) { substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + wake_up(&substream->runtime->sleep); + wake_up(&substream->runtime->tsleep); + } snd_pcm_stream_unlock_irq(substream); } list_for_each_entry(notify, &snd_pcm_notify_list, list) { diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 95043e32776a93..d15e5be2ae1bd2 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1518,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); remove_wait_queue(&to_check->sleep, &wait); + if (card->shutdown) { + result = -ENODEV; + break; + } if (tout == 0) { if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; @@ -2168,6 +2172,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 7d4f62ab67111f..1bb95aeea084d3 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -424,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) mutex_unlock(&rmidi->open_mutex); schedule(); mutex_lock(&rmidi->open_mutex); + if (rmidi->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -995,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_unlock_irq(&runtime->lock); schedule(); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail) @@ -1238,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, spin_unlock_irq(&runtime->lock); timeout = schedule_timeout(30 * HZ); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail && !timeout) @@ -1613,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) static int snd_rawmidi_dev_disconnect(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; + int dir; mutex_lock(®ister_mutex); + mutex_lock(&rmidi->open_mutex); + wake_up(&rmidi->open_wait); list_del_init(&rmidi->list); + for (dir = 0; dir < 2; dir++) { + struct snd_rawmidi_substream *s; + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { + if (s->runtime) + wake_up(&s->runtime->sleep); + } + } + #ifdef CONFIG_SND_OSSEMUL if (rmidi->ossreg) { if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1630,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) } #endif /* CONFIG_SND_OSSEMUL */ snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); + mutex_unlock(&rmidi->open_mutex); mutex_unlock(®ister_mutex); return 0; } From f1d2d8a9f14c93996ebeb28e1da98b4eb025f88b Mon Sep 17 00:00:00 2001 From: Zijie Pan Date: Mon, 15 Oct 2012 03:56:39 +0000 Subject: [PATCH 0512/1071] sctp: fix call to SCTP_CMD_PROCESS_SACK in sctp_cmd_interpreter() [ Upstream commit f6e80abeab928b7c47cc1fbf53df13b4398a2bec ] Bug introduced by commit edfee0339e681a784ebacec7e8c2dc97dc6d2839 (sctp: check src addr when processing SACK to update transport state) Signed-off-by: Zijie Pan Signed-off-by: Nicolas Dichtel Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/sm_sideeffect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index fe99628e1257bd..b1c5be3f82e023 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1634,8 +1634,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, asoc->outqueue.outstanding_bytes; sackh.num_gap_ack_blocks = 0; sackh.num_dup_tsns = 0; + chunk->subh.sack_hdr = &sackh; sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, - SCTP_SACKH(&sackh)); + SCTP_CHUNK(chunk)); break; case SCTP_CMD_DISCARD_PACKET: From 400b8b8c0bc217c72caef1b980f218a0e3662a9a Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 17 Oct 2012 21:17:44 +0000 Subject: [PATCH 0513/1071] ipv4: Fix flushing of cached routing informations [ Upstream commit 13d82bf50dce632355fcccafa4fe44a9b5e706d8 ] Currently we can not flush cached pmtu/redirect informations via the ipv4_sysctl_rtcache_flush sysctl. We need to check the rt_genid of the old route and reset the nh exeption if the old route is expired when we bind a new route to a nh exeption. Signed-off-by: Steffen Klassert Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 2a1383c10fb28b..c017cb1634e571 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1166,8 +1166,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, spin_lock_bh(&fnhe_lock); if (daddr == fnhe->fnhe_daddr) { - struct rtable *orig; - + struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); + if (orig && rt_is_expired(orig)) { + fnhe->fnhe_gw = 0; + fnhe->fnhe_pmtu = 0; + fnhe->fnhe_expires = 0; + } if (fnhe->fnhe_pmtu) { unsigned long expires = fnhe->fnhe_expires; unsigned long diff = expires - jiffies; @@ -1184,7 +1188,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, } else if (!rt->rt_gateway) rt->rt_gateway = daddr; - orig = rcu_dereference(fnhe->fnhe_rth); rcu_assign_pointer(fnhe->fnhe_rth, rt); if (orig) rt_free(orig); From dd2a911bc67a0c2ccf80f89f9aeb8e26fcd45ab1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Oct 2012 03:21:55 +0000 Subject: [PATCH 0514/1071] netlink: use kfree_rcu() in netlink_release() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 6d772ac5578f711d1ce7b03535d1c95bffb21dff ] On some suspend/resume operations involving wimax device, we have noticed some intermittent memory corruptions in netlink code. Stéphane Marchesin tracked this corruption in netlink_update_listeners() and suggested a patch. It appears netlink_release() should use kfree_rcu() instead of kfree() for the listeners structure as it may be used by other cpus using RCU protection. netlink_release() must set to NULL the listeners pointer when it is about to be freed. Also have to protect netlink_update_listeners() and netlink_has_listeners() if listeners is NULL. Add a nl_deref_protected() lockdep helper to properly document which locks protects us. Reported-by: Jonathan Kliegman Signed-off-by: Eric Dumazet Cc: Stéphane Marchesin Cc: Sam Leffler Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netlink/af_netlink.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9172179becfb2c..0426b677dbb787 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk); static DEFINE_RWLOCK(nl_table_lock); static atomic_t nl_table_users = ATOMIC_INIT(0); +#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); + static ATOMIC_NOTIFIER_HEAD(netlink_chain); static inline u32 netlink_group_mask(u32 group) @@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk) struct hlist_node *node; unsigned long mask; unsigned int i; + struct listeners *listeners; + + listeners = nl_deref_protected(tbl->listeners); + if (!listeners) + return; for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { mask = 0; @@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk) if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) mask |= nlk_sk(sk)->groups[i]; } - tbl->listeners->masks[i] = mask; + listeners->masks[i] = mask; } /* this function is only called with the netlink table "grabbed", which * makes sure updates are visible before bind or setsockopt return. */ @@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock) if (netlink_is_kernel(sk)) { BUG_ON(nl_table[sk->sk_protocol].registered == 0); if (--nl_table[sk->sk_protocol].registered == 0) { - kfree(nl_table[sk->sk_protocol].listeners); + struct listeners *old; + + old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); + RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); + kfree_rcu(old, rcu); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].registered = 0; } @@ -978,7 +989,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) rcu_read_lock(); listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); - if (group - 1 < nl_table[sk->sk_protocol].groups) + if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) res = test_bit(group - 1, listeners->masks); rcu_read_unlock(); @@ -1620,7 +1631,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); if (!new) return -ENOMEM; - old = rcu_dereference_protected(tbl->listeners, 1); + old = nl_deref_protected(tbl->listeners); memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); rcu_assign_pointer(tbl->listeners, new); From 48ff12fe363a34b854b1703ecb62d57cf9c65e9c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Oct 2012 09:14:12 +0000 Subject: [PATCH 0515/1071] tcp: fix FIONREAD/SIOCINQ [ Upstream commit a3374c42aa5f7237e87ff3b0622018636b0c847e ] tcp_ioctl() tries to take into account if tcp socket received a FIN to report correct number bytes in receive queue. But its flaky because if the application ate the last skb, we return 1 instead of 0. Correct way to detect that FIN was received is to test SOCK_DONE. Reported-by: Elliot Hughes Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Tom Herbert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5f641934182163..49dd9930781533 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -548,14 +548,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) !tp->urg_data || before(tp->urg_seq, tp->copied_seq) || !before(tp->urg_seq, tp->rcv_nxt)) { - struct sk_buff *skb; answ = tp->rcv_nxt - tp->copied_seq; - /* Subtract 1, if FIN is in queue. */ - skb = skb_peek_tail(&sk->sk_receive_queue); - if (answ && skb) - answ -= tcp_hdr(skb)->fin; + /* Subtract 1, if FIN was received */ + if (answ && sock_flag(sk, SOCK_DONE)) + answ--; } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); From 7a77dd0168e94667ca4f44a33721380dfc1fd104 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 22 Oct 2012 09:03:40 +0000 Subject: [PATCH 0516/1071] net: fix secpath kmemleak [ Upstream commit 3d861f661006606bf159fd6bd973e83dbf21d0f9 ] Mike Kazantsev found 3.5 kernels and beyond were leaking memory, and tracked the faulty commit to a1c7fff7e18f59e ("net: netdev_alloc_skb() use build_skb()") While this commit seems fine, it uncovered a bug introduced in commit bad43ca8325 ("net: introduce skb_try_coalesce()), in function kfree_skb_partial()"): If head is stolen, we free the sk_buff, without removing references on secpath (skb->sp). So IPsec + IP defrag/reassembly (using skb coalescing), or TCP coalescing could leak secpath objects. Fix this bug by calling skb_release_head_state(skb) to properly release all possible references to linked objects. Reported-by: Mike Kazantsev Signed-off-by: Eric Dumazet Bisected-by: Mike Kazantsev Tested-by: Mike Kazantsev Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/skbuff.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ef172afd3a8b43..97087775b1b350 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3384,10 +3384,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding); void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) { - if (head_stolen) + if (head_stolen) { + skb_release_head_state(skb); kmem_cache_free(skbuff_head_cache, skb); - else + } else { __kfree_skb(skb); + } } EXPORT_SYMBOL(kfree_skb_partial); From f84e04295509a11acae9efa3a8ab03e236c18886 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Wed, 24 Oct 2012 14:01:18 +0800 Subject: [PATCH 0517/1071] ipv6: Set default hoplimit as zero. [ Upstream commit 14edd87dc67311556f1254a8f29cf4dd6cb5b7d1 ] Commit a02e4b7dae4551(Demark default hoplimit as zero) only changes the hoplimit checking condition and default value in ip6_dst_hoplimit, not zeros all hoplimit default value. Keep the zeroing ip6_template_metrics[RTAX_HOPLIMIT - 1] to force it as const, cause as a37e6e344910(net: force dst_default_metrics to const section) Signed-off-by: Li RongQing Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 46eff4238e367d..070a3ce0e3d527 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { }; static const u32 ip6_template_metrics[RTAX_MAX] = { - [RTAX_HOPLIMIT - 1] = 255, + [RTAX_HOPLIMIT - 1] = 0, }; static struct rt6_info ip6_null_entry_template = { @@ -1241,7 +1241,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; - dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); spin_lock_bh(&icmp6_dst_lock); rt->dst.next = icmp6_dst_gc_list; From ed6f958d9875c2198c247ee568a9a9e9741a64ee Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 25 Oct 2012 18:17:54 +0000 Subject: [PATCH 0518/1071] net: usb: Fix memory leak on Tx data path [ Upstream commit 39707c2a3ba5011038b363f84d37c8a98d2d9db1 ] Driver anchors the tx urbs and defers the urb submission if a transmit request comes when the interface is suspended. Anchoring urb increments the urb reference count. These deferred urbs are later accessed by calling usb_get_from_anchor() for submission during interface resume. usb_get_from_anchor() unanchors the urb but urb reference count remains same. This causes the urb reference count to remain non-zero after usb_free_urb() gets called and urb never gets freed. Hence call usb_put_urb() after anchoring the urb to properly balance the reference count for these deferred urbs. Also, unanchor these deferred urbs during disconnect, to free them up. Signed-off-by: Hemant Kumar Acked-by: Oliver Neukum Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/usbnet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index fc9f578a1e253a..9c382b5f5ed01d 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1158,6 +1158,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, usb_anchor_urb(urb, &dev->deferred); /* no use to process more packets */ netif_stop_queue(net); + usb_put_urb(urb); spin_unlock_irqrestore(&dev->txq.lock, flags); netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; @@ -1310,6 +1311,8 @@ void usbnet_disconnect (struct usb_interface *intf) cancel_work_sync(&dev->kevent); + usb_scuttle_anchored_urbs(&dev->deferred); + if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); From b80dd87f485767f1e1c809620329e7337f178410 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Wed, 31 Oct 2012 02:45:32 +0000 Subject: [PATCH 0519/1071] net: fix divide by zero in tcp algorithm illinois [ Upstream commit 8f363b77ee4fbf7c3bbcf5ec2c5ca482d396d664 ] Reading TCP stats when using TCP Illinois congestion control algorithm can cause a divide by zero kernel oops. The division by zero occur in tcp_illinois_info() at: do_div(t, ca->cnt_rtt); where ca->cnt_rtt can become zero (when rtt_reset is called) Steps to Reproduce: 1. Register tcp_illinois: # sysctl -w net.ipv4.tcp_congestion_control=illinois 2. Monitor internal TCP information via command "ss -i" # watch -d ss -i 3. Establish new TCP conn to machine Either it fails at the initial conn, or else it needs to wait for a loss or a reset. This is only related to reading stats. The function avg_delay() also performs the same divide, but is guarded with a (ca->cnt_rtt > 0) at its calling point in update_params(). Thus, simply fix tcp_illinois_info(). Function tcp_illinois_info() / get_info() is called without socket lock. Thus, eliminate any race condition on ca->cnt_rtt by using a local stack variable. Simply reuse info.tcpv_rttcnt, as its already set to ca->cnt_rtt. Function avg_delay() is not affected by this race condition, as its called with the socket lock. Cc: Petr Matousek Signed-off-by: Jesper Dangaard Brouer Acked-by: Eric Dumazet Acked-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_illinois.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fece7..834857f3c8713e 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, .tcpv_rttcnt = ca->cnt_rtt, .tcpv_minrtt = ca->base_rtt, }; - u64 t = ca->sum_rtt; - do_div(t, ca->cnt_rtt); - info.tcpv_rtt = t; + if (info.tcpv_rttcnt > 0) { + u64 t = ca->sum_rtt; + do_div(t, info.tcpv_rttcnt); + info.tcpv_rtt = t; + } nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); } } From 632f90fd0c77d74f5b6cbc8b4dd1e2330984edf6 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Sun, 28 Oct 2012 06:12:00 +0000 Subject: [PATCH 0520/1071] drivers/net/ethernet/nxp/lpc_eth.c: Call mdiobus_unregister before mdiobus_free [ Upstream commit 57c10b61c84bfed68b1b317d6f507a392724b9c4 ] Based on commit b27393aecf66199f5ddad37c302d3e0cfadbe6c0 Calling mdiobus_free without calling mdiobus_unregister causes BUG_ON(). This patch fixes the issue. The semantic patch that found this issue(http://coccinelle.lip6.fr/): // @@ expression E; @@ ... when != mdiobus_unregister(E); + mdiobus_unregister(E); mdiobus_free(E); // Signed-off-by: Peter Senna Tschudin Tested-by: Roland Stigge Tested-by: Alexandre Pereira da Silva Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/nxp/lpc_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 53743f7a2ca960..af8b4142088c3d 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) pldat->dma_buff_base_p); free_irq(ndev->irq, ndev); iounmap(pldat->net_base); + mdiobus_unregister(pldat->mii_bus); mdiobus_free(pldat->mii_bus); clk_disable(pldat->clk); clk_put(pldat->clk); From 8d4948a7d059c2604bf24812c887f85dceba4d6d Mon Sep 17 00:00:00 2001 From: Tom Parkin Date: Mon, 29 Oct 2012 23:41:48 +0000 Subject: [PATCH 0521/1071] l2tp: fix oops in l2tp_eth_create() error path [ Upstream commit 789336360e0a2aeb9750c16ab704a02cbe035e9e ] When creating an L2TPv3 Ethernet session, if register_netdev() should fail for any reason (for example, automatic naming for "l2tpeth%d" interfaces hits the 32k-interface limit), the netdev is freed in the error path. However, the l2tp_eth_sess structure's dev pointer is left uncleared, and this results in l2tp_eth_delete() then attempting to unregister the same netdev later in the session teardown. This results in an oops. To avoid this, clear the session dev pointer in the error path. Signed-off-by: Tom Parkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/l2tp/l2tp_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 3bfb34aaee293c..69bf48d35a086f 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -290,6 +290,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p out_del_dev: free_netdev(dev); + spriv->dev = NULL; out_del_session: l2tp_session_delete(session); out: From 3583fce0d7937bfbf9846928f5cd41e11b5e4538 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 29 Oct 2012 05:05:33 +0000 Subject: [PATCH 0522/1071] tcp-repair: Handle zero-length data put in rcv queue [ Upstream commit c454e6111d1ef4268fe98e87087216e51c2718c3 ] When sending data into a tcp socket in repair state we should check for the amount of data being 0 explicitly. Otherwise we'll have an skb with seq == end_seq in rcv queue, but tcp doesn't expect this to happen (in particular a warn_on in tcp_recvmsg shoots). Signed-off-by: Pavel Emelyanov Reported-by: Giorgos Mavrikas Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d377f4854cb853..c92c4da4757de5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4556,6 +4556,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) struct tcphdr *th; bool fragstolen; + if (size == 0) + return 0; + skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); if (!skb) goto err; From 491eea6d0163ea9ff41892851eb5542997f2216c Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 3 Nov 2012 09:30:34 +0000 Subject: [PATCH 0523/1071] net: inet_diag -- Return error code if protocol handler is missed [ Upstream commit cacb6ba0f36ab14a507f4ee7697e8332899015d2 ] We've observed that in case if UDP diag module is not supported in kernel the netlink returns NLMSG_DONE without notifying a caller that handler is missed. This patch makes __inet_diag_dump to return error code instead. So as example it become possible to detect such situation and handle it gracefully on userspace level. Signed-off-by: Cyrill Gorcunov CC: David Miller CC: Eric Dumazet CC: Pavel Emelyanov Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_diag.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 570e61f9611fe9..6405a449448243 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -883,13 +883,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc) { const struct inet_diag_handler *handler; + int err = 0; handler = inet_diag_lock_handler(r->sdiag_protocol); if (!IS_ERR(handler)) handler->dump(skb, cb, r, bc); + else + err = PTR_ERR(handler); inet_diag_unlock_handler(handler); - return skb->len; + return err ? : skb->len; } static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) From 095ce0731f8ab7912070859b8e4d5ec663144b32 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Tue, 6 Nov 2012 02:10:10 +0000 Subject: [PATCH 0524/1071] af-packet: fix oops when socket is not present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit a3d744e995d2b936c500585ae39d99ee251c89b4 ] Due to a NULL dereference, the following patch is causing oops in normal trafic condition: commit c0de08d04215031d68fa13af36f347a6cfa252ca Author: Eric Leblond Date:   Thu Aug 16 22:02:58 2012 +0000     af_packet: don't emit packet on orig fanout group This buggy patch was a feature fix and has reached most stable branches. When skb->sk is NULL and when packet fanout is used, there is a crash in match_fanout_group where skb->sk is accessed. This patch fixes the issue by returning false as soon as the socket is NULL: this correspond to the wanted behavior because the kernel as to resend the skb to all the listening socket in this case. Signed-off-by: Eric Leblond Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 2fb9f590b3316b..aed87a401458db 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1644,7 +1644,7 @@ static inline int deliver_skb(struct sk_buff *skb, static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) { - if (ptype->af_packet_priv == NULL) + if (!ptype->af_packet_priv || !skb->sk) return false; if (ptype->id_match) From 32a529ebd901e7a8b5956732f0f32c5d98faa0a2 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 6 Nov 2012 16:18:41 +0000 Subject: [PATCH 0525/1071] ipv6: send unsolicited neighbour advertisements to all-nodes [ Upstream commit 60713a0ca7fd6651b951cc1b4dbd528d1fc0281b ] As documented in RFC4861 (Neighbor Discovery for IP version 6) 7.2.6., unsolicited neighbour advertisements should be sent to the all-nodes multicast address. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ndisc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index ff36194a71aa7d..2edce30ef7338c 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -535,7 +535,7 @@ static void ndisc_send_unsol_na(struct net_device *dev) { struct inet6_dev *idev; struct inet6_ifaddr *ifa; - struct in6_addr mcaddr; + struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT; idev = in6_dev_get(dev); if (!idev) @@ -543,7 +543,6 @@ static void ndisc_send_unsol_na(struct net_device *dev) read_lock_bh(&idev->lock); list_for_each_entry(ifa, &idev->addr_list, if_list) { - addrconf_addr_solict_mult(&ifa->addr, &mcaddr); ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, /*router=*/ !!idev->cnf.forwarding, /*solicited=*/ false, /*override=*/ true, From f98f5bfb851481d11b7395a9a2cd62ccdcf79d13 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 23 Oct 2012 22:29:38 +0200 Subject: [PATCH 0526/1071] futex: Handle futex_pi OWNER_DIED take over correctly commit 59fa6245192159ab5e1e17b8e31f15afa9cff4bf upstream. Siddhesh analyzed a failure in the take over of pi futexes in case the owner died and provided a workaround. See: http://sourceware.org/bugzilla/show_bug.cgi?id=14076 The detailed problem analysis shows: Futex F is initialized with PTHREAD_PRIO_INHERIT and PTHREAD_MUTEX_ROBUST_NP attributes. T1 lock_futex_pi(F); T2 lock_futex_pi(F); --> T2 blocks on the futex and creates pi_state which is associated to T1. T1 exits --> exit_robust_list() runs --> Futex F userspace value TID field is set to 0 and FUTEX_OWNER_DIED bit is set. T3 lock_futex_pi(F); --> Succeeds due to the check for F's userspace TID field == 0 --> Claims ownership of the futex and sets its own TID into the userspace TID field of futex F --> returns to user space T1 --> exit_pi_state_list() --> Transfers pi_state to waiter T2 and wakes T2 via rt_mutex_unlock(&pi_state->mutex) T2 --> acquires pi_state->mutex and gains real ownership of the pi_state --> Claims ownership of the futex and sets its own TID into the userspace TID field of futex F --> returns to user space T3 --> observes inconsistent state This problem is independent of UP/SMP, preemptible/non preemptible kernels, or process shared vs. private. The only difference is that certain configurations are more likely to expose it. So as Siddhesh correctly analyzed the following check in futex_lock_pi_atomic() is the culprit: if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { We check the userspace value for a TID value of 0 and take over the futex unconditionally if that's true. AFAICT this check is there as it is correct for a different corner case of futexes: the WAITERS bit became stale. Now the proposed change - if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { + if (unlikely(ownerdied || + !(curval & (FUTEX_TID_MASK | FUTEX_WAITERS)))) { solves the problem, but it's not obvious why and it wreckages the "stale WAITERS bit" case. What happens is, that due to the WAITERS bit being set (T2 is blocked on that futex) it enforces T3 to go through lookup_pi_state(), which in the above case returns an existing pi_state and therefor forces T3 to legitimately fight with T2 over the ownership of the pi_state (via pi_state->mutex). Probelm solved! Though that does not work for the "WAITERS bit is stale" problem because if lookup_pi_state() does not find existing pi_state it returns -ERSCH (due to TID == 0) which causes futex_lock_pi() to return -ESRCH to user space because the OWNER_DIED bit is not set. Now there is a different solution to that problem. Do not look at the user space value at all and enforce a lookup of possibly available pi_state. If pi_state can be found, then the new incoming locker T3 blocks on that pi_state and legitimately races with T2 to acquire the rt_mutex and the pi_state and therefor the proper ownership of the user space futex. lookup_pi_state() has the correct order of checks. It first tries to find a pi_state associated with the user space futex and only if that fails it checks for futex TID value = 0. If no pi_state is available nothing can create new state at that point because this happens with the hash bucket lock held. So the above scenario changes to: T1 lock_futex_pi(F); T2 lock_futex_pi(F); --> T2 blocks on the futex and creates pi_state which is associated to T1. T1 exits --> exit_robust_list() runs --> Futex F userspace value TID field is set to 0 and FUTEX_OWNER_DIED bit is set. T3 lock_futex_pi(F); --> Finds pi_state and blocks on pi_state->rt_mutex T1 --> exit_pi_state_list() --> Transfers pi_state to waiter T2 and wakes it via rt_mutex_unlock(&pi_state->mutex) T2 --> acquires pi_state->mutex and gains ownership of the pi_state --> Claims ownership of the futex and sets its own TID into the userspace TID field of futex F --> returns to user space This covers all gazillion points on which T3 might come in between T1's exit_robust_list() clearing the TID field and T2 fixing it up. It also solves the "WAITERS bit stale" problem by forcing the take over. Another benefit of changing the code this way is that it makes it less dependent on untrusted user space values and therefor minimizes the possible wreckage which might be inflicted. As usual after staring for too long at the futex code my brain hurts so much that I really want to ditch that whole optimization of avoiding the syscall for the non contended case for PI futexes and rip out the maze of corner case handling code. Unfortunately we can't as user space relies on that existing behaviour, but at least thinking about it helps me to preserve my mental sanity. Maybe we should nevertheless :) Reported-and-tested-by: Siddhesh Poyarekar Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1210232138540.2756@ionos Acked-by: Darren Hart Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 3717e7b306e08c..20ef219bbe9b76 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, struct futex_pi_state **ps, struct task_struct *task, int set_waiters) { - int lock_taken, ret, ownerdied = 0; + int lock_taken, ret, force_take = 0; u32 uval, newval, curval, vpid = task_pid_vnr(task); retry: @@ -755,17 +755,15 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, newval = curval | FUTEX_WAITERS; /* - * There are two cases, where a futex might have no owner (the - * owner TID is 0): OWNER_DIED. We take over the futex in this - * case. We also do an unconditional take over, when the owner - * of the futex died. - * - * This is safe as we are protected by the hash bucket lock ! + * Should we force take the futex? See below. */ - if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { - /* Keep the OWNER_DIED bit */ + if (unlikely(force_take)) { + /* + * Keep the OWNER_DIED and the WAITERS bit and set the + * new TID value. + */ newval = (curval & ~FUTEX_TID_MASK) | vpid; - ownerdied = 0; + force_take = 0; lock_taken = 1; } @@ -775,7 +773,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, goto retry; /* - * We took the lock due to owner died take over. + * We took the lock due to forced take over. */ if (unlikely(lock_taken)) return 1; @@ -790,20 +788,25 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, switch (ret) { case -ESRCH: /* - * No owner found for this futex. Check if the - * OWNER_DIED bit is set to figure out whether - * this is a robust futex or not. + * We failed to find an owner for this + * futex. So we have no pi_state to block + * on. This can happen in two cases: + * + * 1) The owner died + * 2) A stale FUTEX_WAITERS bit + * + * Re-read the futex value. */ if (get_futex_value_locked(&curval, uaddr)) return -EFAULT; /* - * We simply start over in case of a robust - * futex. The code above will take the futex - * and return happy. + * If the owner died or we have a stale + * WAITERS bit the owner TID in the user space + * futex is 0. */ - if (curval & FUTEX_OWNER_DIED) { - ownerdied = 1; + if (!(curval & FUTEX_TID_MASK)) { + force_take = 1; goto retry; } default: From 2d2db636c0f85a0fa4da6b6bc82d3474745b10de Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 23 Oct 2012 14:08:52 +0200 Subject: [PATCH 0527/1071] mmc: sh_mmcif: fix use after free commit a0d28ba01ebd048b4ba418142b37f5cf80e6d156 upstream. A recent commit "mmc: sh_mmcif: fix clock management" has introduced a use after free bug in sh_mmcif.c: in sh_mmcif_remove() the call to mmc_free_host() frees private driver data, therefore using it afterwards is a bug. Revert that hunk. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sh_mmcif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index ba0e493ad0c603..9058d21ae5d853 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1464,9 +1464,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); + clk_disable(host->hclk); mmc_free_host(host->mmc); pm_runtime_put_sync(&pdev->dev); - clk_disable(host->hclk); pm_runtime_disable(&pdev->dev); return 0; From 2091b753133a0bd22439357ed13f68fa595b8dd7 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Mon, 5 Nov 2012 14:29:49 -0500 Subject: [PATCH 0528/1071] mmc: sdhci: fix NULL dereference in sdhci_request() tuning commit 14efd957209461bbdf285bf0d67e931955d04a4c upstream. Commit 473b095a72a9 ("mmc: sdhci: fix incorrect command used in tuning") introduced a NULL dereference at resume-time if an SD 3.0 host controller raises the SDHCI_NEEDS_TUNING flag while no card is inserted. Seen on an OLPC XO-4 with sdhci-pxav3, but presumably affects other controllers too. Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9a11dc39921c06..b1facf936366b8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1307,16 +1307,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) */ if ((host->flags & SDHCI_NEEDS_RETUNING) && !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { - /* eMMC uses cmd21 while sd and sdio use cmd19 */ - tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? - MMC_SEND_TUNING_BLOCK_HS200 : - MMC_SEND_TUNING_BLOCK; - spin_unlock_irqrestore(&host->lock, flags); - sdhci_execute_tuning(mmc, tuning_opcode); - spin_lock_irqsave(&host->lock, flags); - - /* Restore original mmc_request structure */ - host->mrq = mrq; + if (mmc->card) { + /* eMMC uses cmd21 but sd and sdio use cmd19 */ + tuning_opcode = + mmc->card->type == MMC_TYPE_MMC ? + MMC_SEND_TUNING_BLOCK_HS200 : + MMC_SEND_TUNING_BLOCK; + spin_unlock_irqrestore(&host->lock, flags); + sdhci_execute_tuning(mmc, tuning_opcode); + spin_lock_irqsave(&host->lock, flags); + + /* Restore original mmc_request structure */ + host->mrq = mrq; + } } if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) From 443b7c19cea4ec05349ff916b1a55b12a76c9981 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 9 Nov 2012 10:05:57 +0100 Subject: [PATCH 0529/1071] drm/vmwgfx: Fix hibernation device reset commit 95e8f6a21996c4cc2c4574b231c6e858b749dce3 upstream. The device would not reset properly when resuming from hibernation. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul Reviewed-by: Dmitry Torokhov Cc: linux-graphics-maintainer@vmware.com Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ba2c35dbf10e3a..4a04ae0584a152 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1099,6 +1099,11 @@ static void vmw_pm_complete(struct device *kdev) struct drm_device *dev = pci_get_drvdata(pdev); struct vmw_private *dev_priv = vmw_priv(dev); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); + (void) vmw_read(dev_priv, SVGA_REG_ID); + mutex_unlock(&dev_priv->hw_mutex); + /** * Reclaim 3d reference held by fbdev and potentially * start fifo. From 7ea9b315caa53539867855ae14584c2075ec4dc7 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 9 Nov 2012 10:45:14 +0100 Subject: [PATCH 0530/1071] drm/vmwgfx: Fix a case where the code would BUG when trying to pin GMR memory commit afcc87aa6a233e52df73552dc1dc9ae3881b7cc8 upstream. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul Reviewed-by: Dmitry Torokhov Cc: linux-graphics-maintainer@vmware.com Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c index 3fa884db08abcb..27151f74fec8df 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c @@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) BUG_ON(!atomic_read(&bo->reserved)); BUG_ON(old_mem_type != TTM_PL_VRAM && - old_mem_type != VMW_PL_FLAG_GMR); + old_mem_type != VMW_PL_GMR); pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; if (pin) From 9bdfb16dac3c0ed0551fdc7f17320be55a7bacb3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Nov 2012 10:08:04 -0500 Subject: [PATCH 0531/1071] drm/radeon/cayman: add some missing regs to the VM reg checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 860fe2f05fa2eacac84368e23547ec8cf3cc6652 upstream. These regs were being wronly rejected leading to rendering issues. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=56876 Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen_cs.c | 3 +++ drivers/gpu/drm/radeon/evergreend.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index e932810c9b5a6f..4a33cdc37c07a9 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: + case CP_COHER_SIZE: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_GS_VERTEX_REUSE: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 79347855d9bf50..302af4f89a2d9b 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -87,6 +87,10 @@ #define CONFIG_MEMSIZE 0x5428 +#define CP_STRMOUT_CNTL 0x84FC + +#define CP_COHER_CNTL 0x85F0 +#define CP_COHER_SIZE 0x85F4 #define CP_COHER_BASE 0x85F8 #define CP_STALLED_STAT1 0x8674 #define CP_STALLED_STAT2 0x8678 From 9a7c2012cafea0ee0c507b411f33d279a115d623 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Nov 2012 10:13:24 -0500 Subject: [PATCH 0532/1071] drm/radeon/si: add some missing regs to the VM reg checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f418b88aad0c42b4caf4d79a0cf8d14a5d0a2284 upstream. This register is needed for streamout to work properly. Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/si.c | 1 + drivers/gpu/drm/radeon/sid.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 0139e227e3c724..6ab4a90c5a86dc 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2472,6 +2472,7 @@ static bool si_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_ESGS_RING_SIZE: diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index ef4815c27b1c67..6f0083a37f16d0 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -424,6 +424,7 @@ # define RDERR_INT_ENABLE (1 << 0) # define GUI_IDLE_INT_ENABLE (1 << 19) +#define CP_STRMOUT_CNTL 0x84FC #define SCRATCH_REG0 0x8500 #define SCRATCH_REG1 0x8504 #define SCRATCH_REG2 0x8508 From f4c27fc8bffdb18f1e78c6cd25264a0880b39010 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 7 Nov 2012 00:38:06 -0600 Subject: [PATCH 0533/1071] GFS2: Test bufdata with buffer locked and gfs2_log_lock held commit 96e5d1d3adf56f1c7eeb07258f6a1a0a7ae9c489 upstream. In gfs2_trans_add_bh(), gfs2 was testing if a there was a bd attached to the buffer without having the gfs2_log_lock held. It was then assuming it would stay attached for the rest of the function. However, without either the log lock being held of the buffer locked, __gfs2_ail_flush() could detach bd at any time. This patch moves the locking before the test. If there isn't a bd already attached, gfs2 can safely allocate one and attach it before locking. There is no way that the newly allocated bd could be on the ail list, and thus no way for __gfs2_ail_flush() to detach it. Signed-off-by: Benjamin Marzinski Signed-off-by: Steven Whitehouse Signed-off-by: Greg Kroah-Hartman --- fs/gfs2/lops.c | 14 ++------------ fs/gfs2/trans.c | 8 ++++++++ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 8ff95a2d54ee7d..0967d0cb40ccfb 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) struct gfs2_meta_header *mh; struct gfs2_trans *tr; - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); tr = current->journal_info; tr->tr_touched = 1; if (!list_empty(&bd->bd_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; @@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) sdp->sd_log_num_buf++; list_add(&bd->bd_list, &sdp->sd_log_le_buf); tr->tr_num_buf_new++; -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } static void gfs2_check_magic(struct buffer_head *bh) @@ -777,12 +772,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) struct address_space *mapping = bd->bd_bh->b_page->mapping; struct gfs2_inode *ip = GFS2_I(mapping->host); - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); if (tr) tr->tr_touched = 1; if (!list_empty(&bd->bd_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); if (gfs2_is_jdata(ip)) { @@ -793,9 +786,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) } else { list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered); } -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } /** diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index adbd27875ef957..413627072f3681 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_bufdata *bd; + lock_buffer(bh); + gfs2_log_lock(sdp); bd = bh->b_private; if (bd) gfs2_assert(sdp, bd->bd_gl == gl); else { + gfs2_log_unlock(sdp); + unlock_buffer(bh); gfs2_attach_bufdata(gl, bh, meta); bd = bh->b_private; + lock_buffer(bh); + gfs2_log_lock(sdp); } lops_add(sdp, bd); + gfs2_log_unlock(sdp); + unlock_buffer(bh); } void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) From 373296d1087d33a5ece7b898a54532e558760009 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 2 Nov 2012 11:38:44 +1100 Subject: [PATCH 0534/1071] xfs: fix reading of wrapped log data commit 6ce377afd1755eae5c93410ca9a1121dfead7b87 upstream. Commit 4439647 ("xfs: reset buffer pointers before freeing them") in 3.0-rc1 introduced a regression when recovering log buffers that wrapped around the end of log. The second part of the log buffer at the start of the physical log was being read into the header buffer rather than the data buffer, and hence recovery was seeing garbage in the data buffer when it got to the region of the log buffer that was incorrectly read. Reported-by: Torsten Kaiser Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_log_recover.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 5da3ace352bffe..d308749fabf126 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3541,7 +3541,7 @@ xlog_do_recovery_pass( * - order is important. */ error = xlog_bread_offset(log, 0, - bblks - split_bblks, hbp, + bblks - split_bblks, dbp, offset + BBTOB(split_bblks)); if (error) goto bread_err2; From 7565b210845bb9c80836d32fcd6de5fb1bb90134 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 2 Nov 2012 14:23:12 +1100 Subject: [PATCH 0535/1071] xfs: fix buffer shudown reference count mismatch commit 03b1293edad462ad1ad62bcc5160c76758e450d5 upstream. When we shut down the filesystem, we have to unpin and free all the buffers currently active in the CIL. To do this we unpin and remove them in one operation as a result of a failed iclogbuf write. For buffers, we do this removal via a simultated IO completion of after marking the buffer stale. At the time we do this, we have two references to the buffer - the active LRU reference and the buf log item. The LRU reference is removed by marking the buffer stale, and the active CIL reference is by the xfs_buf_iodone() callback that is run by xfs_buf_do_callbacks() during ioend processing (via the bp->b_iodone callback). However, ioend processing requires one more reference - that of the IO that it is completing. We don't have this reference, so we free the buffer prematurely and use it after it is freed. For buffers marked with XBF_ASYNC, this leads to assert failures in xfs_buf_rele() on debug kernels because the b_hold count is zero. Fix this by making sure we take the necessary IO reference before starting IO completion processing on the stale buffer, and set the XBF_ASYNC flag to ensure that IO completion processing removes all the active references from the buffer to ensure it is fully torn down. Signed-off-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_buf_item.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index a8d0ed91119612..becf4a97efc65c 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -526,7 +526,25 @@ xfs_buf_item_unpin( } xfs_buf_relse(bp); } else if (freed && remove) { + /* + * There are currently two references to the buffer - the active + * LRU reference and the buf log item. What we are about to do + * here - simulate a failed IO completion - requires 3 + * references. + * + * The LRU reference is removed by the xfs_buf_stale() call. The + * buf item reference is removed by the xfs_buf_iodone() + * callback that is run by xfs_buf_do_callbacks() during ioend + * processing (via the bp->b_iodone callback), and then finally + * the ioend processing will drop the IO reference if the buffer + * is marked XBF_ASYNC. + * + * Hence we need to take an additional reference here so that IO + * completion processing doesn't free the buffer prematurely. + */ xfs_buf_lock(bp); + xfs_buf_hold(bp); + bp->b_flags |= XBF_ASYNC; xfs_buf_ioerror(bp, EIO); XFS_BUF_UNDONE(bp); xfs_buf_stale(bp); From f49c1beea97dfea9acb4a4dc213c12cf040b0280 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Nov 2012 14:36:18 +0100 Subject: [PATCH 0536/1071] ALSA: Fix card refcount unbalance commit 8bb4d9ce08b0a92ca174e41d92c180328f86173f upstream. There are uncovered cases whether the card refcount introduced by the commit a0830dbd isn't properly increased or decreased: - OSS PCM and mixer success paths - When lookup function gets NULL This patch fixes these places. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=50251 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/oss/mixer_oss.c | 1 + sound/core/oss/pcm_oss.c | 1 + sound/core/pcm_native.c | 6 ++++-- sound/core/sound.c | 2 +- sound/core/sound_oss.c | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 05395aaeaa32a4..c353768854e6b0 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -76,6 +76,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) snd_card_unref(card); return -EFAULT; } + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index f337b66a020b5b..4c1cc51772e6f1 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2454,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; + snd_card_unref(pcm->card); return err; __error: diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index d15e5be2ae1bd2..bf3bf4360743ef 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2121,7 +2121,8 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_PLAYBACK); err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); - snd_card_unref(pcm->card); + if (pcm) + snd_card_unref(pcm->card); return err; } @@ -2134,7 +2135,8 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_CAPTURE); err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); - snd_card_unref(pcm->card); + if (pcm) + snd_card_unref(pcm->card); return err; } diff --git a/sound/core/sound.c b/sound/core/sound.c index 7c0640eeee521d..3700d96fb3fb51 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -115,7 +115,7 @@ void *snd_lookup_minor_data(unsigned int minor, int type) mreg = snd_minors[minor]; if (mreg && mreg->type == type) { private_data = mreg->private_data; - if (mreg->card_ptr) + if (private_data && mreg->card_ptr) atomic_inc(&mreg->card_ptr->refcount); } else private_data = NULL; diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index e1d79ee3590650..726a49ac97253d 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -54,7 +54,7 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) mreg = snd_oss_minors[minor]; if (mreg && mreg->type == type) { private_data = mreg->private_data; - if (mreg->card_ptr) + if (private_data && mreg->card_ptr) atomic_inc(&mreg->card_ptr->refcount); } else private_data = NULL; From 118ff53fa02dc7830e2f561b6aa2619ef41de6ab Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Nov 2012 11:22:48 +0100 Subject: [PATCH 0537/1071] ALSA: usb-audio: Fix mutex deadlock at disconnection commit 10e44239f67d0b6fb74006e61a7e883b8075247a upstream. The recent change for USB-audio disconnection race fixes introduced a mutex deadlock again. There is a circular dependency between chip->shutdown_rwsem and pcm->open_mutex, depicted like below, when a device is opened during the disconnection operation: A. snd_usb_audio_disconnect() -> card.c::register_mutex -> chip->shutdown_rwsem (write) -> snd_card_disconnect() -> pcm.c::register_mutex -> pcm->open_mutex B. snd_pcm_open() -> pcm->open_mutex -> snd_usb_pcm_open() -> chip->shutdown_rwsem (read) Since the chip->shutdown_rwsem protection in the case A is required only for turning on the chip->shutdown flag and it doesn't have to be taken for the whole operation, we can reduce its window in snd_usb_audio_disconnect(). Reported-by: Jiri Slaby Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 486b4a67772d3a..b3f5ad4971390a 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, return; card = chip->card; - mutex_lock(®ister_mutex); down_write(&chip->shutdown_rwsem); chip->shutdown = 1; + up_write(&chip->shutdown_rwsem); + + mutex_lock(®ister_mutex); chip->num_interfaces--; if (chip->num_interfaces <= 0) { snd_card_disconnect(card); @@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); } } From 9f3dc4baa6813f64f89ce408dc93bdcba38ba022 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 17 Nov 2012 13:21:23 -0800 Subject: [PATCH 0538/1071] Linux 3.6.7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 471b83c4e34473..07f23080b86d0a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 6 +SUBLEVEL = 7 EXTRAVERSION = NAME = Terrified Chipmunk From 9e9dbb97a010f748114404bd44ab2e02082d215c Mon Sep 17 00:00:00 2001 From: Takamori Yamaguchi Date: Thu, 8 Nov 2012 15:53:39 -0800 Subject: [PATCH 0539/1071] mm: bugfix: set current->reclaim_state to NULL while returning from kswapd() commit b0a8cc58e6b9aaae3045752059e5e6260c0b94bc upstream. In kswapd(), set current->reclaim_state to NULL before returning, as current->reclaim_state holds reference to variable on kswapd()'s stack. In rare cases, while returning from kswapd() during memory offlining, __free_slab() and freepages() can access the dangling pointer of current->reclaim_state. Signed-off-by: Takamori Yamaguchi Signed-off-by: Aaditya Kumar Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/vmscan.c b/mm/vmscan.c index 99b434b674c02b..a018dfcbb2f76f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2953,6 +2953,8 @@ static int kswapd(void *p) &balanced_classzone_idx); } } + + current->reclaim_state = NULL; return 0; } From fee02d04c682f3ef8d1d1ec46e22fb7f833c9330 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Tue, 9 Oct 2012 15:37:48 +0800 Subject: [PATCH 0540/1071] libata-acpi: Fix NULL ptr derference in ata_acpi_dev_handle commit 60817a680b1bd3341b6909fab7d8a1fcc3a78369 upstream. commit 6b66d95895c149cbc04d4fac5a2f5477c543a8ae didn't handle SATA PMP case in ata_acpi_bind_device and will cause a NULL ptr dereference when user attached a SATA drive to the PMP port. Fix this by checking PMP support. This bug is reported by Dan van der Ster in the following bugzilla page: https://bugzilla.kernel.org/show_bug.cgi?id=48211 Reported-by: Dan van der Ster Tested-by: Dan van der Ster Signed-off-by: Aaron Lu Signed-off-by: Jeff Garzik Tested-by: Simon Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-acpi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index fd9ecf74e631af..5b0ba3f20edcfd 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, struct acpi_device *acpi_dev; struct acpi_device_power_state *states; - if (ap->flags & ATA_FLAG_ACPI_SATA) - ata_dev = &ap->link.device[sdev->channel]; - else + if (ap->flags & ATA_FLAG_ACPI_SATA) { + if (!sata_pmp_attached(ap)) + ata_dev = &ap->link.device[sdev->id]; + else + ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id]; + } + else { ata_dev = &ap->link.device[sdev->id]; + } *handle = ata_dev_acpi_handle(ata_dev); From 77d8dd2cf8eff86d9ec00b02d3623702c45ea23e Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 12 Nov 2012 22:09:46 +1100 Subject: [PATCH 0541/1071] xfs: drop buffer io reference when a bad bio is built commit d69043c42d8c6414fa28ad18d99973aa6c1c2e24 upstream. Error handling in xfs_buf_ioapply_map() does not handle IO reference counts correctly. We increment the b_io_remaining count before building the bio, but then fail to decrement it in the failure case. This leads to the buffer never running IO completion and releasing the reference that the IO holds, so at unmount we can leak the buffer. This leak is captured by this assert failure during unmount: XFS: Assertion failed: atomic_read(&pag->pag_ref) == 0, file: fs/xfs/xfs_mount.c, line: 273 This is not a new bug - the b_io_remaining accounting has had this problem for a long, long time - it's just very hard to get a zero length bio being built by this code... Further, the buffer IO error can be overwritten on a multi-segment buffer by subsequent bio completions for partial sections of the buffer. Hence we should only set the buffer error status if the buffer is not already carrying an error status. This ensures that a partial IO error on a multi-segment buffer will not be lost. This part of the problem is a regression, however. Signed-off-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_buf.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 933b7930b8636d..4b0b8dd1b7b0ea 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io( { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; - xfs_buf_ioerror(bp, -error); + /* + * don't overwrite existing errors - otherwise we can lose errors on + * buffers that require multiple bios to complete. + */ + if (!bp->b_error) + xfs_buf_ioerror(bp, -error); - if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) + if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); _xfs_buf_ioend(bp, 1); @@ -1279,6 +1284,11 @@ xfs_buf_ioapply_map( if (size) goto next_chunk; } else { + /* + * This is guaranteed not to be the last io reference count + * because the caller (xfs_buf_iorequest) holds a count itself. + */ + atomic_dec(&bp->b_io_remaining); xfs_buf_ioerror(bp, EIO); bio_put(bio); } From a64e7f53c0f5d061ccbd8b28fa09b51b32b7ec53 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 5 Nov 2012 10:27:52 +0200 Subject: [PATCH 0542/1071] mac80211: sync acccess to tx_filtered/ps_tx_buf queues commit 987c285c2ae2e4e32aca3a9b3252d28171c75711 upstream. These are accessed without a lock when ending STA PSM. If the sta_cleanup timer accesses these lists at the same time, we might crash. This may fix some mysterious crashes we had during ieee80211_sta_ps_deliver_wakeup. Signed-off-by: Arik Nemtsov Signed-off-by: Ido Yariv Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/sta_info.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 63882b991d3ade..0318537e86ca5e 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -948,6 +948,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; struct sk_buff_head pending; int filtered = 0, buffered = 0, ac; + unsigned long flags; clear_sta_flag(sta, WLAN_STA_SP); @@ -963,12 +964,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int count = skb_queue_len(&pending), tmp; + spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); + spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); tmp = skb_queue_len(&pending); filtered += tmp - count; count = tmp; + spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); + spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); tmp = skb_queue_len(&pending); buffered += tmp - count; } From f79b61dcf47fc54e5a4c8307bad659bc1f352a3d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 Nov 2012 14:06:28 +0100 Subject: [PATCH 0543/1071] mac80211: don't send null data packet when not associated commit 20f544eea03db4b498942558b882d463ce575c3e upstream. On resume or firmware recovery, mac80211 sends a null data packet to see if the AP is still around and hasn't disconnected us. However, it always does this even if it wasn't even connected before, leading to a warning in the new channel context code. Fix this by checking that it's associated. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1cfe6d56dcfa8c..78834496ecc15b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1434,6 +1434,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; + if (!sdata->u.mgd.associated) + continue; ieee80211_send_nullfunc(local, sdata, 0); } From 1325ed662eb4129a96320145bea7ec5bfce249c9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 10 Nov 2012 03:44:14 +0100 Subject: [PATCH 0544/1071] mac80211: call skb_dequeue/ieee80211_free_txskb instead of __skb_queue_purge commit 1f98ab7fef48a2968f37f422c256c9fbd978c3f0 upstream. Fixes more wifi status skb leaks, leading to hostapd/wpa_supplicant hangs. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/sta_info.c | 6 +++--- net/mac80211/status.c | 9 +++++++++ net/mac80211/tx.c | 9 ++++++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index bb61f7718c4c52..642a2a3411d50c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1304,6 +1304,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs); /* HT */ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 0318537e86ca5e..31aa8b82a1147f 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -730,8 +730,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->tx_filtered[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); } #ifdef CONFIG_MAC80211_MESH @@ -765,7 +765,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); if (!tid_tx) continue; - __skb_queue_purge(&tid_tx->pending); + ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); kfree(tid_tx); } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 118329a2c84b96..14e1b83895efc2 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -648,3 +648,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); } EXPORT_SYMBOL(ieee80211_free_txskb); + +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(skbs))) + ieee80211_free_txskb(hw, skb); +} diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 362c418a9c34a3..8133fede8fd162 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1358,7 +1358,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) if (tx->skb) ieee80211_free_txskb(&tx->local->hw, tx->skb); else - __skb_queue_purge(&tx->skbs); + ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); return -1; } else if (unlikely(res == TX_QUEUED)) { I802_DEBUG_INC(tx->local->tx_handlers_queued); @@ -2132,10 +2132,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, */ void ieee80211_clear_tx_pending(struct ieee80211_local *local) { + struct sk_buff *skb; int i; - for (i = 0; i < local->hw.queues; i++) - skb_queue_purge(&local->pending[i]); + for (i = 0; i < local->hw.queues; i++) { + while ((skb = skb_dequeue(&local->pending[i])) != NULL) + ieee80211_free_txskb(&local->hw, skb); + } } /* From 45f158b2641200ed81c20a118758ddc8cbfc4364 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 24 Oct 2012 14:54:14 +0800 Subject: [PATCH 0545/1071] PCI/PM: Resume device before shutdown commit 3ff2de9ba1a2e22e548979dbcd46e999b22c93d8 upstream. Some actions during shutdown need device to be in D0 state, such as MSI shutdown etc, so resume device before shutdown. Without this patch, a device may not be enumerated after a kexec because the corresponding bridge is not in D0, so that configuration space of the device is not accessible. Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index d6fd6b6d9d4b57..729e0385f912f9 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -421,6 +421,8 @@ static void pci_device_shutdown(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_driver *drv = pci_dev->driver; + pm_runtime_resume(dev); + if (drv && drv->shutdown) drv->shutdown(pci_dev); pci_msi_shutdown(pci_dev); @@ -431,16 +433,6 @@ static void pci_device_shutdown(struct device *dev) * continue to do DMA */ pci_disable_device(pci_dev); - - /* - * Devices may be enabled to wake up by runtime PM, but they need not - * be supposed to wake up the system from its "power off" state (e.g. - * ACPI S5). Therefore disable wakeup for all devices that aren't - * supposed to wake up the system at this point. The state argument - * will be ignored by pci_enable_wake(). - */ - if (!device_may_wakeup(dev)) - pci_enable_wake(pci_dev, PCI_UNKNOWN, false); } #ifdef CONFIG_PM From ee62ff8a0db9d64cdd41abd1acfa1447d78dd5b4 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Thu, 25 Oct 2012 09:36:03 +0800 Subject: [PATCH 0546/1071] PCI/PM: Fix proc config reg access for D3cold and bridge suspending commit b3c32c4f9565f93407921c0d8a4458042eb8998e upstream. In https://bugzilla.kernel.org/show_bug.cgi?id=48981 Peter reported that /proc/bus/pci/??/??.? does not work for 3.6. This is because the device configuration space registers are not accessible if the corresponding parent bridge is suspended or the device is put into D3cold state. This is the same as /sys/bus/pci/devices/0000:??:??.?/config access issue. So the function used to solve sysfs issue is used to solve this issue. This patch moves pci_config_pm_runtime_get()/_put() from pci/pci-sysfs.c to pci/pci.c and makes them extern so they can be used by both the sysfs and proc paths. [bhelgaas: changelog, references, reporters] Reference: https://bugzilla.kernel.org/show_bug.cgi?id=48981 Reference: https://bugzilla.kernel.org/show_bug.cgi?id=49031 Reported-by: Forrest Loomis Reported-by: Peter Reported-by: Micael Dias Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-sysfs.c | 34 ---------------------------------- drivers/pci/pci.c | 32 ++++++++++++++++++++++++++++++++ drivers/pci/pci.h | 2 ++ drivers/pci/proc.c | 8 ++++++++ 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 02d107b152818e..f39378d9da1500 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) } struct device_attribute vga_attr = __ATTR_RO(boot_vga); -static void -pci_config_pm_runtime_get(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - if (parent) - pm_runtime_get_sync(parent); - pm_runtime_get_noresume(dev); - /* - * pdev->current_state is set to PCI_D3cold during suspending, - * so wait until suspending completes - */ - pm_runtime_barrier(dev); - /* - * Only need to resume devices in D3cold, because config - * registers are still accessible for devices suspended but - * not in D3cold. - */ - if (pdev->current_state == PCI_D3cold) - pm_runtime_resume(dev); -} - -static void -pci_config_pm_runtime_put(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - pm_runtime_put(dev); - if (parent) - pm_runtime_put_sync(parent); -} - static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index ab4bf5a4c2f12e..a0f8e8f856fec5 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1910,6 +1910,38 @@ bool pci_dev_run_wake(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_dev_run_wake); +void pci_config_pm_runtime_get(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + if (parent) + pm_runtime_get_sync(parent); + pm_runtime_get_noresume(dev); + /* + * pdev->current_state is set to PCI_D3cold during suspending, + * so wait until suspending completes + */ + pm_runtime_barrier(dev); + /* + * Only need to resume devices in D3cold, because config + * registers are still accessible for devices suspended but + * not in D3cold. + */ + if (pdev->current_state == PCI_D3cold) + pm_runtime_resume(dev); +} + +void pci_config_pm_runtime_put(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + pm_runtime_put(dev); + if (parent) + pm_runtime_put_sync(parent); +} + /** * pci_pm_init - Initialize PM functions of given PCI device * @dev: PCI device to handle. diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index bacbcba69cf386..fd92aab9904b92 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev); extern int pci_finish_runtime_suspend(struct pci_dev *dev); extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); extern void pci_wakeup_bus(struct pci_bus *bus); +extern void pci_config_pm_runtime_get(struct pci_dev *dev); +extern void pci_config_pm_runtime_put(struct pci_dev *dev); extern void pci_pm_init(struct pci_dev *dev); extern void platform_pci_wakeup_init(struct pci_dev *dev); extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 27911b55c2a522..af028c7459367e 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp if (!access_ok(VERIFY_WRITE, buf, cnt)) return -EINVAL; + pci_config_pm_runtime_get(dev); + if ((pos & 1) && cnt) { unsigned char val; pci_user_read_config_byte(dev, pos, &val); @@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp cnt--; } + pci_config_pm_runtime_put(dev); + *ppos = pos; return nbytes; } @@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof if (!access_ok(VERIFY_READ, buf, cnt)) return -EINVAL; + pci_config_pm_runtime_get(dev); + if ((pos & 1) && cnt) { unsigned char val; __get_user(val, buf); @@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof cnt--; } + pci_config_pm_runtime_put(dev); + *ppos = pos; i_size_write(ino, dp->size); return nbytes; From d5ad050308134580749cc1dbbeae4946d4f2cefe Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 8 Nov 2012 15:53:37 -0800 Subject: [PATCH 0547/1071] fanotify: fix missing break commit 848561d368751a1c0f679b9f045a02944506a801 upstream. Anders Blomdell noted in 2010 that Fanotify lost events and provided a test case. Eric Paris confirmed it was a bug and posted a fix to the list https://groups.google.com/forum/?fromgroups=#!topic/linux.kernel/RrJfTfyW2BE but never applied it. Repeated attempts over time to actually get him to apply it have never had a reply from anyone who has raised it So apply it anyway Signed-off-by: Alan Cox Reported-by: Anders Blomdell Cc: Eric Paris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/notify/fanotify/fanotify.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index f35794b97e8e5c..a5063602536421 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) if ((old->path.mnt == new->path.mnt) && (old->path.dentry == new->path.dentry)) return true; + break; case (FSNOTIFY_EVENT_NONE): return true; default: From 17773c7701fe1eb68b8841f215b506dca07a3b6a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 25 Oct 2012 10:49:25 +1030 Subject: [PATCH 0548/1071] module: fix out-by-one error in kallsyms commit 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 upstream. Masaki found and patched a kallsyms issue: the last symbol in a module's symtab wasn't transferred. This is because we manually copy the zero'th entry (which is always empty) then copy the rest in a loop starting at 1, though from src[0]. His fix was minimal, I prefer to rewrite the loops in more standard form. There are two loops: one to get the size, and one to copy. Make these identical: always count entry 0 and any defined symbol in an allocated non-init section. This bug exists since the following commit was introduced. module: reduce symbol table for loaded modules (v2) commit: 4a4962263f07d14660849ec134ee42b63e95ea9a LKML: http://lkml.org/lkml/2012/10/24/27 Reported-by: Masaki Kimura Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 9ad9ee9406d64d..2a15c59e48501d 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2273,12 +2273,17 @@ static void layout_symtab(struct module *mod, struct load_info *info) src = (void *)info->hdr + symsect->sh_offset; nsrc = symsect->sh_size / sizeof(*src); + /* strtab always starts with a nul, so offset 0 is the empty string. */ + strtab_size = 1; + /* Compute total space required for the core symbols' strtab. */ - for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) - if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { - strtab_size += strlen(&info->strtab[src->st_name]) + 1; + for (ndst = i = 0; i < nsrc; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + strtab_size += strlen(&info->strtab[src[i].st_name])+1; ndst++; } + } /* Append room for core symbols at end of core part. */ info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); @@ -2312,15 +2317,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) mod->core_symtab = dst = mod->module_core + info->symoffs; mod->core_strtab = s = mod->module_core + info->stroffs; src = mod->symtab; - *dst = *src; *s++ = 0; - for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { - if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) - continue; - - dst[ndst] = *src; - dst[ndst++].st_name = s - mod->core_strtab; - s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; + for (ndst = i = 0; i < mod->num_symtab; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + dst[ndst] = src[i]; + dst[ndst++].st_name = s - mod->core_strtab; + s += strlcpy(s, &mod->strtab[src[i].st_name], + KSYM_NAME_LEN) + 1; + } } mod->core_num_syms = ndst; } From 01ae49199e6a67075b53150ecd8dfc627a67183b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 9 Nov 2012 14:54:12 +1030 Subject: [PATCH 0549/1071] virtio: Don't access index after unregister. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 237242bddc99041e15a4ca51b8439657cadaff17 upstream. Virtio wants to release used indices after the corresponding virtio device has been unregistered. However, virtio does not hold an extra reference, giving up its last reference with device_unregister(), making accessing dev->index afterwards invalid. I actually saw problems when testing my (not-yet-merged) virtio-ccw code: - device_add virtio-net,id=xxx -> creates device virtio with n>0 - device_del xxx -> deletes virtio, but calls ida_simple_remove with an index of 0 - device_add virtio-net,id=xxx -> tries to add virtio0, which is still in use... So let's save the index we want to release before calling device_unregister(). Signed-off-by: Cornelia Huck Acked-by: Sjur Brændeland Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/virtio/virtio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index c3b3f7f0d9d197..abd47c7452d2b1 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device); void unregister_virtio_device(struct virtio_device *dev) { + int index = dev->index; /* save for after device release */ + device_unregister(&dev->dev); - ida_simple_remove(&virtio_index_ida, dev->index); + ida_simple_remove(&virtio_index_ida, index); } EXPORT_SYMBOL_GPL(unregister_virtio_device); From ea617a2c5150f9914c57215545575abf394df7bc Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 3 Nov 2012 09:37:28 -0400 Subject: [PATCH 0550/1071] cifs: fix potential buffer overrun in cifs.idmap handling code commit 36960e440ccf94349c09fb944930d3bfe4bc473f upstream. The userspace cifs.idmap program generally works with the wbclient libs to generate binary SIDs in userspace. That program defines the struct that holds these values as having a max of 15 subauthorities. The kernel idmapping code however limits that value to 5. When the kernel copies those values around though, it doesn't sanity check the num_subauths value handed back from userspace or from the server. It's possible therefore for userspace to hand us back a bogus num_subauths value (or one that's valid, but greater than 5) that could cause the kernel to walk off the end of the cifs_sid->sub_auths array. Fix this by defining a new routine for copying sids and using that in all of the places that copy it. If we end up with a sid that's longer than expected then this approach will just lop off the "extra" subauths, but that's basically what the code does today already. Better approaches might be to fix this code to reject SIDs with >5 subauths, or fix it to handle the subauths array dynamically. At the same time, change the kernel to check the length of the data returned by userspace. If it's shorter than struct cifs_sid, reject it and return -EIO. If that happens we'll end up with fields that are basically uninitialized. Long term, it might make sense to redefine cifs_sid using a flexarray at the end, to allow for variable-length subauth lists, and teach the code to handle the case where the subauths array being passed in from userspace is shorter than 5 elements. Note too, that I don't consider this a security issue since you'd need a compromised cifs.idmap program. If you have that, you can do all sorts of nefarious stuff. Still, this is probably reasonable for stable. Reviewed-by: Shirish Pargaonkar Signed-off-by: Jeff Layton Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifsacl.c | 49 +++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 05f4dc263a23b7..8d453b795a0d1f 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -224,6 +224,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr) } } +static void +cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) +{ + memcpy(dst, src, sizeof(*dst)); + dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS); +} + static void id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, struct cifs_sid_id **psidid, char *typestr) @@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, } } - memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); + cifs_copy_sid(&(*psidid)->sid, sidptr); (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); (*psidid)->refcount = 0; @@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) * any fields of the node after a reference is put . */ if (test_bit(SID_ID_MAPPED, &psidid->state)) { - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); psidid->time = jiffies; /* update ts for accessing */ goto id_sid_out; } @@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) if (IS_ERR(sidkey)) { rc = -EINVAL; cFYI(1, "%s: Can't map and id to a SID", __func__); + } else if (sidkey->datalen < sizeof(struct cifs_sid)) { + rc = -EIO; + cFYI(1, "%s: Downcall contained malformed key " + "(datalen=%hu)", __func__, sidkey->datalen); } else { lsid = (struct cifs_sid *)sidkey->payload.data; - memcpy(&psidid->sid, lsid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - memcpy(ssid, &psidid->sid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); + cifs_copy_sid(&psidid->sid, lsid); + cifs_copy_sid(ssid, &psidid->sid); set_bit(SID_ID_MAPPED, &psidid->state); key_put(sidkey); kfree(psidid->sidstr); @@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) return rc; } if (test_bit(SID_ID_MAPPED, &psidid->state)) - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); else rc = -EINVAL; } @@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) static void copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, __u32 sidsoffset) { - int i; - struct cifs_sid *owner_sid_ptr, *group_sid_ptr; struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; @@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd, owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->osidoffset)); nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); - - nowner_sid_ptr->revision = owner_sid_ptr->revision; - nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; + cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr); /* copy group sid */ group_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->gsidoffset)); ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + sizeof(struct cifs_sid)); - - ngroup_sid_ptr->revision = group_sid_ptr->revision; - ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; + cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr); return; } @@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(nowner_sid_ptr); return rc; } - memcpy(owner_sid_ptr, nowner_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr); kfree(nowner_sid_ptr); *aclflag = CIFS_ACL_OWNER; } @@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(ngroup_sid_ptr); return rc; } - memcpy(group_sid_ptr, ngroup_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr); kfree(ngroup_sid_ptr); *aclflag = CIFS_ACL_GROUP; } From 50d4bcc3701d7f6173e3e8727234a4dd81518a3d Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Mon, 5 Nov 2012 11:39:32 +0000 Subject: [PATCH 0551/1071] cifs: Do not lookup hashed negative dentry in cifs_atomic_open commit 3798f47aa276b332c30da499cb4df4577e2f8872 upstream. We do not need to lookup a hashed negative directory since we have already revalidated it before and have found it to be fine. This also prevents a crash in cifs_lookup() when it attempts to rehash the already hashed negative lookup dentry. The patch has been tested using the reproducer at https://bugzilla.redhat.com/show_bug.cgi?id=867344#c28 Reported-by: Vit Zahradka Signed-off-by: Sachin Prabhu Signed-off-by: Greg Kroah-Hartman --- fs/cifs/dir.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 781025be48bc47..2b33b2ce894ad4 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -392,7 +392,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, * in network traffic in the other paths. */ if (!(oflags & O_CREAT)) { - struct dentry *res = cifs_lookup(inode, direntry, 0); + struct dentry *res; + + /* + * Check for hashed negative dentry. We have already revalidated + * the dentry and it is fine. No need to perform another lookup. + */ + if (!d_unhashed(direntry)) + return -ENOENT; + + res = cifs_lookup(inode, direntry, 0); if (IS_ERR(res)) return PTR_ERR(res); From 9ef0ecd730892e4086a7b9ad4dc38486f7db989c Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sun, 21 Oct 2012 20:42:28 +0300 Subject: [PATCH 0552/1071] crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption commit 9efade1b3e981f5064f9db9ca971b4dc7557ae42 upstream. cryptd_queue_worker attempts to prevent simultaneous accesses to crypto workqueue by cryptd_enqueue_request using preempt_disable/preempt_enable. However cryptd_enqueue_request might be called from softirq context, so add local_bh_disable/local_bh_enable to prevent data corruption and panics. Bug report at http://marc.info/?l=linux-crypto-vger&m=134858649616319&w=2 v2: - Disable software interrupts instead of hardware interrupts Reported-by: Gurucharan Shetty Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- crypto/cryptd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 671d4d6d14df10..7bdd61b867c899 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work) struct crypto_async_request *req, *backlog; cpu_queue = container_of(work, struct cryptd_cpu_queue, work); - /* Only handle one request at a time to avoid hogging crypto - * workqueue. preempt_disable/enable is used to prevent - * being preempted by cryptd_enqueue_request() */ + /* + * Only handle one request at a time to avoid hogging crypto workqueue. + * preempt_disable/enable is used to prevent being preempted by + * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent + * cryptd_enqueue_request() being accessed from software interrupts. + */ + local_bh_disable(); preempt_disable(); backlog = crypto_get_backlog(&cpu_queue->queue); req = crypto_dequeue_request(&cpu_queue->queue); preempt_enable(); + local_bh_enable(); if (!req) return; From 26a10f1df3311011e4317fafd33002309587d963 Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Tue, 6 Nov 2012 17:31:03 +0100 Subject: [PATCH 0553/1071] ARM: at91/AT91SAM9G45: fix crypto peripherals irq issue due to sparse irq support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 097965ee447e5ccec9776f9b075e64cf7607e5eb upstream. Spare irq support introduced by commit 8fe82a5 (ARM: at91: sparse irq support) involves to add the NR_IRQS_LEGACY offset to irq number. Signed-off-by: Nicolas Royer Acked-by: Nicolas Ferre Acked-by: Eric Bénard Tested-by: Eric Bénard Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/at91sam9g45_devices.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 1b47319ca00b1a..bdbbbbcc66efd2 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -1847,8 +1847,8 @@ static struct resource sha_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = AT91SAM9G45_ID_AESTDESSHA, - .end = AT91SAM9G45_ID_AESTDESSHA, + .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, .flags = IORESOURCE_IRQ, }, }; @@ -1880,8 +1880,8 @@ static struct resource tdes_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = AT91SAM9G45_ID_AESTDESSHA, - .end = AT91SAM9G45_ID_AESTDESSHA, + .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, .flags = IORESOURCE_IRQ, }, }; @@ -1916,8 +1916,8 @@ static struct resource aes_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = AT91SAM9G45_ID_AESTDESSHA, - .end = AT91SAM9G45_ID_AESTDESSHA, + .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, .flags = IORESOURCE_IRQ, }, }; From 6e216b4a2fa0eada850c943e6834e8e635e2fb9c Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 1 Nov 2012 12:30:16 +0000 Subject: [PATCH 0554/1071] ptp: update adjfreq callback description commit 87f4d7c1d36f44b0822053b7e5dedc31fdd0ab99 upstream. This patch updates the adjfreq callback description to include a note that the delta in ppb is always relative to the base frequency, and not to the current frequency of the hardware clock. Signed-off-by: Jacob Keller CC: Richard Cochran CC: John Stultz Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/ptp_clock_kernel.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h index 945704c2ed6530..00b9e619717c45 100644 --- a/include/linux/ptp_clock_kernel.h +++ b/include/linux/ptp_clock_kernel.h @@ -50,7 +50,8 @@ struct ptp_clock_request { * clock operations * * @adjfreq: Adjusts the frequency of the hardware clock. - * parameter delta: Desired period change in parts per billion. + * parameter delta: Desired frequency offset from nominal frequency + * in parts per billion * * @adjtime: Shifts the time of the hardware clock. * parameter delta: Desired change in nanoseconds. From ce19f2c0dfca3c4680f2fde304aa81d3b4911782 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 1 Nov 2012 13:42:37 +0100 Subject: [PATCH 0555/1071] ALSA: hda: Cirrus: Fix coefficient index for beep configuration commit 5a83b4b5a391f07141b157ac9daa51c409e71ab5 upstream. Signed-off-by: Alexander Stein Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index cc31346ce9b443..b922895c7ada7c 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1102,7 +1102,7 @@ static const struct hda_verb cs_coef_init_verbs[] = { | 0x0400 /* Disable Coefficient Auto increment */ )}, /* Beep */ - {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, + {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG}, {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ {} /* terminator */ From bd8d3a552e2cc77c63b98337b1d149a0e81d7d3c Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Sun, 4 Nov 2012 13:19:03 +0800 Subject: [PATCH 0556/1071] ALSA: HDA: Fix digital microphone on CS420x commit 16337e028a6dae9fbdd718c0d42161540a668ff3 upstream. Correctly enable the digital microphones with the right bits in the right coeffecient registers on Cirrus CS4206/7 codecs. It also prevents misconfiguring ADC1/2. This fixes the digital mic on the Macbook Pro 10,1/Retina. Based-on-patch-by: Alexander Stein Signed-off-by: Daniel J Blueman Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index b922895c7ada7c..2bb9bee085191b 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -96,8 +96,8 @@ enum { #define CS420X_VENDOR_NID 0x11 #define CS_DIG_OUT1_PIN_NID 0x10 #define CS_DIG_OUT2_PIN_NID 0x15 -#define CS_DMIC1_PIN_NID 0x12 -#define CS_DMIC2_PIN_NID 0x0e +#define CS_DMIC1_PIN_NID 0x0e +#define CS_DMIC2_PIN_NID 0x12 /* coef indices */ #define IDX_SPDIF_STAT 0x0000 @@ -1074,14 +1074,18 @@ static void init_input(struct hda_codec *codec) cs_automic(codec); coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ + cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG); if (is_active_pin(codec, CS_DMIC2_PIN_NID)) - coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ + coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */ if (is_active_pin(codec, CS_DMIC1_PIN_NID)) - coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off + coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off * No effect if SPDIF_OUT2 is * selected in IDX_SPDIF_CTL. */ - cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef); } else { if (spec->mic_detect) cs_automic(codec); From be6a306b17a18f0e74fa553b77ea932be7f8211f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 5 Nov 2012 12:32:46 +0100 Subject: [PATCH 0557/1071] ALSA: hda - Force to reset IEC958 status bits for AD codecs commit ae24c3191ba2ab03ec6b4be323e730e00404b4b6 upstream. Several bug reports suggest that the forcibly resetting IEC958 status bits is required for AD codecs to get the SPDIF output working properly after changing streams. Original fix credit to Javeed Shaikh. BugLink: https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/359361 Reported-by: Robin Kreis Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_analog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 0208fa121e5aad..b2cd011afbe061 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -545,6 +545,7 @@ static int ad198x_build_pcms(struct hda_codec *codec) if (spec->multiout.dig_out_nid) { info++; codec->num_pcms++; + codec->spdif_status_reset = 1; info->name = "AD198x Digital"; info->pcm_type = HDA_PCM_TYPE_SPDIF; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; From cac9141d75777308d05f9876cfd2885fd98fafa2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 10:32:47 +0100 Subject: [PATCH 0558/1071] ALSA: hda - Fix empty DAC filling in patch_via.c commit 5b3761954dac2d1393beef8210eb8cee81d16b8d upstream. In via_auto_fill_adc_nids(), the parser tries to fill dac_nids[] at the point of the current line-out (i). When no valid path is found for this output, this results in dac = 0, thus it creates a hole in dac_nids[]. This confuses is_empty_dac() and trims the detected DAC in later reference. This patch fixes the bug by appending DAC properly to dac_nids[] in via_auto_fill_adc_nids(). Reported-by: Massimo Del Fedele Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 4c404a0c644046..d6e7de64d6a721 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1875,11 +1875,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) { struct via_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; - int i, dac_num; + int i; hda_nid_t nid; + spec->multiout.num_dacs = 0; spec->multiout.dac_nids = spec->private_dac_nids; - dac_num = 0; for (i = 0; i < cfg->line_outs; i++) { hda_nid_t dac = 0; nid = cfg->line_out_pins[i]; @@ -1890,16 +1890,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) if (!i && parse_output_path(codec, nid, dac, 1, &spec->out_mix_path)) dac = spec->out_mix_path.path[0]; - if (dac) { - spec->private_dac_nids[i] = dac; - dac_num++; - } + if (dac) + spec->private_dac_nids[spec->multiout.num_dacs++] = dac; } if (!spec->out_path[0].depth && spec->out_mix_path.depth) { spec->out_path[0] = spec->out_mix_path; spec->out_mix_path.depth = 0; } - spec->multiout.num_dacs = dac_num; return 0; } From 3a31a7aa8aafb51de01e31a44738ff15683df3ab Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 10:37:48 +0100 Subject: [PATCH 0559/1071] ALSA: hda - Fix invalid connections in VT1802 codec commit ef4da45828603df57e5e21b8aa21a66ce309f79b upstream. VT1802 codec provides the invalid connection lists of NID 0x24 and 0x33 containing the routes to a non-exist widget 0x3e. This confuses the auto-parser. Fix it up in the driver by overriding these connections. Reported-by: Massimo Del Fedele Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index d6e7de64d6a721..66cd4f0a23cc0a 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -3697,6 +3697,18 @@ static const struct snd_pci_quirk vt2002p_fixups[] = { {} }; +/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e + * Replace this with mixer NID 0x1c + */ +static void fix_vt1802_connections(struct hda_codec *codec) +{ + static hda_nid_t conn_24[] = { 0x14, 0x1c }; + static hda_nid_t conn_33[] = { 0x1c }; + + snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24); + snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33); +} + /* patch for vt2002P */ static int patch_vt2002P(struct hda_codec *codec) { @@ -3711,6 +3723,8 @@ static int patch_vt2002P(struct hda_codec *codec) spec->aa_mix_nid = 0x21; override_mic_boost(codec, 0x2b, 0, 3, 40); override_mic_boost(codec, 0x29, 0, 3, 40); + if (spec->codec_type == VT1802) + fix_vt1802_connections(codec); add_secret_dac_path(codec); snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); From 1614e57c8b9a47e315493f3b780aad058e5dabb7 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Thu, 8 Nov 2012 10:23:18 +0100 Subject: [PATCH 0560/1071] ALSA: hda - Improve HP depop when system enter to S3 commit 1387e2d12799e554df2f60e7ae7fe01384bcb96f upstream. alc269_toggle_power_output() was only use in ALC269VB. I rename it to alc269vb_toggle_power_output(). Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 70ce60fd530133..cb763d4b7c51d2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5867,7 +5867,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) return alc_parse_auto_config(codec, alc269_ignore, ssids); } -static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) +static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) { int val = alc_read_coef_idx(codec, 0x04); if (power_up) @@ -5884,10 +5884,10 @@ static void alc269_shutup(struct hda_codec *codec) if (spec->codec_variant != ALC269_TYPE_ALC269VB) return; - if ((alc_get_coef0(codec) & 0x00ff) == 0x017) - alc269_toggle_power_output(codec, 0); - if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { - alc269_toggle_power_output(codec, 0); + if (spec->codec_variant == ALC269_TYPE_ALC269VB) + alc269vb_toggle_power_output(codec, 0); + if (spec->codec_variant == ALC269_TYPE_ALC269VB && + (alc_get_coef0(codec) & 0x00ff) == 0x018) { msleep(150); } } @@ -5897,24 +5897,22 @@ static int alc269_resume(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - if (spec->codec_variant == ALC269_TYPE_ALC269VB || + if (spec->codec_variant == ALC269_TYPE_ALC269VB) + alc269vb_toggle_power_output(codec, 0); + if (spec->codec_variant == ALC269_TYPE_ALC269VB && (alc_get_coef0(codec) & 0x00ff) == 0x018) { - alc269_toggle_power_output(codec, 0); msleep(150); } codec->patch_ops.init(codec); - if (spec->codec_variant == ALC269_TYPE_ALC269VB || + if (spec->codec_variant == ALC269_TYPE_ALC269VB) + alc269vb_toggle_power_output(codec, 1); + if (spec->codec_variant == ALC269_TYPE_ALC269VB && (alc_get_coef0(codec) & 0x00ff) == 0x017) { - alc269_toggle_power_output(codec, 1); msleep(200); } - if (spec->codec_variant == ALC269_TYPE_ALC269VB || - (alc_get_coef0(codec) & 0x00ff) == 0x018) - alc269_toggle_power_output(codec, 1); - snd_hda_codec_resume_amp(codec); snd_hda_codec_resume_cache(codec); hda_call_check_power_status(codec, 0x01); From a7d231db5cfa1da0cc43d0a889528736bde803c4 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Thu, 8 Nov 2012 10:25:37 +0100 Subject: [PATCH 0561/1071] ALSA: hda - Add new codec ALC668 and ALC900 (default name ALC1150) commit 19a62823eae453619604636082085812c14ee391 upstream. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cb763d4b7c51d2..d959c0ba21eb13 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7101,6 +7101,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { .patch = patch_alc662 }, { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, + { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, @@ -7118,6 +7119,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, + { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 }, {} /* terminator */ }; From 17ec635a73dea32ac4bdfa0e8f46c511271fceed Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Nov 2012 10:07:36 +0100 Subject: [PATCH 0562/1071] ALSA: hda - Add a missing quirk entry for iMac 9,1 commit 05193639ca977cc889668718adb38db6d585045b upstream. This is another variant of iMac 9,1 with a different codec SSID. Reported-and-tested-by: Everaldo Canuto Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d959c0ba21eb13..f6b5995fce9c9b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5434,6 +5434,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), From 177c55702e8093a78e1f20a62bd7e529e9822df5 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Fri, 2 Nov 2012 17:05:44 -0400 Subject: [PATCH 0563/1071] ASoC: wm8978: pll incorrectly configured when codec is master commit 55c6f4cb6ef49afbb86222c6a3ff85329199c729 upstream. When MCLK is supplied externally and BCLK and LRC are configured as outputs (codec is master), the PLL values are only calculated correctly on the first transmission. On subsequent transmissions, at differenct sample rates, the wrong PLL values are used. Test for f_opclk instead of f_pllout to determine if the PLL values are needed. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8978.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a5be3adecf7572..2f46d66fb0cabb 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, wm8978->mclk_idx = -1; f_sel = wm8978->f_mclk; } else { - if (!wm8978->f_pllout) { + if (!wm8978->f_opclk) { /* We only enter here, if OPCLK is not used */ int ret = wm8978_configure_pll(codec); if (ret < 0) From 27d215a1cf4f5f4e815b2ddf964f24b7eacee452 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 7 Nov 2012 20:38:35 +0800 Subject: [PATCH 0564/1071] ASoC: cs42l52: fix the return value of cs42l52_set_fmt() commit 5c855c8e2be67f2d5a989ef1190098f924f9f820 upstream. Fix the return value of cs42l52_set_fmt() when clock inversion is not allowed and also remove the useless variable ret. dpatch engine is used to auto generate this patch. (https://github.com/weiyj/dpatch) [We had been assigning to ret but then ignoring the value we assgined -- broonie] Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/cs42l52.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 628daf6a1d97e8..d8cfcc7c2f6b52 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -774,7 +774,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); - int ret = 0; u8 iface = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -823,7 +822,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) case SND_SOC_DAIFMT_NB_IF: break; default: - ret = -EINVAL; + return -EINVAL; } cs42l52->config.format = iface; snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format); From c392855dfc4259992947d4a960b57df4c19b71bc Mon Sep 17 00:00:00 2001 From: Misael Lopez Cruz Date: Thu, 8 Nov 2012 12:03:12 -0600 Subject: [PATCH 0565/1071] ASoC: dapm: Use card_list during DAPM shutdown commit 445632ad6dda42f4d3f9df2569a852ca0d4ea608 upstream. DAPM shutdown incorrectly uses "list" field of codec struct while iterating over probed components (codec_dev_list). "list" field refers to codecs registered in the system, "card_list" field is used for probed components. Signed-off-by: Misael Lopez Cruz Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f90139b5f50d74..c4a08a2b9612bc 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3710,7 +3710,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { struct snd_soc_codec *codec; - list_for_each_entry(codec, &card->codec_dev_list, list) { + list_for_each_entry(codec, &card->codec_dev_list, card_list) { soc_dapm_shutdown_codec(&codec->dapm); if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) snd_soc_dapm_set_bias_level(&codec->dapm, From 176b18a140915eb8d684ed823967f3010e8ac3bc Mon Sep 17 00:00:00 2001 From: Mukund Navada Date: Fri, 9 Nov 2012 11:53:40 +0530 Subject: [PATCH 0566/1071] ASoC: core: Double control update err for snd_soc_put_volsw_sx commit d055852ee86703d48b0c571e94bd2eb33aa9b91d upstream. snd_soc_put_volsw_sx function fails to update second control if first control is updated by snd_soc_update_bits_locked. Signed-off-by: Mukund Navada Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c501af6d8dbefa..8bf05d7a86cafc 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2776,8 +2776,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, val = (ucontrol->value.integer.value[0] + min) & mask; val = val << shift; - if (snd_soc_update_bits_locked(codec, reg, val_mask, val)) - return err; + err = snd_soc_update_bits_locked(codec, reg, val_mask, val); + if (err < 0) + return err; if (snd_soc_volsw_is_stereo(mc)) { val_mask = mask << rshift; From bbf1959d853718c6a0f75000425744270ff6b920 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 9 Oct 2012 16:20:15 +0300 Subject: [PATCH 0567/1071] UBIFS: fix mounting problems after power cuts commit a28ad42a4a0c6f302f488f26488b8b37c9b30024 upstream. This is a bugfix for a problem with the following symptoms: 1. A power cut happens 2. After reboot, we try to mount UBIFS 3. Mount fails with "No space left on device" error message UBIFS complains like this: UBIFS error (pid 28225): grab_empty_leb: could not find an empty LEB The root cause of this problem is that when we mount, not all LEBs are categorized. Only those which were read are. However, the 'ubifs_find_free_leb_for_idx()' function assumes that all LEBs were categorized and 'c->freeable_cnt' is valid, which is a false assumption. This patch fixes the problem by teaching 'ubifs_find_free_leb_for_idx()' to always fall back to LPT scanning if no freeable LEBs were found. This problem was reported by few people in the past, but Brent Taylor was able to reproduce it and send me a flash image which cannot be mounted, which made it easy to hunt the bug. Kudos to Brent. Reported-by: Brent Taylor Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/find.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 28ec13af28d91c..2dcf3d473fec1d 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c) if (!lprops) { lprops = ubifs_fast_find_freeable(c); if (!lprops) { - ubifs_assert(c->freeable_cnt == 0); - if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + /* + * The first condition means the following: go scan the + * LPT if there are uncategorized lprops, which means + * there may be freeable LEBs there (UBIFS does not + * store the information about freeable LEBs in the + * master node). + */ + if (c->in_a_category_cnt != c->main_lebs || + c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + ubifs_assert(c->freeable_cnt == 0); lprops = scan_for_leb_for_idx(c); if (IS_ERR(lprops)) { err = PTR_ERR(lprops); From e1813d49914ec3f7751b4981d5f46c94f111b670 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 10 Oct 2012 10:55:28 +0300 Subject: [PATCH 0568/1071] UBIFS: introduce categorized lprops counter commit 98a1eebda3cb2a84ecf1f219bb3a95769033d1bf upstream. This commit is a preparation for a subsequent bugfix. We introduce a counter for categorized lprops. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/lprops.c | 6 ++++++ fs/ubifs/ubifs.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index 86eb8e533249c4..b33ec7aa0f3f88 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, default: ubifs_assert(0); } + lprops->flags &= ~LPROPS_CAT_MASK; lprops->flags |= cat; + c->in_a_category_cnt += 1; + ubifs_assert(c->in_a_category_cnt <= c->main_lebs); } /** @@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c, default: ubifs_assert(0); } + + c->in_a_category_cnt -= 1; + ubifs_assert(c->in_a_category_cnt >= 0); } /** diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 1e5a08623d1121..51ac3e6989754e 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1184,6 +1184,8 @@ struct ubifs_debug_info; * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size) * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size) * @freeable_cnt: number of freeable LEBs in @freeable_list + * @in_a_category_cnt: count of lprops which are in a certain category, which + * basically meants that they were loaded from the flash * * @ltab_lnum: LEB number of LPT's own lprops table * @ltab_offs: offset of LPT's own lprops table @@ -1413,6 +1415,7 @@ struct ubifs_info { struct list_head freeable_list; struct list_head frdi_idx_list; int freeable_cnt; + int in_a_category_cnt; int ltab_lnum; int ltab_offs; From ab37cb2a6cde96c269a9cfb14b4affbe5fe11675 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 14 Nov 2012 11:49:53 +0000 Subject: [PATCH 0569/1071] pstore: Fix NULL pointer dereference in console writes commit 70a6f46d7b0ec03653b9ab3f8063a9717a4a53ef upstream. Passing a NULL id causes a NULL pointer deference in writers such as erst_writer and efi_pstore_write because they expect to update this id. Pass a dummy id instead. This avoids a cascade of oopses caused when the initial pstore_console_write passes a null which in turn causes writes to the console causing further oopses in subsequent pstore_console_write calls. Signed-off-by: Colin Ian King Acked-by: Kees Cook Signed-off-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman --- fs/pstore/platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 29996e8793a775..2d1e0f3912f99a 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -161,12 +161,13 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) while (s < e) { unsigned long flags; + u64 id; if (c > psinfo->bufsize) c = psinfo->bufsize; spin_lock_irqsave(&psinfo->buf_lock, flags); memcpy(psinfo->buf, s, c); - psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo); + psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo); spin_unlock_irqrestore(&psinfo->buf_lock, flags); s += c; c = e - s; From 1a62325ca4a3dda40da10a21806b6baa2c8d40dd Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 13 Nov 2012 09:48:51 +0100 Subject: [PATCH 0570/1071] regulator: fix voltage check in regulator_is_supported_voltage() commit f0f98b19e23d4426ca185e3d4ca80e6aff5ef51b upstream. regulator_is_supported_voltage() should return true only if the voltage of fixed/constant regulator is between min_uV and max_uV. Signed-off-by: Marek Szyprowski Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 48385318175a83..e6f2990a407dc6 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1942,7 +1942,7 @@ int regulator_is_supported_voltage(struct regulator *regulator, if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) - return (min_uV >= ret && ret <= max_uV); + return (min_uV <= ret && ret <= max_uV); else return ret; } From e2c0b531309e4c685cad1a4e4e7a014829deee49 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 13 Nov 2012 22:27:19 +0100 Subject: [PATCH 0571/1071] i2c-mux-pinctrl: Fix probe error path commit aa1e3e81e75ceb3d977c3292cefafcd5179eb8b8 upstream. When allocating the memory for i2c busses, the code checked the wrong variable and thus never detected if there was a memory error. Signed-off-by: Guenter Roeck Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/muxes/i2c-mux-pinctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 46a66976347605..c52401845e1f54 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev) mux->busses = devm_kzalloc(&pdev->dev, sizeof(mux->busses) * mux->pdata->bus_count, GFP_KERNEL); - if (!mux->states) { + if (!mux->busses) { dev_err(&pdev->dev, "Cannot allocate busses\n"); ret = -ENOMEM; goto err; From 05007e9de2deb4fd5e846ba78fd5e071fb8dc2ab Mon Sep 17 00:00:00 2001 From: Christoph Fritz Date: Fri, 16 Nov 2012 15:39:24 +0100 Subject: [PATCH 0572/1071] ARM: imx: ehci: fix host power mask bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 3d5e2abe6e265acc5e1fda810301243e9bac92b2 upstream. This patch sets HPM (Host power mask bit) to bit 16 according to i.MX Reference Manual. Falsely it was set to bit 8, but this controls pull-up Impedance. Reported-by: Michael Burkey Signed-off-by: Christoph Fritz Acked-by: Eric Bénard Signed-off-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-imx/ehci-imx25.c | 2 +- arch/arm/mach-imx/ehci-imx35.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c index 05bb41d99728b3..8d5b30aa319b97 100644 --- a/arch/arm/mach-imx/ehci-imx25.c +++ b/arch/arm/mach-imx/ehci-imx25.c @@ -30,7 +30,7 @@ #define MX25_H1_SIC_SHIFT 21 #define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) #define MX25_H1_PP_BIT (1 << 18) -#define MX25_H1_PM_BIT (1 << 8) +#define MX25_H1_PM_BIT (1 << 16) #define MX25_H1_IPPUE_UP_BIT (1 << 7) #define MX25_H1_IPPUE_DOWN_BIT (1 << 6) #define MX25_H1_TLL_BIT (1 << 5) diff --git a/arch/arm/mach-imx/ehci-imx35.c b/arch/arm/mach-imx/ehci-imx35.c index 73574c30cf50ca..746ce5fc3f11ca 100644 --- a/arch/arm/mach-imx/ehci-imx35.c +++ b/arch/arm/mach-imx/ehci-imx35.c @@ -30,7 +30,7 @@ #define MX35_H1_SIC_SHIFT 21 #define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) #define MX35_H1_PP_BIT (1 << 18) -#define MX35_H1_PM_BIT (1 << 8) +#define MX35_H1_PM_BIT (1 << 16) #define MX35_H1_IPPUE_UP_BIT (1 << 7) #define MX35_H1_IPPUE_DOWN_BIT (1 << 6) #define MX35_H1_TLL_BIT (1 << 5) From 65cdd08d8e6cda80990107b8d911c611bdb45bf3 Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Tue, 30 Oct 2012 15:37:09 +0530 Subject: [PATCH 0573/1071] ARM: dt: tegra: fix length of pad control and mux registers commit 322337b8fbd8c392246529d5db924820fc0c7381 upstream. The reg property contains not . Fix the length values to be length not last_offset. Signed-off-by: Pritesh Raithatha Signed-off-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/tegra30.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index 3e4334d14efb4d..3f96658f18a4c6 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -73,8 +73,8 @@ pinmux: pinmux { compatible = "nvidia,tegra30-pinmux"; - reg = <0x70000868 0xd0 /* Pad control registers */ - 0x70003000 0x3e0>; /* Mux registers */ + reg = <0x70000868 0xd4 /* Pad control registers */ + 0x70003000 0x3e4>; /* Mux registers */ }; serial@70006000 { From 8f21eab98e218f6cd38c89ad5952980234c1804d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 7 Nov 2012 18:21:51 -0800 Subject: [PATCH 0574/1071] Revert "Staging: Android alarm: IOCTL command encoding fix" commit d38e0e3fed4f58bcddef4dc93a591dfe2f651cb0 upstream. Commit 6bd4a5d96c08dc2380f8053b1bd4f879f55cd3c9 changed the ANDROID_ALARM_GET_TIME ioctls from IOW to IOR. While technically correct, the _IOC_DIR bits are ignored by alarm_ioctl, so the commit breaks a userspace ABI used by all existing Android devices for a purely cosmetic reason. Revert it. Cc: Dae S. Kim Signed-off-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/android_alarm.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index f2ffd963f1c348..d0cafd6371996c 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -51,12 +51,10 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) -#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) - /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) From fc4cc3fbd6c79a96b38c4d88d07c165e869ef7bf Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 22 Oct 2012 15:49:02 +0200 Subject: [PATCH 0575/1071] s390/gup: add missing TASK_SIZE check to get_user_pages_fast() commit d55c4c613fc4d4ad2ba0fc6fa2b57176d420f7e4 upstream. When walking page tables we need to make sure that everything is within bounds of the ASCE limit of the task's address space. Otherwise we might calculate e.g. a pud pointer which is not within a pud and dereference it. So check against TASK_SIZE (which is the ASCE limit) before walking page tables. Reviewed-by: Gerald Schaefer Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/mm/gup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 65cb06e2af4eaa..4ccf9f54355ea9 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -183,7 +183,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if (end < start) + if ((end < start) || (end > TASK_SIZE)) goto slow_irqon; /* From 17ca63a0b5ec5e2747ffa1a69f6e28a04b7c9fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sat, 10 Nov 2012 10:13:42 +0100 Subject: [PATCH 0576/1071] USB: keyspan: fix typo causing GPF on open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f0e3e35c9049087172c65302b42da8fe7ebb63a8 upstream. Commit f79b2d0f (USB: keyspan: fix NULL-pointer dereferences and memory leaks) had a small typo which made the driver use wrong offsets when mapping serial port private data. This results in in a GPF when the port is opened. Reported-by: Richard Signed-off-by: Bjørn Mork Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index f6788d7e915bce..059d44b0050f5a 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2448,7 +2448,7 @@ static void keyspan_release(struct usb_serial *serial) static int keyspan_port_probe(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct keyspan_port_private *s_priv; + struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; struct callbacks *cback; @@ -2463,7 +2463,6 @@ static int keyspan_port_probe(struct usb_serial_port *port) if (!p_priv) return -ENOMEM; - s_priv = usb_get_serial_data(port->serial); p_priv->device_details = d_details; /* Setup values for the various callback routines */ From c00d81ec46b6a4c6ad3987fde9a984acecebbbd1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 26 Oct 2012 18:44:20 +0200 Subject: [PATCH 0577/1071] USB: usb_wwan: fix bulk-urb allocation commit 8e493ca1767d4951ed1322abaa74d6edbca29918 upstream. Make sure we do not allocate urbs if we do not have a bulk endpoint. Legacy code used incorrect assumption to test for bulk endpoints. Reported-by: Dan Carpenter Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb_wwan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 2f2d074a9081e0..188b5b37b78e07 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -455,9 +455,6 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, struct usb_serial *serial = port->serial; struct urb *urb; - if (endpoint == -1) - return NULL; /* endpoint not needed */ - urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (urb == NULL) { dbg("%s: alloc for endpoint %d failed.", __func__, endpoint); @@ -487,6 +484,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port) init_usb_anchor(&portdata->delayed); for (i = 0; i < N_IN_URB; i++) { + if (!port->bulk_in_size) + break; + buffer = (u8 *)__get_free_page(GFP_KERNEL); if (!buffer) goto bail_out_error; @@ -499,8 +499,8 @@ int usb_wwan_port_probe(struct usb_serial_port *port) portdata->in_urbs[i] = urb; } for (i = 0; i < N_OUT_URB; i++) { - if (port->bulk_out_endpointAddress == -1) - continue; + if (!port->bulk_out_size) + break; buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); if (!buffer) From 92ca7e8af21a852c1ffad3f17639f4966861ce51 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 8 Nov 2012 11:56:42 -0600 Subject: [PATCH 0578/1071] USB: option: add Novatel E362 and Dell Wireless 5800 USB IDs commit fcb21645f1bd86d2be29baf48aa1b298de52ccc7 upstream. The Dell 5800 appears to be a simple rebrand of the Novatel E362. Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 76a48e45d781d7..93d6efd87a6dfb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -158,6 +158,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 +#define NOVATELWIRELESS_PRODUCT_E362 0x9010 #define NOVATELWIRELESS_PRODUCT_G1 0xA001 #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 @@ -193,6 +194,9 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181 #define DELL_PRODUCT_5730_MINICARD_VZW 0x8182 +#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */ +#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */ + #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a @@ -706,6 +710,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -728,6 +733,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, From 09390c7bc9fe02c5d5565d9701e2c26c94c08c96 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 8 Nov 2012 11:56:53 -0600 Subject: [PATCH 0579/1071] USB: option: add Alcatel X220/X500D USB IDs commit c0bc3098871dd9b964f6b45ec1e4d70d87811744 upstream. Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 93d6efd87a6dfb..f852329c4f8d66 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -287,6 +287,7 @@ static void option_instat_callback(struct urb *urb); /* ALCATEL PRODUCTS */ #define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_PRODUCT_X060S_X200 0x0000 +#define ALCATEL_PRODUCT_X220_X500D 0x0017 #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -1164,6 +1165,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), From 93010a5f6f58093d5d2204a61cdaf6bf17848d09 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 Nov 2012 18:31:35 +0200 Subject: [PATCH 0580/1071] drm/i915/sdvo: clean up connectors on intel_sdvo_init() failures commit d0ddfbd3d1346c1f481ec2289eef350cdba64b42 upstream. Any failures in intel_sdvo_init() after the intel_sdvo_setup_output() call left behind ghost connectors, attached (with a dangling pointer) to the sdvo that has been cleaned up and freed. Properly destroy any connectors attached to the encoder. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46381 CC: Chris Wilson Signed-off-by: Jani Nikula Tested-by: bjo@nord-west.org [danvet: added a comment to explain why we need to clean up connectors even when sdvo_output_setup fails.] Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_sdvo.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 20cb52dfcb5a06..d554f647613763 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2287,6 +2287,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) return true; } +static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) +{ + struct drm_device *dev = intel_sdvo->base.base.dev; + struct drm_connector *connector, *tmp; + + list_for_each_entry_safe(connector, tmp, + &dev->mode_config.connector_list, head) { + if (intel_attached_encoder(connector) == &intel_sdvo->base) + intel_sdvo_destroy(connector); + } +} + static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector, int type) @@ -2606,7 +2618,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", SDVO_NAME(intel_sdvo)); - goto err; + /* Output_setup can leave behind connectors! */ + goto err_output; } /* Only enable the hotplug irq if we need it, to work around noisy @@ -2619,12 +2632,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) - goto err; + goto err_output; if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, &intel_sdvo->pixel_clock_min, &intel_sdvo->pixel_clock_max)) - goto err; + goto err_output; DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " "clock range %dMHz - %dMHz, " @@ -2644,6 +2657,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); return true; +err_output: + intel_sdvo_output_cleanup(intel_sdvo); + err: drm_encoder_cleanup(&intel_encoder->base); i2c_del_adapter(&intel_sdvo->ddc); From abcf86b63e5aafbd2e9508ddf9f5be5de27942a4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 14 Nov 2012 09:10:39 -0500 Subject: [PATCH 0581/1071] drm/radeon: fix logic error in atombios_encoders.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b9196395c905edec512dfd6690428084228c16ec upstream. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=50431 Reported-by: David Binderman Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 6e8803a1170c24..2eb418e257f767 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1421,7 +1421,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { From 8bca5a1ee4f09bfde2f024747edaedf686ce71fe Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 16 Nov 2012 14:15:03 -0800 Subject: [PATCH 0582/1071] tmpfs: fix shmem_getpage_gfp() VM_BUG_ON commit 215c02bc33bbd5ff4d7379a909462d11f0103218 upstream. Fuzzing with trinity hit the "impossible" VM_BUG_ON(error) (which Fedora has converted to WARNING) in shmem_getpage_gfp(): WARNING: at mm/shmem.c:1151 shmem_getpage_gfp+0xa5c/0xa70() Pid: 29795, comm: trinity-child4 Not tainted 3.7.0-rc2+ #49 Call Trace: warn_slowpath_common+0x7f/0xc0 warn_slowpath_null+0x1a/0x20 shmem_getpage_gfp+0xa5c/0xa70 shmem_fault+0x4f/0xa0 __do_fault+0x71/0x5c0 handle_pte_fault+0x97/0xae0 handle_mm_fault+0x289/0x350 __do_page_fault+0x18e/0x530 do_page_fault+0x2b/0x50 page_fault+0x28/0x30 tracesys+0xe1/0xe6 Thanks to Johannes for pointing to truncation: free_swap_and_cache() only does a trylock on the page, so the page lock we've held since before confirming swap is not enough to protect against truncation. What cleanup is needed in this case? Just delete_from_swap_cache(), which takes care of the memcg uncharge. Signed-off-by: Hugh Dickins Reported-by: Dave Jones Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/shmem.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index d2eeca18e2cfdc..4ae737ebf82074 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1156,8 +1156,20 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, if (!error) { error = shmem_add_to_page_cache(page, mapping, index, gfp, swp_to_radix_entry(swap)); - /* We already confirmed swap, and make no allocation */ - VM_BUG_ON(error); + /* + * We already confirmed swap under page lock, and make + * no memory allocation here, so usually no possibility + * of error; but free_swap_and_cache() only trylocks a + * page, so it is just possible that the entry has been + * truncated or holepunched since swap was confirmed. + * shmem_undo_range() will have done some of the + * unaccounting, now delete_from_swap_cache() will do + * the rest (including mem_cgroup_uncharge_swapcache). + * Reset swap.val? No, leave it so "failed" goes back to + * "repeat": reading a hole and writing should succeed. + */ + if (error) + delete_from_swap_cache(page); } if (error) goto failed; From 05e7fb4f1ab1840c84ebb3e840d8bcce90b283cd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 Nov 2012 15:20:17 +0100 Subject: [PATCH 0583/1071] KVM: x86: Fix invalid secondary exec controls in vmx_cpuid_update() commit 29282fde80d44e587f8c152b10049a56e61659f0 upstream. The commit [ad756a16: KVM: VMX: Implement PCID/INVPCID for guests with EPT] introduced the unconditional access to SECONDARY_VM_EXEC_CONTROL, and this triggers kernel warnings like below on old CPUs: vmwrite error: reg 401e value a0568000 (err 12) Pid: 13649, comm: qemu-kvm Not tainted 3.7.0-rc4-test2+ #154 Call Trace: [] vmwrite_error+0x27/0x29 [kvm_intel] [] vmcs_writel+0x1b/0x20 [kvm_intel] [] vmx_cpuid_update+0x74/0x170 [kvm_intel] [] kvm_vcpu_ioctl_set_cpuid2+0x76/0x90 [kvm] [] kvm_arch_vcpu_ioctl+0xc37/0xed0 [kvm] [] ? __vunmap+0x9c/0x110 [] ? vmx_vcpu_load+0x39/0x1a0 [kvm_intel] [] ? kvm_arch_vcpu_load+0x52/0x1a0 [kvm] [] ? vcpu_load+0x74/0xd0 [kvm] [] kvm_vcpu_ioctl+0x110/0x5e0 [kvm] [] ? kvm_dev_ioctl+0x4d/0x4a0 [kvm] [] do_vfs_ioctl+0x8f/0x530 [] ? remove_vma+0x56/0x60 [] ? do_munmap+0x328/0x400 [] ? fget_light+0x4c/0x100 [] sys_ioctl+0x91/0xb0 [] system_call_fastpath+0x1a/0x1f This patch adds a check for the availability of secondary exec control to avoid these warnings. Signed-off-by: Takashi Iwai Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/vmx.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index b1eb202ee76a92..ff66a3bc5f7b49 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -6584,19 +6584,22 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) } } - exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); /* Exposing INVPCID only when PCID is exposed */ best = kvm_find_cpuid_entry(vcpu, 0x7, 0); if (vmx_invpcid_supported() && best && (best->ebx & bit(X86_FEATURE_INVPCID)) && guest_cpuid_has_pcid(vcpu)) { + exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); } else { - exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; - vmcs_write32(SECONDARY_VM_EXEC_CONTROL, - exec_control); + if (cpu_has_secondary_exec_ctrls()) { + exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, + exec_control); + } if (best) best->ebx &= ~bit(X86_FEATURE_INVPCID); } From 6084d9f5193ccae102f767d394913a6c0043f882 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 13 Nov 2012 18:31:55 +0000 Subject: [PATCH 0584/1071] ttm: Clear the ttm page allocated from high memory zone correctly commit ac207ed2471150e06af0afc76e4becc701fa2733 upstream. The TTM page can be allocated from high memory. In such case it is wrong to use the page_address(page) as the virtual address for the high memory page. bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=50241 Signed-off-by: Zhao Yakui Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/ttm/ttm_page_alloc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index ebc6fac96e36c9..578207ecc43fc5 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags, /* clear the pages coming from the pool if requested */ if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { list_for_each_entry(p, &plist, lru) { - clear_page(page_address(p)); + if (PageHighMem(p)) + clear_highpage(p); + else + clear_page(page_address(p)); } } From 7adaec367d93adc1c3c378eedd9a0251d0f60a8e Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 16 Nov 2012 14:14:49 -0800 Subject: [PATCH 0585/1071] memcg: oom: fix totalpages calculation for memory.swappiness==0 commit 9a5a8f19b43430752067ecaee62fc59e11e88fa6 upstream. oom_badness() takes a totalpages argument which says how many pages are available and it uses it as a base for the score calculation. The value is calculated by mem_cgroup_get_limit which considers both limit and total_swap_pages (resp. memsw portion of it). This is usually correct but since fe35004fbf9e ("mm: avoid swapping out with swappiness==0") we do not swap when swappiness is 0 which means that we cannot really use up all the totalpages pages. This in turn confuses oom score calculation if the memcg limit is much smaller than the available swap because the used memory (capped by the limit) is negligible comparing to totalpages so the resulting score is too small if adj!=0 (typically task with CAP_SYS_ADMIN or non zero oom_score_adj). A wrong process might be selected as result. The problem can be worked around by checking mem_cgroup_swappiness==0 and not considering swap at all in such a case. Signed-off-by: Michal Hocko Acked-by: David Rientjes Acked-by: Johannes Weiner Acked-by: KOSAKI Motohiro Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- Documentation/cgroups/memory.txt | 4 ++++ mm/memcontrol.c | 21 +++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 4372e6b8a353f3..97aa4ebf6d930a 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -466,6 +466,10 @@ Note: 5.3 swappiness Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only. +Please note that unlike the global swappiness, memcg knob set to 0 +really prevents from any swapping even if there is a swap storage +available. This might lead to memcg OOM killer if there are no file +pages to reclaim. Following cgroups' swappiness can't be changed. - root cgroup (uses /proc/sys/vm/swappiness). diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 795e525afaba89..7cc4239f36e0c7 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1458,17 +1458,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg) static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) { u64 limit; - u64 memsw; limit = res_counter_read_u64(&memcg->res, RES_LIMIT); - limit += total_swap_pages << PAGE_SHIFT; - memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); /* - * If memsw is finite and limits the amount of swap space available - * to this memcg, return that limit. + * Do not consider swap space if we cannot swap due to swappiness */ - return min(limit, memsw); + if (mem_cgroup_swappiness(memcg)) { + u64 memsw; + + limit += total_swap_pages << PAGE_SHIFT; + memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); + + /* + * If memsw is finite and limits the amount of swap space + * available to this memcg, return that limit. + */ + limit = min(limit, memsw); + } + + return limit; } void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, From dd51fb8944830c19fe9f946e32c95c569985ac85 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 16 Nov 2012 14:14:54 -0800 Subject: [PATCH 0586/1071] memcg: fix hotplugged memory zone oops commit bea8c150a7efbc0f204e709b7274fe273f55e0d3 upstream. When MEMCG is configured on (even when it's disabled by boot option), when adding or removing a page to/from its lru list, the zone pointer used for stats updates is nowadays taken from the struct lruvec. (On many configurations, calculating zone from page is slower.) But we have no code to update all the lruvecs (per zone, per memcg) when a memory node is hotadded. Here's an extract from the oops which results when running numactl to bind a program to a newly onlined node: BUG: unable to handle kernel NULL pointer dereference at 0000000000000f60 IP: __mod_zone_page_state+0x9/0x60 Pid: 1219, comm: numactl Not tainted 3.6.0-rc5+ #180 Bochs Bochs Process numactl (pid: 1219, threadinfo ffff880039abc000, task ffff8800383c4ce0) Call Trace: __pagevec_lru_add_fn+0xdf/0x140 pagevec_lru_move_fn+0xb1/0x100 __pagevec_lru_add+0x1c/0x30 lru_add_drain_cpu+0xa3/0x130 lru_add_drain+0x2f/0x40 ... The natural solution might be to use a memcg callback whenever memory is hotadded; but that solution has not been scoped out, and it happens that we do have an easy location at which to update lruvec->zone. The lruvec pointer is discovered either by mem_cgroup_zone_lruvec() or by mem_cgroup_page_lruvec(), and both of those do know the right zone. So check and set lruvec->zone in those; and remove the inadequate attempt to set lruvec->zone from lruvec_init(), which is called before NODE_DATA(node) has been allocated in such cases. Ah, there was one exceptionr. For no particularly good reason, mem_cgroup_force_empty_list() has its own code for deciding lruvec. Change it to use the standard mem_cgroup_zone_lruvec() and mem_cgroup_get_lru_size() too. In fact it was already safe against such an oops (the lru lists in danger could only be empty), but we're better proofed against future changes this way. I've marked this for stable (3.6) since we introduced the problem in 3.5 (now closed to stable); but I have no idea if this is the only fix needed to get memory hotadd working with memcg in 3.6, and received no answer when I enquired twice before. Reported-by: Tang Chen Signed-off-by: Hugh Dickins Acked-by: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Cc: Konstantin Khlebnikov Cc: Wen Congyang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mmzone.h | 2 +- mm/memcontrol.c | 46 ++++++++++++++++++++++++++++++++---------- mm/mmzone.c | 6 +----- mm/page_alloc.c | 2 +- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 2daa54f55db7bc..a16d92907af0bd 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -744,7 +744,7 @@ extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn, unsigned long size, enum memmap_context context); -extern void lruvec_init(struct lruvec *lruvec, struct zone *zone); +extern void lruvec_init(struct lruvec *lruvec); static inline struct zone *lruvec_zone(struct lruvec *lruvec) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7cc4239f36e0c7..a6e2f8134010cc 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1061,12 +1061,24 @@ struct lruvec *mem_cgroup_zone_lruvec(struct zone *zone, struct mem_cgroup *memcg) { struct mem_cgroup_per_zone *mz; + struct lruvec *lruvec; - if (mem_cgroup_disabled()) - return &zone->lruvec; + if (mem_cgroup_disabled()) { + lruvec = &zone->lruvec; + goto out; + } mz = mem_cgroup_zoneinfo(memcg, zone_to_nid(zone), zone_idx(zone)); - return &mz->lruvec; + lruvec = &mz->lruvec; +out: + /* + * Since a node can be onlined after the mem_cgroup was created, + * we have to be prepared to initialize lruvec->zone here; + * and if offlined then reonlined, we need to reinitialize it. + */ + if (unlikely(lruvec->zone != zone)) + lruvec->zone = zone; + return lruvec; } /* @@ -1093,9 +1105,12 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone) struct mem_cgroup_per_zone *mz; struct mem_cgroup *memcg; struct page_cgroup *pc; + struct lruvec *lruvec; - if (mem_cgroup_disabled()) - return &zone->lruvec; + if (mem_cgroup_disabled()) { + lruvec = &zone->lruvec; + goto out; + } pc = lookup_page_cgroup(page); memcg = pc->mem_cgroup; @@ -1113,7 +1128,16 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone) pc->mem_cgroup = memcg = root_mem_cgroup; mz = page_cgroup_zoneinfo(memcg, page); - return &mz->lruvec; + lruvec = &mz->lruvec; +out: + /* + * Since a node can be onlined after the mem_cgroup was created, + * we have to be prepared to initialize lruvec->zone here; + * and if offlined then reonlined, we need to reinitialize it. + */ + if (unlikely(lruvec->zone != zone)) + lruvec->zone = zone; + return lruvec; } /** @@ -3703,17 +3727,17 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg, int node, int zid, enum lru_list lru) { - struct mem_cgroup_per_zone *mz; + struct lruvec *lruvec; unsigned long flags, loop; struct list_head *list; struct page *busy; struct zone *zone; zone = &NODE_DATA(node)->node_zones[zid]; - mz = mem_cgroup_zoneinfo(memcg, node, zid); - list = &mz->lruvec.lists[lru]; + lruvec = mem_cgroup_zone_lruvec(zone, memcg); + list = &lruvec->lists[lru]; - loop = mz->lru_size[lru]; + loop = mem_cgroup_get_lru_size(lruvec, lru); /* give some margin against EBUSY etc...*/ loop += 256; busy = NULL; @@ -4751,7 +4775,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node) for (zone = 0; zone < MAX_NR_ZONES; zone++) { mz = &pn->zoneinfo[zone]; - lruvec_init(&mz->lruvec, &NODE_DATA(node)->node_zones[zone]); + lruvec_init(&mz->lruvec); mz->usage_in_excess = 0; mz->on_tree = false; mz->memcg = memcg; diff --git a/mm/mmzone.c b/mm/mmzone.c index 3cef80f6ac79ff..4596d81b89b162 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -87,7 +87,7 @@ int memmap_valid_within(unsigned long pfn, } #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */ -void lruvec_init(struct lruvec *lruvec, struct zone *zone) +void lruvec_init(struct lruvec *lruvec) { enum lru_list lru; @@ -95,8 +95,4 @@ void lruvec_init(struct lruvec *lruvec, struct zone *zone) for_each_lru(lru) INIT_LIST_HEAD(&lruvec->lists[lru]); - -#ifdef CONFIG_MEMCG - lruvec->zone = zone; -#endif } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index c13ea7538891d8..d2d8f54900e515 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4456,7 +4456,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, zone->zone_pgdat = pgdat; zone_pcp_init(zone); - lruvec_init(&zone->lruvec, zone); + lruvec_init(&zone->lruvec); if (!size) continue; From e91533adb3ab60e10f05a537936e475098522766 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 4 Nov 2012 09:29:17 +0100 Subject: [PATCH 0587/1071] iwlwifi: handle DMA mapping failures commit 7c34158231b2eda8dcbd297be2bb1559e69cb433 upstream. The RX replenish code doesn't handle DMA mapping failures, which will cause issues if there actually is a failure. This was reported by Shuah Khan who found a DMA mapping framework warning ("device driver failed to check map error"). Reported-by: Shuah Khan Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/pcie/rx.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index d1a61ba6247ab6..c3d2751df2daba 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -314,6 +314,14 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) dma_map_page(trans->dev, page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); + if (dma_mapping_error(trans->dev, rxb->page_dma)) { + rxb->page = NULL; + spin_lock_irqsave(&rxq->lock, flags); + list_add(&rxb->list, &rxq->rx_used); + spin_unlock_irqrestore(&rxq->lock, flags); + __free_pages(page, trans_pcie->rx_page_order); + return; + } /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); /* and also 256 byte aligned! */ @@ -463,8 +471,19 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, dma_map_page(trans->dev, rxb->page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; + if (dma_mapping_error(trans->dev, rxb->page_dma)) { + /* + * free the page(s) as well to not break + * the invariant that the items on the used + * list have no page(s) + */ + __free_pages(rxb->page, trans_pcie->rx_page_order); + rxb->page = NULL; + list_add_tail(&rxb->list, &rxq->rx_used); + } else { + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + } } else list_add_tail(&rxb->list, &rxq->rx_used); spin_unlock_irqrestore(&rxq->lock, flags); From c322410c338e617342312c0a7418708ee9187c1a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Nov 2012 10:51:34 +0100 Subject: [PATCH 0588/1071] wireless: allow 40 MHz on world roaming channels 12/13 commit 43c771a1963ab461a2f194e3c97fded1d5fe262f upstream. When in world roaming mode, allow 40 MHz to be used on channels 12 and 13 so that an AP that is, e.g., using HT40+ on channel 9 (in the UK) can be used. Reported-by: Eddie Chapman Tested-by: Eddie Chapman Acked-by: Luis R. Rodriguez Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 72d170ca340665..3062b88e9b6d27 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -141,9 +141,8 @@ static const struct ieee80211_regdomain world_regdom = { .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11b/g, channels 12..13. No HT40 - * channel fits here. */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, + /* IEEE 802.11b/g, channels 12..13. */ + REG_RULE(2467-10, 2472+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), /* IEEE 802.11 channel 14 - Only JP enables From 9437e9d67094de0a69de1585b28932d6ac2b1911 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 19 Oct 2012 20:10:46 +0300 Subject: [PATCH 0589/1071] Bluetooth: Fix having bogus entries in mgmt_read_index_list reply commit 476e44cb19f1fbf2d5883dddcc0ce31b33b45915 upstream. The mgmt_read_index_list uses one loop to calculate the max needed size of its response with the help of an upper-bound of the controller count. The second loop is more strict as it checks for HCI_SETUP (which might have gotten set after the first loop) and could result in some indexes being skipped. Because of this the function needs to readjust the event length and index count after filling in the response array. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/mgmt.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index eba022de3c205b..534250ada18d40 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -321,7 +321,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, struct hci_dev *d; size_t rp_len; u16 count; - int i, err; + int err; BT_DBG("sock %p", sk); @@ -339,17 +339,18 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, return -ENOMEM; } - rp->num_controllers = cpu_to_le16(count); - - i = 0; + count = 0; list_for_each_entry(d, &hci_dev_list, list) { if (test_bit(HCI_SETUP, &d->dev_flags)) continue; - rp->index[i++] = cpu_to_le16(d->id); + rp->index[count++] = cpu_to_le16(d->id); BT_DBG("Added hci%u", d->id); } + rp->num_controllers = cpu_to_le16(count); + rp_len = sizeof(*rp) + (2 * count); + read_unlock(&hci_dev_list_lock); err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp, From 6ee34a305634346a23fce16352019d45097dc425 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 17 Nov 2012 22:27:04 +0100 Subject: [PATCH 0590/1071] m68k: fix sigset_t accessor functions commit 34fa78b59c52d1db3513db4c1a999db26b2e9ac2 upstream. The sigaddset/sigdelset/sigismember functions that are implemented with bitfield insn cannot allow the sigset argument to be placed in a data register since the sigset is wider than 32 bits. Remove the "d" constraint from the asm statements. The effect of the bug is that sending RT signals does not work, the signal number is truncated modulo 32. Signed-off-by: Andreas Schwab Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- arch/m68k/include/asm/signal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 60e88660169c45..93fe83e7ffb5a0 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h @@ -156,7 +156,7 @@ typedef struct sigaltstack { static inline void sigaddset(sigset_t *set, int _sig) { asm ("bfset %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -164,7 +164,7 @@ static inline void sigaddset(sigset_t *set, int _sig) static inline void sigdelset(sigset_t *set, int _sig) { asm ("bfclr %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -180,7 +180,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig) int ret; asm ("bfextu %1{%2,#1},%0" : "=d" (ret) - : "od" (*set), "id" ((_sig-1) ^ 31) + : "o" (*set), "id" ((_sig-1) ^ 31) : "cc"); return ret; } From dc61f8a222dd360e802205bbc908b175848aa5bf Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Sun, 11 Nov 2012 11:20:01 +0000 Subject: [PATCH 0591/1071] ipv4: avoid undefined behavior in do_ip_setsockopt() [ Upstream commit 0c9f79be295c99ac7e4b569ca493d75fdcc19e4e ] (1< Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_sockglue.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 5eea4a811042ad..14bbfcf717acb9 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level, struct inet_sock *inet = inet_sk(sk); int val = 0, err; - if (((1<= sizeof(int)) { if (get_user(val, (int __user *) optval)) return -EFAULT; From b31143d12a55f2cbb2875abf46239eb7ef417c74 Mon Sep 17 00:00:00 2001 From: Saurabh Mohan Date: Wed, 14 Nov 2012 18:08:15 -0800 Subject: [PATCH 0592/1071] ipv4/ip_vti.c: VTI fix post-decryption forwarding [ Upstream commit b2942004fb5c9f3304b77e187b8a1977b3626c9b ] With the latest kernel there are two things that must be done post decryption so that the packet are forwarded. 1. Remove the mark from the packet. This will cause the packet to not match the ipsec-policy again. However doing this causes the post-decryption check to fail also and the packet will get dropped. (cat /proc/net/xfrm_stat). 2. Remove the sp association in the skbuff so that no policy check is done on the packet for VTI tunnels. Due to #2 above we must now do a security-policy check in the vti rcv path prior to resetting the mark in the skbuff. Signed-off-by: Saurabh Mohan Reported-by: Ruben Herold Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_vti.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 3511ffba7bd410..bf89b21d22d0f6 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -341,12 +341,17 @@ static int vti_rcv(struct sk_buff *skb) if (tunnel != NULL) { struct pcpu_tstats *tstats; + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) + return -1; + tstats = this_cpu_ptr(tunnel->dev->tstats); u64_stats_update_begin(&tstats->syncp); tstats->rx_packets++; tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); + skb->mark = 0; + secpath_reset(skb); skb->dev = tunnel->dev; rcu_read_unlock(); return 1; From 2dba0003a5cf5f7834ec89ca6d488c4763a20505 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sat, 10 Nov 2012 19:52:34 +0000 Subject: [PATCH 0593/1071] ipv6: setsockopt(IPIPPROTO_IPV6, IPV6_MINHOPCOUNT) forgot to set return value [ Upstream commit d4596bad2a713fcd0def492b1960e6d899d5baa8 ] Cc: Stephen Hemminger Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ipv6_sockglue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index ba6d13d1f1e162..e02faed6d17efa 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -827,6 +827,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (val < 0 || val > 255) goto e_inval; np->min_hopcount = val; + retv = 0; break; case IPV6_DONTFRAG: np->dontfrag = valbool; From 37afa2af2d81d3508a47adf9a5029096c2900c21 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 14 Nov 2012 02:51:04 +0000 Subject: [PATCH 0594/1071] net: correct check in dev_addr_del() [ Upstream commit a652208e0b52c190e57f2a075ffb5e897fe31c3b ] Check (ha->addr == dev->dev_addr) is always true because dev_addr_init() sets this. Correct the check to behave properly on addr removal. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev_addr_lists.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index c4cc2bc49f06d4..716f3638b3aa4e 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -317,7 +317,8 @@ int dev_addr_del(struct net_device *dev, unsigned char *addr, */ ha = list_first_entry(&dev->dev_addrs.list, struct netdev_hw_addr, list); - if (ha->addr == dev->dev_addr && ha->refcount == 1) + if (!memcmp(ha->addr, addr, dev->addr_len) && + ha->type == addr_type && ha->refcount == 1) return -ENOENT; err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, From a809dffbbbcfbac5f6e6e291e472ac3ca91e0ca2 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Fri, 16 Nov 2012 09:04:15 +0000 Subject: [PATCH 0595/1071] net-rps: Fix brokeness causing OOO packets [ Upstream commit baefa31db2f2b13a05d1b81bdf2d20d487f58b0a ] In commit c445477d74ab3779 which adds aRFS to the kernel, the CPU selected for RFS is not set correctly when CPU is changing. This is causing OOO packets and probably other issues. Signed-off-by: Tom Herbert Acked-by: Eric Dumazet Acked-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index aed87a401458db..1dce5b5f614b74 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2793,8 +2793,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, if (unlikely(tcpu != next_cpu) && (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || ((int)(per_cpu(softnet_data, tcpu).input_queue_head - - rflow->last_qtail)) >= 0)) + rflow->last_qtail)) >= 0)) { + tcpu = next_cpu; rflow = set_rps_cpu(dev, skb, rflow, next_cpu); + } if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { *rflowp = rflow; From c6f7b86211233142300aeec7b1ab4ae640b81abd Mon Sep 17 00:00:00 2001 From: Andrew Vagin Date: Thu, 15 Nov 2012 04:03:17 +0000 Subject: [PATCH 0596/1071] tcp: fix retransmission in repair mode [ Upstream commit ec34232575083fd0f43d3a101e8ebb041b203761 ] Currently if a socket was repaired with a few packet in a write queue, a kernel bug may be triggered: kernel BUG at net/ipv4/tcp_output.c:2330! RIP: 0010:[] tcp_retransmit_skb+0x5ff/0x610 According to the initial realization v3.4-rc2-963-gc0e88ff, all skb-s should look like already posted. This patch fixes code according with this sentence. Here are three points, which were not done in the initial patch: 1. A tcp send head should not be changed 2. Initialize TSO state of a skb 3. Reset the retransmission time This patch moves logic from tcp_sendmsg to tcp_write_xmit. A packet passes the ussual way, but isn't sent to network. This patch solves all described problems and handles tcp_sendpages. Signed-off-by: Andrey Vagin Cc: Pavel Emelyanov Cc: "David S. Miller" Cc: Alexey Kuznetsov Cc: James Morris Cc: Hideaki YOSHIFUJI Cc: Patrick McHardy Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 4 ++-- net/ipv4/tcp_output.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 49dd9930781533..b0b39f60495e96 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1236,7 +1236,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, wait_for_sndbuf: set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); wait_for_memory: - if (copied && likely(!tp->repair)) + if (copied) tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) @@ -1247,7 +1247,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } out: - if (copied && likely(!tp->repair)) + if (copied) tcp_push(sk, flags, mss_now, tp->nonagle); release_sock(sk); return copied + copied_syn; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index d04632673a9e5f..6735beaacbedb8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1977,6 +1977,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, tso_segs = tcp_init_tso_segs(sk, skb, mss_now); BUG_ON(!tso_segs); + if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) + goto repair; /* Skip network transmission */ + cwnd_quota = tcp_cwnd_test(tp, skb); if (!cwnd_quota) break; @@ -2017,6 +2020,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp))) break; +repair: /* Advance the send_head. This one is sent out. * This call will increment packets_out. */ From e7c1a252a7236c6a318c703a1bf29e3261a44e9c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 16 Nov 2012 05:31:53 +0000 Subject: [PATCH 0597/1071] tcp: handle tcp_net_metrics_init() order-5 memory allocation failures [ Upstream commit 976a702ac9eeacea09e588456ab165dc06f9ee83 ] order-5 allocations can fail with current kernels, we should try vmalloc() as well. Reported-by: Julien Tinnes Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_metrics.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 0abe67bb4d3a3a..2efd1a511fcc63 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -1,13 +1,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include @@ -722,7 +722,10 @@ static int __net_init tcp_net_metrics_init(struct net *net) net->ipv4.tcp_metrics_hash_log = order_base_2(slots); size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log; - net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL); + net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + if (!net->ipv4.tcp_metrics_hash) + net->ipv4.tcp_metrics_hash = vzalloc(size); + if (!net->ipv4.tcp_metrics_hash) return -ENOMEM; @@ -743,7 +746,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net) tm = next; } } - kfree(net->ipv4.tcp_metrics_hash); + if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash)) + vfree(net->ipv4.tcp_metrics_hash); + else + kfree(net->ipv4.tcp_metrics_hash); } static __net_initdata struct pernet_operations tcp_net_metrics_ops = { From 347bd4501eec64db816bcd2438e38784f0107041 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 16 Nov 2012 14:15:04 -0800 Subject: [PATCH 0598/1071] tmpfs: change final i_blocks BUG to WARNING commit 0f3c42f522dc1ad7e27affc0a4aa8c790bce0a66 upstream. Under a particular load on one machine, I have hit shmem_evict_inode()'s BUG_ON(inode->i_blocks), enough times to narrow it down to a particular race between swapout and eviction. It comes from the "if (freed > 0)" asymmetry in shmem_recalc_inode(), and the lack of coherent locking between mapping's nrpages and shmem's swapped count. There's a window in shmem_writepage(), between lowering nrpages in shmem_delete_from_page_cache() and then raising swapped count, when the freed count appears to be +1 when it should be 0, and then the asymmetry stops it from being corrected with -1 before hitting the BUG. One answer is coherent locking: using tree_lock throughout, without info->lock; reasonable, but the raw_spin_lock in percpu_counter_add() on used_blocks makes that messier than expected. Another answer may be a further effort to eliminate the weird shmem_recalc_inode() altogether, but previous attempts at that failed. So far undecided, but for now change the BUG_ON to WARN_ON: in usual circumstances it remains a useful consistency check. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/shmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/shmem.c b/mm/shmem.c index 4ae737ebf82074..31e1506eb5cd1f 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -654,7 +654,7 @@ static void shmem_evict_inode(struct inode *inode) kfree(xattr->name); kfree(xattr); } - BUG_ON(inode->i_blocks); + WARN_ON(inode->i_blocks); shmem_free_inode(inode->i_sb); clear_inode(inode); } From e01d83515635e7176cb69f1ac2c59ad1e39e8a63 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Nov 2012 08:20:02 +0100 Subject: [PATCH 0599/1071] ALSA: usb-audio: Fix crash at re-preparing the PCM stream commit f58161ba1b05a968e5136824b5a16b714b6a5317 upstream. There are bug reports of a crash with USB-audio devices when PCM prepare is performed immediately after the stream is stopped via trigger callback. It turned out that the problem is that we don't wait until all URBs are killed. This patch adds a new function to synchronize the pending stop operation on an endpoint, and calls in the prepare callback for avoiding the crash above. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=49181 Reported-and-tested-by: Artem S. Tashkinov Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/endpoint.c | 13 +++++++++++++ sound/usb/endpoint.h | 1 + sound/usb/pcm.c | 3 +++ 3 files changed, 17 insertions(+) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index d9de6670b97ef8..eafc8897af7dda 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -35,6 +35,7 @@ #define EP_FLAG_ACTIVATED 0 #define EP_FLAG_RUNNING 1 +#define EP_FLAG_STOPPING 2 /* * snd_usb_endpoint is a model that abstracts everything related to an @@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) if (alive) snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", alive, ep->ep_num); + clear_bit(EP_FLAG_STOPPING, &ep->flags); return 0; } +/* sync the pending stop operation; + * this function itself doesn't trigger the stop operation + */ +void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) +{ + if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) + wait_clear_urbs(ep); +} + /* * unlink active urbs. */ @@ -913,6 +924,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, if (wait) wait_clear_urbs(ep); + else + set_bit(EP_FLAG_STOPPING, &ep->flags); } } diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index cbbbdf226d66b6..774a0ebc8c5ac5 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -16,6 +16,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, int force, int can_sleep, int wait); +void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); void snd_usb_endpoint_free(struct list_head *head); diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index ee3c15c546e035..90731af0a76203 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -563,6 +563,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; } + snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); + snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); + /* some unit conversions in runtime */ subs->data_endpoint->maxframesize = bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); From 3707c973f834b0035e611ceb89162d3f6081e262 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 6 Nov 2012 00:49:28 -0600 Subject: [PATCH 0600/1071] GFS2: Don't call file_accessed() with a shared glock commit 3d1626889a64bd5a661544d582036a0a02104a60 upstream. file_accessed() was being called by gfs2_mmap() with a shared glock. If it needed to update the atime, it was crashing because it dirtied the inode in gfs2_dirty_inode() without holding an exclusive lock. gfs2_dirty_inode() checked if the caller was already holding a glock, but it didn't make sure that the glock was in the exclusive state. Now, instead of calling file_accessed() while holding the shared lock in gfs2_mmap(), file_accessed() is called after grabbing and releasing the glock to update the inode. If file_accessed() needs to update the atime, it will grab an exclusive lock in gfs2_dirty_inode(). gfs2_dirty_inode() now also checks to make sure that if the calling process has already locked the glock, it has an exclusive lock. Signed-off-by: Benjamin Marzinski Signed-off-by: Steven Whitehouse Signed-off-by: Greg Kroah-Hartman --- fs/gfs2/file.c | 12 +++++------- fs/gfs2/super.c | 3 ++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 382000ffac1f7e..07cc71ffe5d99a 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -515,15 +515,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) struct gfs2_holder i_gh; int error; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); - error = gfs2_glock_nq(&i_gh); - if (error == 0) { - file_accessed(file); - gfs2_glock_dq(&i_gh); - } - gfs2_holder_uninit(&i_gh); + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, + &i_gh); if (error) return error; + /* grab lock to update inode */ + gfs2_glock_dq_uninit(&i_gh); + file_accessed(file); } vma->vm_ops = &gfs2_vm_ops; vma->vm_flags |= VM_CAN_NONLINEAR; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index fc3168f47a146a..12ff463cba0b95 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) return; } need_unlock = 1; - } + } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) + return; if (current->journal_info == NULL) { ret = gfs2_trans_begin(sdp, RES_DINODE, 0); From 8deae47cf81c03c730b6b5d0a21ab3b50cda33c1 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Sun, 9 Sep 2012 13:55:26 +0000 Subject: [PATCH 0601/1071] r8169: use unlimited DMA burst for TX commit aee77e4accbeb2c86b1d294cd84fec4a12dde3bd upstream. The r8169 driver currently limits the DMA burst for TX to 1024 bytes. I have a box where this prevents the interface from using the gigabit line to its full potential. This patch solves the problem by setting TX_DMA_BURST to unlimited. The box has an ASRock B75M motherboard with on-board RTL8168evl/8111evl (XID 0c900880). TSO is enabled. I used netperf (TCP_STREAM test) to measure the dependency of TX throughput on MTU. I did it for three different values of TX_DMA_BURST ('5'=512, '6'=1024, '7'=unlimited). This chart shows the results: http://michich.fedorapeople.org/r8169/r8169-effects-of-TX_DMA_BURST.png Interesting points: - With the current DMA burst limit (1024): - at the default MTU=1500 I get only 842 Mbit/s. - when going from small MTU, the performance rises monotonically with increasing MTU only up to a peak at MTU=1076 (908 MBit/s). Then there's a sudden drop to 762 MBit/s from which the throughput rises monotonically again with further MTU increases. - With a smaller DMA burst limit (512): - there's a similar peak at MTU=1076 and another one at MTU=564. - With unlimited DMA burst: - at the default MTU=1500 I get nice 940 Mbit/s. - the throughput rises monotonically with increasing MTU with no strange peaks. Notice that the peaks occur at MTU sizes that are multiples of the DMA burst limit plus 52. Why 52? Because: 20 (IP header) + 20 (TCP header) + 12 (TCP options) = 52 The Realtek-provided r8168 driver (v8.032.00) uses unlimited TX DMA burst too, except for CFG_METHOD_1 where the TX DMA burst is set to 512 bytes. CFG_METHOD_1 appears to be the oldest MAC version of "RTL8168B/8111B", i.e. RTL_GIGA_MAC_VER_11 in r8169. Not sure if this MAC version really needs the smaller burst limit, or if any other versions have similar requirements. Signed-off-by: Michal Schmidt Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index b47d5b35024ed4..549314f5e0f468 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -77,7 +77,7 @@ static const int multicast_filter_limit = 32; #define MAX_READ_REQUEST_SHIFT 12 -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ From 605e644a5c9a8665b39d544354cfc4aafcefc694 Mon Sep 17 00:00:00 2001 From: Mojiong Qiu Date: Tue, 6 Nov 2012 16:08:15 +0800 Subject: [PATCH 0602/1071] xen/events: fix RCU warning, or Call idle notifier after irq_enter() commit 772aebcefeff310f80e32b874988af0076cb799d upstream. exit_idle() should be called after irq_enter(), otherwise it throws: [ INFO: suspicious RCU usage. ] 3.6.5 #1 Not tainted ------------------------------- include/linux/rcupdate.h:725 rcu_read_lock() used illegally while idle! other info that might help us debug this: RCU used illegally from idle CPU! rcu_scheduler_active = 1, debug_locks = 1 RCU used illegally from extended quiescent state! 1 lock held by swapper/0/0: #0: (rcu_read_lock){......}, at: [] __atomic_notifier_call_chain+0x0/0x140 stack backtrace: Pid: 0, comm: swapper/0 Not tainted 3.6.5 #1 Call Trace: [] lockdep_rcu_suspicious+0xe2/0x130 [] __atomic_notifier_call_chain+0x12c/0x140 [] ? atomic_notifier_chain_unregister+0x90/0x90 [] ? trace_hardirqs_off+0xd/0x10 [] atomic_notifier_call_chain+0x16/0x20 [] exit_idle+0x43/0x50 [] xen_evtchn_do_upcall+0x25/0x50 [] xen_do_hypervisor_callback+0x1e/0x30 [] ? hypercall_page+0x3aa/0x1000 [] ? hypercall_page+0x3aa/0x1000 [] ? xen_safe_halt+0x10/0x20 [] ? default_idle+0xba/0x570 [] ? cpu_idle+0xdf/0x140 [] ? rest_init+0x135/0x144 [] ? csum_partial_copy_generic+0x16c/0x16c [] ? start_kernel+0x3db/0x3e8 [] ? repair_env_string+0x5a/0x5a [] ? x86_64_start_reservations+0x131/0x135 [] ? xen_start_kernel+0x465/0x46 Git commit 98ad1cc14a5c4fd658f9d72c6ba5c86dfd3ce0d5 Author: Frederic Weisbecker Date: Fri Oct 7 18:22:09 2011 +0200 x86: Call idle notifier after irq_enter() did this, but it missed the Xen code. Signed-off-by: Mojiong Qiu Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 7595581d032cc9..99c53450b455d9 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1374,8 +1374,8 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - exit_idle(); irq_enter(); + exit_idle(); __xen_evtchn_do_upcall(); From 0c46d72c25ddabd39d02ce5d63fc722f59671c1d Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Wed, 5 Sep 2012 21:36:47 -0700 Subject: [PATCH 0603/1071] SCSI: isci: Allow SSP tasks into the task management path. commit 54b46677757ff8d6c282305fc7710f466b63d6dc upstream. This commit fixes a driver bug for SSP tasks that require task management in the target after they complete in the SCU hardware. The problem was manifested in the function "isci_task_abort_task", which tests to see if the sas_task.lldd_task is non-NULL before allowing task management; this bug would always NULL lldd_task in the SCU I/O completion path even if target management was required, which would prevent task / target manangement from happening. Note that in the case of SATA/STP targets, error recovery is provided by the libata error handler which is why SATA/STP device recovery worked correctly even though SSP handling did not. Signed-off-by: Jeff Skirvin Signed-off-by: James Bottomley Cc: "Dorau, Lukasz" Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/isci/host.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 45385f531649d7..446fdd831b0819 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1079,7 +1079,6 @@ static void sci_controller_completion_handler(struct isci_host *ihost) void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_task *task) { - task->lldd_task = NULL; if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags) && !(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { if (test_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags)) { @@ -1087,16 +1086,19 @@ void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct sas_ta dev_dbg(&ihost->pdev->dev, "%s: Normal - ireq/task = %p/%p\n", __func__, ireq, task); - + task->lldd_task = NULL; task->task_done(task); } else { dev_dbg(&ihost->pdev->dev, "%s: Error - ireq/task = %p/%p\n", __func__, ireq, task); - + if (sas_protocol_ata(task->task_proto)) + task->lldd_task = NULL; sas_task_abort(task); } - } + } else + task->lldd_task = NULL; + if (test_and_clear_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags)) wake_up_all(&ihost->eventq); From 596365ec90394f937d52ad85fb674cab3d034ab3 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 1 Oct 2012 11:43:49 -0400 Subject: [PATCH 0604/1071] tg3: unconditionally select HWMON support when tg3 is enabled. commit de0a41484c47d783dd4d442914815076aa2caac2 upstream. There is the seldom used corner case where HWMON=m at the same time as TIGON3=y (typically randconfigs) which will cause a link fail like: drivers/built-in.o: In function `tg3_close': tg3.c:(.text+0x16bd86): undefined reference to `hwmon_device_unregister' drivers/built-in.o: In function `tg3_hwmon_open': tg3.c:(.text+0x16fc4b): undefined reference to `hwmon_device_register' make[1]: *** [vmlinux] Error 1 Fix it as suggested by DaveM[1] by having the Kconfig logic simply select HWMON when TIGON3 is selected. This gets rid of all the extra IS_ENABLED ifdeffery in tg3.c as a side benefit. [1] http://marc.info/?l=linux-netdev&m=134250573718151&w=2 Reported-by: Benjamin Herrenschmidt Cc: Michael Chan Reported-by: Anisse Astier Suggested-by: David S. Miller Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/Kconfig | 1 + drivers/net/ethernet/broadcom/tg3.c | 9 --------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index f15e72e81ac4db..4bd416b72e65a9 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -101,6 +101,7 @@ config TIGON3 tristate "Broadcom Tigon3 support" depends on PCI select PHYLIB + select HWMON ---help--- This driver supports Broadcom Tigon3 based gigabit Ethernet cards. diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index bf906c51d82a40..711eb145aa5ca5 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -44,10 +44,8 @@ #include #include #include -#if IS_ENABLED(CONFIG_HWMON) #include #include -#endif #include #include @@ -9517,7 +9515,6 @@ static int tg3_init_hw(struct tg3 *tp, int reset_phy) return tg3_reset_hw(tp, reset_phy); } -#if IS_ENABLED(CONFIG_HWMON) static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir) { int i; @@ -9570,22 +9567,17 @@ static const struct attribute_group tg3_group = { .attrs = tg3_attributes, }; -#endif - static void tg3_hwmon_close(struct tg3 *tp) { -#if IS_ENABLED(CONFIG_HWMON) if (tp->hwmon_dev) { hwmon_device_unregister(tp->hwmon_dev); tp->hwmon_dev = NULL; sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group); } -#endif } static void tg3_hwmon_open(struct tg3 *tp) { -#if IS_ENABLED(CONFIG_HWMON) int i, err; u32 size = 0; struct pci_dev *pdev = tp->pdev; @@ -9617,7 +9609,6 @@ static void tg3_hwmon_open(struct tg3 *tp) dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n"); sysfs_remove_group(&pdev->dev.kobj, &tg3_group); } -#endif } From 630a09217dc7c20f7963a2ef785404e80ba98e0b Mon Sep 17 00:00:00 2001 From: Cyril Brulebois Date: Wed, 31 Oct 2012 14:00:46 +0000 Subject: [PATCH 0605/1071] r8169: Fix WoL on RTL8168d/8111d. commit b00e69dee4ccbb3a19989e3d4f1385bc2e3406cd upstream. This regression was spotted between Debian squeeze and Debian wheezy kernels (respectively based on 2.6.32 and 3.2). More info about Wake-on-LAN issues with Realtek's 816x chipsets can be found in the following thread: http://marc.info/?t=132079219400004 Probable regression from d4ed95d796e5126bba51466dc07e287cebc8bd19; more chipsets are likely affected. Tested on top of a 3.2.23 kernel. Reported-by: Florent Fourcot Tested-by: Florent Fourcot Hinted-by: Francois Romieu Signed-off-by: Cyril Brulebois Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 549314f5e0f468..b887856cc2c8e0 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3832,6 +3832,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_29: case RTL_GIGA_MAC_VER_30: case RTL_GIGA_MAC_VER_32: From 4d3440149ead396a3955f08608e535aed0befbc4 Mon Sep 17 00:00:00 2001 From: Nathan Walp Date: Thu, 1 Nov 2012 12:08:47 +0000 Subject: [PATCH 0606/1071] r8169: allow multicast packets on sub-8168f chipset. commit 0481776b7a70f09acf7d9d97c288c3a8403fbfe4 upstream. RTL_GIGA_MAC_VER_35 includes no multicast hardware filter. Signed-off-by: Nathan Walp Suggested-by: Hayes Wang Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index b887856cc2c8e0..df7bbbad71d004 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -4526,6 +4526,9 @@ static void rtl_set_rx_mode(struct net_device *dev) mc_filter[1] = swab32(data); } + if (tp->mac_version == RTL_GIGA_MAC_VER_35) + mc_filter[1] = mc_filter[0] = 0xffffffff; + RTL_W32(MAR0 + 4, mc_filter[1]); RTL_W32(MAR0 + 0, mc_filter[0]); From 9a406de3049374c0e480baca0ffafd9588c57959 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Thu, 25 Oct 2012 05:34:45 +0000 Subject: [PATCH 0607/1071] netfilter: nf_nat: don't check for port change on ICMP tuples commit 38fe36a248ec3228f8e6507955d7ceb0432d2000 upstream. ICMP tuples have id in src and type/code in dst. So comparing src.u.all with dst.u.all will always fail here and ip_xfrm_me_harder() is called for every ICMP packet, even if there was no NAT. Signed-off-by: Ulrich Weber Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/nf_nat_standalone.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 3828a422982295..da4098f087842b 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -194,7 +194,8 @@ nf_nat_out(unsigned int hooknum, if ((ct->tuplehash[dir].tuple.src.u3.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) || - (ct->tuplehash[dir].tuple.src.u.all != + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && + ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all) ) return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; @@ -230,7 +231,8 @@ nf_nat_local_fn(unsigned int hooknum, ret = NF_DROP; } #ifdef CONFIG_XFRM - else if (ct->tuplehash[dir].tuple.dst.u.all != + else if (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && + ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) if (ip_xfrm_me_harder(skb)) ret = NF_DROP; From 2b5ea01a9e4664d772ec9c8fc088ae48614564cd Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 16 Oct 2012 22:33:29 +0000 Subject: [PATCH 0608/1071] netfilter: xt_TEE: don't use destination address found in header commit 2ad5b9e4bd314fc685086b99e90e5de3bc59e26b upstream. Torsten Luettgert bisected TEE regression starting with commit f8126f1d5136be1 (ipv4: Adjust semantics of rt->rt_gateway.) The problem is that it tries to ARP-lookup the original destination address of the forwarded packet, not the address of the gateway. Fix this using FLOWI_FLAG_KNOWN_NH Julian added in commit c92b96553a80c1 (ipv4: Add FLOWI_FLAG_KNOWN_NH), so that known nexthop (info->gw.ip) has preference on resolving. Reported-by: Torsten Luettgert Bisected-by: Torsten Luettgert Tested-by: Torsten Luettgert Cc: Julian Anastasov Signed-off-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/xt_TEE.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index ee2e5bc5a8c7b5..bd93e51d30acc4 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c @@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) fl4.daddr = info->gw.ip; fl4.flowi4_tos = RT_TOS(iph->tos); fl4.flowi4_scope = RT_SCOPE_UNIVERSE; + fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) return false; From d3230589b189623d8d79fd56826001a8076ac5a6 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Tue, 9 Oct 2012 13:00:47 +0000 Subject: [PATCH 0609/1071] netfilter: nf_conntrack: fix rt_gateway checks for H.323 helper commit bbb5823cf742a7e955f35c7d891e4e936944c33a upstream. After the change "Adjust semantics of rt->rt_gateway" (commit f8126f1d51) we should properly match the nexthop when destinations are directly connected because rt_gateway can be 0. The rt_gateway checks in H.323 helper try to avoid the creation of an unnecessary expectation in this call-forwarding case: http://people.netfilter.org/zhaojingmin/h323_conntrack_nat_helper/#_Toc133598073 However, the existing code fails to avoid that in many cases, see this thread: http://marc.info/?l=linux-netdev&m=135043175028620&w=2 It seems it is not trivial to know from the kernel if two hosts have to go through the firewall to communicate each other, which is the main point of the call-forwarding filter code to avoid creating unnecessary expectations. So this patch just gets things the way they were as before commit f8126f1d51. Signed-off-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_h323_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 4283b207e63be6..02f65bc89f3b17 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -733,7 +733,8 @@ static int callforward_do_filter(const union nf_inet_addr *src, flowi4_to_flowi(&fl1), false)) { if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, flowi4_to_flowi(&fl2), false)) { - if (rt1->rt_gateway == rt2->rt_gateway && + if (rt_nexthop(rt1, fl1.daddr) == + rt_nexthop(rt2, fl2.daddr) && rt1->dst.dev == rt2->dst.dev) ret = 1; dst_release(&rt2->dst); From 38efab61680204d6f7cedfbacdc211ab1cfe0806 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 7 Nov 2012 10:44:08 +0100 Subject: [PATCH 0610/1071] s390/signal: set correct address space control commit fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2f upstream. If user space is running in primary mode it can switch to secondary or access register mode, this is used e.g. in the clock_gettime code of the vdso. If a signal is delivered to the user space process while it has been running in access register mode the signal handler is executed in access register mode as well which will result in a crash most of the time. Set the address space control bits in the PSW to the default for the execution of the signal handler and make sure that the previous address space control is restored on signal return. Take care that user space can not switch to the kernel address space by modifying the registers in the signal frame. Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/include/asm/compat.h | 2 +- arch/s390/include/asm/ptrace.h | 4 ++-- arch/s390/kernel/compat_signal.c | 14 ++++++++++++-- arch/s390/kernel/signal.c | 14 ++++++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 234f1d859cea07..2e0a15b4359c35 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -20,7 +20,7 @@ #define PSW32_MASK_CC 0x00003000UL #define PSW32_MASK_PM 0x00000f00UL -#define PSW32_MASK_USER 0x00003F00UL +#define PSW32_MASK_USER 0x0000FF00UL #define PSW32_ADDR_AMODE 0x80000000UL #define PSW32_ADDR_INSN 0x7FFFFFFFUL diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index d5f08ea566ed9a..f512565cd73156 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -238,7 +238,7 @@ typedef struct #define PSW_MASK_EA 0x00000000UL #define PSW_MASK_BA 0x00000000UL -#define PSW_MASK_USER 0x00003F00UL +#define PSW_MASK_USER 0x0000FF00UL #define PSW_ADDR_AMODE 0x80000000UL #define PSW_ADDR_INSN 0x7FFFFFFFUL @@ -267,7 +267,7 @@ typedef struct #define PSW_MASK_EA 0x0000000100000000UL #define PSW_MASK_BA 0x0000000080000000UL -#define PSW_MASK_USER 0x00003F0180000000UL +#define PSW_MASK_USER 0x0000FF0180000000UL #define PSW_ADDR_AMODE 0x0000000000000000UL #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index a1e8a8694bb705..593fcc9253fc43 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) regs32.gprs[i]; @@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__force __u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); @@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index c13a2a37ef007b..d1259d87507417 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (user_sregs.regs.psw.mask & PSW_MASK_USER); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); /* Check for invalid amode */ if (regs->psw.mask & PSW_MASK_EA) regs->psw.mask |= PSW_MASK_BA; @@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); @@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); From cc0e742a68460884c8e3bc982a15801b4f2bde54 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 25 Sep 2012 12:42:50 +0200 Subject: [PATCH 0611/1071] NFC: Use dynamic initialization for rwlocks commit fe235b58d517d623bf6d40c77afca1b0ee6fc85d upstream. If rwlock is dynamically allocated but statically initialized it is missing proper lockdep annotation. INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. Pid: 3352, comm: neard Not tainted 3.5.0-999-nfc+ #2 Call Trace: [] __lock_acquire+0x8f6/0x1bf0 [] ? printk+0x4d/0x4f [] lock_acquire+0x9d/0x220 [] ? nfc_llcp_sock_from_sn+0x4e/0x160 [] _raw_read_lock+0x44/0x60 [] ? nfc_llcp_sock_from_sn+0x4e/0x160 [] nfc_llcp_sock_from_sn+0x4e/0x160 [] nfc_llcp_get_sdp_ssap+0xa7/0x1b0 [] llcp_sock_bind+0x173/0x210 [] sys_bind+0xe4/0x100 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Signed-off-by: Szymon Janc Signed-off-by: Samuel Ortiz Cc: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- net/nfc/llcp/llcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 82f0f7588b463d..7dd983a4168843 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -1182,8 +1182,8 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) goto err_rx_wq; } - local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); - local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); + rwlock_init(&local->sockets.lock); + rwlock_init(&local->connecting_sockets.lock); nfc_llcp_build_gb(local); From 5e6883c0a2d2c59a296864a8db361fca635ffbb2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 14:55:52 +0100 Subject: [PATCH 0612/1071] reiserfs: Fix lock ordering during remount commit 3bb3e1fc47aca554e7e2cc4deeddc24750987ac2 upstream. When remounting reiserfs dquot_suspend() or dquot_resume() can be called. These functions take dqonoff_mutex which ranks above write lock so we have to drop it before calling into quota code. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/super.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 7a37dabf5a968b..fb74d9b606acf2 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1330,7 +1330,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) kfree(qf_names[i]); #endif err = -EINVAL; - goto out_err; + goto out_unlock; } #ifdef CONFIG_QUOTA handle_quota_files(s, qf_names, &qfmt); @@ -1374,7 +1374,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (blocks) { err = reiserfs_resize(s, blocks); if (err != 0) - goto out_err; + goto out_unlock; } if (*mount_flags & MS_RDONLY) { @@ -1384,9 +1384,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) /* it is read-only already */ goto out_ok; + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_suspend() without it. + */ + reiserfs_write_unlock(s); err = dquot_suspend(s, -1); if (err < 0) goto out_err; + reiserfs_write_lock(s); /* try to remount file system with read-only permissions */ if (sb_umount_state(rs) == REISERFS_VALID_FS @@ -1396,7 +1402,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mounting a rw partition read-only. */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1411,7 +1417,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (reiserfs_is_journal_aborted(journal)) { err = journal->j_errno; - goto out_err; + goto out_unlock; } handle_data_mode(s, mount_options); @@ -1420,7 +1426,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mount a partition which is read-only, read-write */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1437,10 +1443,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) SB_JOURNAL(s)->j_must_wait = 1; err = journal_end(&th, s, 10); if (err) - goto out_err; + goto out_unlock; if (!(*mount_flags & MS_RDONLY)) { + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_resume() without it. + */ + reiserfs_write_unlock(s); dquot_resume(s, -1); + reiserfs_write_lock(s); finish_unfinished(s); reiserfs_xattr_init(s, *mount_flags); } @@ -1450,9 +1462,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) reiserfs_write_unlock(s); return 0; +out_unlock: + reiserfs_write_unlock(s); out_err: kfree(new_opts); - reiserfs_write_unlock(s); return err; } From eca9da850bab6a60f07d3069ef69254dc79e10dd Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 16:34:17 +0100 Subject: [PATCH 0613/1071] reiserfs: Protect reiserfs_quota_on() with write lock commit b9e06ef2e8706fe669b51f4364e3aeed58639eb2 upstream. In reiserfs_quota_on() we do quite some work - for example unpacking tail of a quota file. Thus we have to hold write lock until a moment we call back into the quota code. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/super.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index fb74d9b606acf2..db3b6940bc45e3 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2211,8 +2211,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, struct reiserfs_transaction_handle th; int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; - if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) - return -EINVAL; + reiserfs_write_lock(sb); + if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { + err = -EINVAL; + goto out; + } /* Quotafile not on the same filesystem? */ if (path->dentry->d_sb != sb) { @@ -2254,8 +2257,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, if (err) goto out; } - err = dquot_quota_on(sb, type, format_id, path); + reiserfs_write_unlock(sb); + return dquot_quota_on(sb, type, format_id, path); out: + reiserfs_write_unlock(sb); return err; } From 94bdc251fe3e4c14edc5d71d7197ec6e4046f715 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 17:05:14 +0100 Subject: [PATCH 0614/1071] reiserfs: Move quota calls out of write lock commit 7af11686933726e99af22901d622f9e161404e6b upstream. Calls into highlevel quota code cannot happen under the write lock. These calls take dqio_mutex which ranks above write lock. So drop write lock before calling back into quota code. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/inode.c | 10 +++++++--- fs/reiserfs/stree.c | 4 ++++ fs/reiserfs/super.c | 18 ++++++++++++++---- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 63ce6be94c4ad7..567c10cf63cd84 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, BUG_ON(!th->t_trans_id); - dquot_initialize(inode); + reiserfs_write_unlock(inode->i_sb); err = dquot_alloc_inode(inode); + reiserfs_write_lock(inode->i_sb); if (err) goto out_end_trans; if (!dir->i_nlink) { @@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_end_trans: journal_end(th, th->t_super, th->t_blocks_allocated); + reiserfs_write_unlock(inode->i_sb); /* Drop can be outside and it needs more credits so it's better to have it outside */ dquot_drop(inode); + reiserfs_write_lock(inode->i_sb); inode->i_flags |= S_NOQUOTA; make_bad_inode(inode); @@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) /* must be turned off for recursive notify_change calls */ ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); - depth = reiserfs_write_lock_once(inode->i_sb); if (is_quota_modification(inode, attr)) dquot_initialize(inode); - + depth = reiserfs_write_lock_once(inode->i_sb); if (attr->ia_valid & ATTR_SIZE) { /* version 2 items will be caught by the s_maxbytes check ** done for us in vmtruncate @@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) error = journal_begin(&th, inode->i_sb, jbegin_count); if (error) goto out; + reiserfs_write_unlock_once(inode->i_sb, depth); error = dquot_transfer(inode, attr); + depth = reiserfs_write_lock_once(inode->i_sb); if (error) { journal_end(&th, inode->i_sb, jbegin_count); goto out; diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index f8afa4b162b8f0..2f40a4c70a4d96 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree key2type(&(key->on_disk_key))); #endif + reiserfs_write_unlock(inode->i_sb); retval = dquot_alloc_space_nodirty(inode, pasted_size); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(search_path); return retval; @@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, "reiserquota insert_item(): allocating %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(ih)); #endif + reiserfs_write_unlock(inode->i_sb); /* We can't dirty inode here. It would be immediately written but * appropriate stat item isn't inserted yet... */ retval = dquot_alloc_space_nodirty(inode, quota_bytes); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(path); return retval; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index db3b6940bc45e3..4f3d1c79c84ed9 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s) retval = remove_save_link_only(s, &save_link_key, 0); continue; } + reiserfs_write_unlock(s); dquot_initialize(inode); + reiserfs_write_lock(s); if (truncate && S_ISDIR(inode->i_mode)) { /* We got a truncate request for a dir which is impossible. @@ -2103,13 +2105,15 @@ static int reiserfs_write_dquot(struct dquot *dquot) REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_commit(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2125,13 +2129,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_acquire(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2145,19 +2151,21 @@ static int reiserfs_release_dquot(struct dquot *dquot) ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); + reiserfs_write_unlock(dquot->dq_sb); if (ret) { /* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release(dquot); goto out; } ret = dquot_release(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: reiserfs_write_unlock(dquot->dq_sb); +out: return ret; } @@ -2182,11 +2190,13 @@ static int reiserfs_write_info(struct super_block *sb, int type) ret = journal_begin(&th, sb, 2); if (ret) goto out; + reiserfs_write_unlock(sb); ret = dquot_commit_info(sb, type); + reiserfs_write_lock(sb); err = journal_end(&th, sb, 2); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(sb); return ret; } From 2811150bc6fc7a64393531dc4cb3d2a9c586e977 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 18:25:38 +0100 Subject: [PATCH 0615/1071] reiserfs: Protect reiserfs_quota_write() with write lock commit 361d94a338a3fd0cee6a4ea32bbc427ba228e628 upstream. Calls into reiserfs journalling code and reiserfs_get_block() need to be protected with write lock. We remove write lock around calls to high level quota code in the next patch so these paths would suddently become unprotected. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 4f3d1c79c84ed9..4300030788d159 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2343,7 +2343,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; tmp_bh.b_state = 0; + reiserfs_write_lock(sb); err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); + reiserfs_write_unlock(sb); if (err) goto out; if (offset || tocopy != sb->s_blocksize) @@ -2359,10 +2361,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, flush_dcache_page(bh->b_page); set_buffer_uptodate(bh); unlock_buffer(bh); + reiserfs_write_lock(sb); reiserfs_prepare_for_journal(sb, bh, 1); journal_mark_dirty(current->journal_info, sb, bh); if (!journal_quota) reiserfs_add_ordered_list(inode, bh); + reiserfs_write_unlock(sb); brelse(bh); offset = 0; towrite -= tocopy; From 2bd5aecc3d0b659e6dbbc96483737601a69db880 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 13 Nov 2012 10:22:03 -0700 Subject: [PATCH 0616/1071] intel-iommu: Fix lookup in add device commit 3da4af0affbb797e8ac4c2b4598da0c34b8cc52a upstream. We can't assume this device exists, fall back to the bridge itself. Signed-off-by: Alex Williamson Tested-by: Matthew Thode Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index cb9e1146b02fe3..554e6ac8af4256 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) static int intel_iommu_add_device(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct pci_dev *bridge, *dma_pdev; + struct pci_dev *bridge, *dma_pdev = NULL; struct iommu_group *group; int ret; @@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev) dma_pdev = pci_get_domain_bus_and_slot( pci_domain_nr(pdev->bus), bridge->subordinate->number, 0); - else + if (!dma_pdev) dma_pdev = pci_dev_get(bridge); } else dma_pdev = pci_dev_get(pdev); From dd29ec65092dddc6c9ed533d8a1dca63d4ecb63e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 8 Nov 2012 16:09:27 -0800 Subject: [PATCH 0617/1071] selinux: fix sel_netnode_insert() suspicious rcu dereference commit 88a693b5c1287be4da937699cb82068ce9db0135 upstream. =============================== [ INFO: suspicious RCU usage. ] 3.5.0-rc1+ #63 Not tainted ------------------------------- security/selinux/netnode.c:178 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 1 lock held by trinity-child1/8750: #0: (sel_netnode_lock){+.....}, at: [] sel_netnode_sid+0x16a/0x3e0 stack backtrace: Pid: 8750, comm: trinity-child1 Not tainted 3.5.0-rc1+ #63 Call Trace: [] lockdep_rcu_suspicious+0xfd/0x130 [] sel_netnode_sid+0x3b1/0x3e0 [] ? sel_netnode_find+0x1a0/0x1a0 [] selinux_socket_bind+0xf6/0x2c0 [] ? trace_hardirqs_off+0xd/0x10 [] ? lock_release_holdtime.part.9+0x15/0x1a0 [] ? lock_hrtimer_base+0x31/0x60 [] security_socket_bind+0x16/0x20 [] sys_bind+0x7a/0x100 [] ? sysret_check+0x22/0x5d [] ? trace_hardirqs_on_caller+0x10d/0x1a0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b This patch below does what Paul McKenney suggested in the previous thread. Signed-off-by: Dave Jones Reviewed-by: Paul E. McKenney Acked-by: Paul Moore Cc: Eric Paris Signed-off-by: Andrew Morton Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- security/selinux/netnode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 28f911cdd7c79d..c5454c0477c346 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { struct sel_netnode *tail; tail = list_entry( - rcu_dereference(sel_netnode_hash[idx].list.prev), + rcu_dereference_protected(sel_netnode_hash[idx].list.prev, + lockdep_is_held(&sel_netnode_lock)), struct sel_netnode, list); list_del_rcu(&tail->list); kfree_rcu(tail, rcu); From 4d60ac3f136e26522dbdbff28624f59165a27cd9 Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Sat, 13 Oct 2012 04:41:25 +0400 Subject: [PATCH 0618/1071] ACPI video: Ignore errors after _DOD evaluation. commit fba4e087361605d1eed63343bb08811f097c83ee upstream. There are systems where video module known to work fine regardless of broken _DOD and ignoring returned value here doesn't cause any issues later. This should fix brightness controls on some laptops. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861 Signed-off-by: Igor Murzov Reviewed-by: Sergey V Signed-off-by: Zhang Rui Signed-off-by: Abdallah Chatila --- drivers/acpi/video.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 1e0a9e17c31d80..9fe26597e2a6c3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1345,12 +1345,15 @@ static int acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { - int status; + int status = 0; struct acpi_device *dev; - status = acpi_video_device_enumerate(video); - if (status) - return status; + /* + * There are systems where video module known to work fine regardless + * of broken _DOD and ignoring returned value here doesn't cause + * any issues later. + */ + acpi_video_device_enumerate(video); list_for_each_entry(dev, &device->children, node) { From 03faff7a2288f69b0a2218f1cd0e0d81e31e6509 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 16 Oct 2012 17:09:22 +0300 Subject: [PATCH 0619/1071] Revert "serial: omap: fix software flow control" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a4f743851f74fc3e0cc40c13082e65c24139f481 upstream. This reverts commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6 (serial: omap: fix software flow control). As Russell has pointed out, that commit isn't fixing Software Flow Control at all, and it actually makes it even more broken. It was agreed to revert this commit and use Russell's latest UART patches instead. Signed-off-by: Felipe Balbi Cc: Russell King Acked-by: Tony Lindgren Cc: Andreas Bießmann Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/include/plat/omap-serial.h | 4 ++-- drivers/tty/serial/omap-serial.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 3a5764494d474d..1a52725ffcf25c 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -42,10 +42,10 @@ #define OMAP_UART_WER_MOD_WKUP 0X7F /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x8 +#define OMAP_UART_SW_TX 0x04 /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x2 +#define OMAP_UART_SW_RX 0x04 #define OMAP_UART_SYSC_RESET 0X07 #define OMAP_UART_TCR_TRIG 0X0F diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 22992cda572b9b..d3cda0cb2df0a9 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -667,19 +667,19 @@ serial_omap_configure_xonxoff /* * IXON Flag: - * Flow control for OMAP.TX - * OMAP.RX should listen for XON/XOFF + * Enable XON/XOFF flow control on output. + * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXON) - up->efr |= OMAP_UART_SW_RX; + up->efr |= OMAP_UART_SW_TX; /* * IXOFF Flag: - * Flow control for OMAP.RX - * OMAP.TX should send XON/XOFF + * Enable XON/XOFF flow control on input. + * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXOFF) - up->efr |= OMAP_UART_SW_TX; + up->efr |= OMAP_UART_SW_RX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); From 19dfc178ae0ed43e3cc8407f7876497a3ee5ba95 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 10 Oct 2012 01:06:58 -0400 Subject: [PATCH 0620/1071] ext4: fix metadata checksum calculation for the superblock commit 06db49e68ae70cf16819b85a14057acb2820776a upstream. The function ext4_handle_dirty_super() was calculating the superblock on the wrong block data. As a result, when the superblock is modified while it is mounted (most commonly, when inodes are added or removed from the orphan list), the superblock checksum would be wrong. We didn't notice because the superblock *was* being correctly calculated in ext4_commit_super(), and this would get called when the file system was unmounted. So the problem only became obvious if the system crashed while the file system was mounted. Fix this by removing the poorly designed function signature for ext4_superblock_csum_set(); if it only took a single argument, the pointer to a struct superblock, the ambiguity which caused this mistake would have been impossible. Reported-by: George Spelvin Signed-off-by: "Theodore Ts'o" Tested-by: George Spelvin --- fs/ext4/ext4.h | 3 +-- fs/ext4/ext4_jbd2.c | 8 ++------ fs/ext4/resize.c | 2 +- fs/ext4/super.c | 7 ++++--- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 5c69f2b32b1cb1..b686b43164aed2 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2046,8 +2046,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); extern int ext4_calculate_overhead(struct super_block *sb); extern int ext4_superblock_csum_verify(struct super_block *sb, struct ext4_super_block *es); -extern void ext4_superblock_csum_set(struct super_block *sb, - struct ext4_super_block *es); +extern void ext4_superblock_csum_set(struct super_block *sb); extern void *ext4_kvmalloc(size_t size, gfp_t flags); extern void *ext4_kvzalloc(size_t size, gfp_t flags); extern void ext4_kvfree(void *ptr); diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index bfa65b49d4243d..b4323ba846b52a 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line, struct buffer_head *bh = EXT4_SB(sb)->s_sbh; int err = 0; + ext4_superblock_csum_set(sb); if (ext4_handle_valid(handle)) { - ext4_superblock_csum_set(sb, - (struct ext4_super_block *)bh->b_data); err = jbd2_journal_dirty_metadata(handle, bh); if (err) ext4_journal_abort_handle(where, line, __func__, bh, handle, err); - } else { - ext4_superblock_csum_set(sb, - (struct ext4_super_block *)bh->b_data); + } else mark_buffer_dirty(bh); - } return err; } diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 71241bc0eea614..101b41c6844c9f 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -979,7 +979,7 @@ static void update_backups(struct super_block *sb, goto exit_err; } - ext4_superblock_csum_set(sb, (struct ext4_super_block *)data); + ext4_superblock_csum_set(sb); while ((group = ext4_list_backups(sb, &three, &five, &seven)) < last) { struct buffer_head *bh; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index e44b23362088d9..2b5fb603b2b6a1 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb, return es->s_checksum == ext4_superblock_csum(sb, es); } -void ext4_superblock_csum_set(struct super_block *sb, - struct ext4_super_block *es) +void ext4_superblock_csum_set(struct super_block *sb) { + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) return; @@ -4343,7 +4344,7 @@ static int ext4_commit_super(struct super_block *sb, int sync) cpu_to_le32(percpu_counter_sum_positive( &EXT4_SB(sb)->s_freeinodes_counter)); BUFFER_TRACE(sbh, "marking dirty"); - ext4_superblock_csum_set(sb, es); + ext4_superblock_csum_set(sb); mark_buffer_dirty(sbh); if (sync) { error = sync_dirty_buffer(sbh); From 597d50c7a836f80d57d2f6993d4e30d5e1ba7bdb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 26 Nov 2012 12:15:45 -0800 Subject: [PATCH 0621/1071] Linux 3.6.8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 07f23080b86d0a..c5cc2f05256772 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 7 +SUBLEVEL = 8 EXTRAVERSION = NAME = Terrified Chipmunk From 4b2b47ed90264cb775c428039a14ad6fabd4006d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 16 Nov 2012 20:46:19 +0100 Subject: [PATCH 0622/1071] wireless: add back sysfs directory commit 38c1a01cf10c6e4049b4ffbd4a6af655df2a46e1 upstream. commit 35b2a113cb0298d4f9a1263338b456094a414057 broke (at least) Fedora's networking scripts, they check for the existence of the wireless directory. As the files aren't used, add the directory back and not the files. Also do it for both drivers based on the old wireless extensions and cfg80211, regardless of whether the compat code for wext is built into cfg80211 or not. Reported-by: Dave Airlie Reported-by: Bill Nottingham Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/core/net-sysfs.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 72607174ea5a4a..20bb371c909b2e 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -417,6 +417,17 @@ static struct attribute_group netstat_group = { .name = "statistics", .attrs = netstat_attrs, }; + +#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) +static struct attribute *wireless_attrs[] = { + NULL +}; + +static struct attribute_group wireless_group = { + .name = "wireless", + .attrs = wireless_attrs, +}; +#endif #endif /* CONFIG_SYSFS */ #ifdef CONFIG_RPS @@ -1397,6 +1408,15 @@ int netdev_register_kobject(struct net_device *net) groups++; *groups++ = &netstat_group; + +#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) + if (net->ieee80211_ptr) + *groups++ = &wireless_group; +#if IS_ENABLED(CONFIG_WIRELESS_EXT) + else if (net->wireless_handlers) + *groups++ = &wireless_group; +#endif +#endif #endif /* CONFIG_SYSFS */ error = device_add(dev); From e7a733a0c023a9f32c6bf3d34c2f954085ebc322 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 Sep 2012 20:54:48 +0200 Subject: [PATCH 0623/1071] x86-32: Fix invalid stack address while in softirq commit 1022623842cb72ee4d0dbf02f6937f38c92c3f41 upstream. In 32 bit the stack address provided by kernel_stack_pointer() may point to an invalid range causing NULL pointer access or page faults while in NMI (see trace below). This happens if called in softirq context and if the stack is empty. The address at ®s->sp is then out of range. Fixing this by checking if regs and ®s->sp are in the same stack context. Otherwise return the previous stack pointer stored in struct thread_info. If that address is invalid too, return address of regs. BUG: unable to handle kernel NULL pointer dereference at 0000000a IP: [] print_context_stack+0x6e/0x8d *pde = 00000000 Oops: 0000 [#1] SMP Modules linked in: Pid: 4434, comm: perl Not tainted 3.6.0-rc3-oprofile-i386-standard-g4411a05 #4 Hewlett-Packard HP xw9400 Workstation/0A1Ch EIP: 0060:[] EFLAGS: 00010093 CPU: 0 EIP is at print_context_stack+0x6e/0x8d EAX: ffffe000 EBX: 0000000a ECX: f4435f94 EDX: 0000000a ESI: f4435f94 EDI: f4435f94 EBP: f5409ec0 ESP: f5409ea0 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 CR0: 8005003b CR2: 0000000a CR3: 34ac9000 CR4: 000007d0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Process perl (pid: 4434, ti=f5408000 task=f5637850 task.ti=f4434000) Stack: 000003e8 ffffe000 00001ffc f4e39b00 00000000 0000000a f4435f94 c155198c f5409ef0 c1003723 c155198c f5409f04 00000000 f5409edc 00000000 00000000 f5409ee8 f4435f94 f5409fc4 00000001 f5409f1c c12dce1c 00000000 c155198c Call Trace: [] dump_trace+0x7b/0xa1 [] x86_backtrace+0x40/0x88 [] ? oprofile_add_sample+0x56/0x84 [] oprofile_add_sample+0x75/0x84 [] op_amd_check_ctrs+0x46/0x260 [] profile_exceptions_notify+0x23/0x4c [] nmi_handle+0x31/0x4a [] ? ftrace_define_fields_irq_handler_entry+0x45/0x45 [] do_nmi+0xa0/0x2ff [] ? ftrace_define_fields_irq_handler_entry+0x45/0x45 [] nmi_stack_correct+0x28/0x2d [] ? ftrace_define_fields_irq_handler_entry+0x45/0x45 [] ? do_softirq+0x4b/0x7f [] irq_exit+0x35/0x5b [] smp_apic_timer_interrupt+0x6c/0x7a [] apic_timer_interrupt+0x2a/0x30 Code: 89 fe eb 08 31 c9 8b 45 0c ff 55 ec 83 c3 04 83 7d 10 00 74 0c 3b 5d 10 73 26 3b 5d e4 73 0c eb 1f 3b 5d f0 76 1a 3b 5d e8 73 15 <8b> 13 89 d0 89 55 e0 e8 ad 42 03 00 85 c0 8b 55 e0 75 a6 eb cc EIP: [] print_context_stack+0x6e/0x8d SS:ESP 0068:f5409ea0 CR2: 000000000000000a ---[ end trace 62afee3481b00012 ]--- Kernel panic - not syncing: Fatal exception in interrupt V2: * add comments to kernel_stack_pointer() * always return a valid stack address by falling back to the address of regs Reported-by: Yang Wei Signed-off-by: Robert Richter Link: http://lkml.kernel.org/r/20120912135059.GZ8285@erda.amd.com Signed-off-by: H. Peter Anvin Cc: Jun Zhang Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/ptrace.h | 15 ++++----------- arch/x86/kernel/ptrace.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index dcfde52979c3e6..19f16ebaf4fa82 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs) } #endif -/* - * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode - * when it traps. The previous stack will be directly underneath the saved - * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. - * - * This is valid only for kernel mode traps. - */ -static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) -{ #ifdef CONFIG_X86_32 - return (unsigned long)(®s->sp); +extern unsigned long kernel_stack_pointer(struct pt_regs *regs); #else +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ return regs->sp; -#endif } +#endif #define GET_IP(regs) ((regs)->ip) #define GET_FP(regs) ((regs)->bp) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index c4c6a5c2bf0f39..947cf90e10cd28 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -165,6 +165,34 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 +/* + * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode + * when it traps. The previous stack will be directly underneath the saved + * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. + * + * Now, if the stack is empty, '®s->sp' is out of range. In this + * case we try to take the previous stack. To always return a non-null + * stack pointer we fall back to regs as stack if no previous stack + * exists. + * + * This is valid only for kernel mode traps. + */ +unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1); + unsigned long sp = (unsigned long)®s->sp; + struct thread_info *tinfo; + + if (context == (sp & ~(THREAD_SIZE - 1))) + return sp; + + tinfo = (struct thread_info *)context; + if (tinfo->previous_esp) + return tinfo->previous_esp; + + return (unsigned long)regs; +} + static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); From 5e0edcfdac8ef57ef873f75de0780860745942ed Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 20 Nov 2012 13:07:46 +0000 Subject: [PATCH 0624/1071] x86, efi: Fix processor-specific memcpy() build error commit 0f905a43ce955b638139bd84486194770a6a2c08 upstream. Building for Athlon/Duron/K7 results in the following build error, arch/x86/boot/compressed/eboot.o: In function `__constant_memcpy3d': eboot.c:(.text+0x385): undefined reference to `_mmx_memcpy' arch/x86/boot/compressed/eboot.o: In function `efi_main': eboot.c:(.text+0x1a22): undefined reference to `_mmx_memcpy' because the boot stub code doesn't link with the kernel proper, and therefore doesn't have access to the 3DNow version of memcpy. So, follow the example of misc.c and #undef memcpy so that we use the version provided by misc.c. See https://bugzilla.kernel.org/show_bug.cgi?id=50391 Reported-by: Al Viro Reported-by: Ryan Underwood Cc: H. Peter Anvin Signed-off-by: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- arch/x86/boot/compressed/eboot.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b3e0227df2c9ae..90201aace72a8e 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -12,6 +12,8 @@ #include #include +#undef memcpy /* Use memcpy from misc.c */ + #include "eboot.h" static efi_system_table_t *sys_table; From 1ea87b1fa98cfa76a2aad6f182367b0ba2296015 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Thu, 15 Nov 2012 13:41:50 -0500 Subject: [PATCH 0625/1071] x86, microcode, AMD: Add support for family 16h processors commit 36c46ca4f322a7bf89aad5462a3a1f61713edce7 upstream. Add valid patch size for family 16h processors. [ hpa: promoting to urgent/stable since it is hw enabling and trivial ] Signed-off-by: Boris Ostrovsky Acked-by: Andreas Herrmann Link: http://lkml.kernel.org/r/1353004910-2204-1-git-send-email-boris.ostrovsky@amd.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/microcode_amd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 82746f942cd8db..5d8cf0d6796cc1 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -97,6 +97,7 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size, #define F1XH_MPB_MAX_SIZE 2048 #define F14H_MPB_MAX_SIZE 1824 #define F15H_MPB_MAX_SIZE 4096 +#define F16H_MPB_MAX_SIZE 3458 switch (c->x86) { case 0x14: @@ -105,6 +106,9 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size, case 0x15: max_size = F15H_MPB_MAX_SIZE; break; + case 0x16: + max_size = F16H_MPB_MAX_SIZE; + break; default: max_size = F1XH_MPB_MAX_SIZE; break; From 051d62f6f239a9427fcab244a310610ed8bedb43 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 20 Nov 2012 22:21:02 -0800 Subject: [PATCH 0626/1071] x86-32: Export kernel_stack_pointer() for modules commit cb57a2b4cff7edf2a4e32c0163200e9434807e0a upstream. Modules, in particular oprofile (and possibly other similar tools) need kernel_stack_pointer(), so export it using EXPORT_SYMBOL_GPL(). Link: http://lkml.kernel.org/r/20120912135059.GZ8285@erda.amd.com Cc: Yang Wei Cc: Robert Richter Cc: Jun Zhang Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/ptrace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 947cf90e10cd28..9ee1787130594c 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -192,6 +193,7 @@ unsigned long kernel_stack_pointer(struct pt_regs *regs) return (unsigned long)regs; } +EXPORT_SYMBOL_GPL(kernel_stack_pointer); static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { From 03fd10ac54c87c1436643513f76822e8e69bf0e9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 15 Oct 2012 17:57:36 +0200 Subject: [PATCH 0627/1071] iwlwifi: don't WARN when a non empty queue is disabled commit e1b69fdf33f63cfa600b992172d7376f9d9ef2e9 upstream. This can happen when we shut down suddenly an interface. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/pcie/tx.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 6baf8deef5190a..b9d6152adc5478 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 rd_ptr, wr_ptr; - int n_bd = trans_pcie->txq[txq_id].q.n_bd; if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { WARN_ONCE(1, "queue %d not used", txq_id); return; } - rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); - wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); - - WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", - txq_id, rd_ptr, wr_ptr); - iwl_txq_set_inactive(trans, txq_id); IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); } From e052d101c6c8331fa0c5abcc0dec91e46a515e7e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Nov 2012 21:28:44 +0100 Subject: [PATCH 0628/1071] iwlwifi: fix monitor mode FCS flag commit 04baaa27b43d389879237b32f8bd194a94cf1ca7 upstream. When the firmware is in SNIFFER mode, it leaves the FCS at the end of frame. Not telling mac80211 means it won't add the right flag to the radiotap header and that confuses wireshark. Since mac80211 doesn't have a per-packet flag, set the HW flag dynamically. This works as the monitor vif can only be present in the driver by itself. This fixes a regression introduced by my commit 578977264199de9815ace51ade87cec4894cf010 Author: Johannes Berg Date: Fri May 11 10:53:18 2012 +0200 iwlwifi: support explicit monitor interface Reported-by: MARK PHILLIPS Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index a5f7bce9632581..7a2cf5295e989b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -1352,6 +1352,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, vif_priv->ctx = ctx; ctx->vif = vif; + /* + * In SNIFFER device type, the firmware reports the FCS to + * the host, rather than snipping it off. Unfortunately, + * mac80211 doesn't (yet) provide a per-packet flag for + * this, so that we have to set the hardware flag based + * on the interfaces added. As the monitor interface can + * only be present by itself, and will be removed before + * other interfaces are added, this is safe. + */ + if (vif->type == NL80211_IFTYPE_MONITOR) + priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS; + else + priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; + err = iwl_setup_interface(priv, ctx); if (!err || reset) goto out; From baa6c1834000d95f2bbaae5bafd6430c4481af79 Mon Sep 17 00:00:00 2001 From: Albert Pool Date: Tue, 30 Oct 2012 20:58:06 +0100 Subject: [PATCH 0629/1071] rtlwifi: rtl8192cu: Add new USB ID commit a485e827f07bfdd0762059386e6e787bed6e81ee upstream. This is an ISY IWL 2000. Probably a clone of Belkin F7D1102 050d:1102. Its FCC ID is the same. Signed-off-by: Albert Pool Acked-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 9970c2b1b19979..b7e6607e6b6d03 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ From 5410faf6a70b35a851246e32b6b3adfec72a5ffa Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Thu, 15 Nov 2012 15:58:48 -0800 Subject: [PATCH 0630/1071] mwifiex: report error to MMC core if we cannot suspend commit dd321acddc3be1371263b8c9e6c6f2af89f63d57 upstream. When host_sleep_config command fails we should return error to MMC core to indicate the failure for our device. The misspelled variable is also removed as it's redundant. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/sdio.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index fc8a9bfa124830..82cf0fa2d9f683 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; int i; int ret = 0; @@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (!mwifiex_enable_hs(adapter)) { + dev_err(adapter->dev, "cmd: failed to suspend\n"); + return -EFAULT; } + dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + /* Indicate device suspended */ adapter->is_suspended = true; From d467bca7112c08e3981ec568fad9e7d091e3328b Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Thu, 15 Nov 2012 15:58:47 -0800 Subject: [PATCH 0631/1071] mwifiex: fix system hang issue in cmd timeout error case commit b1a47aa5e1e159e2cb06d7dfcc17ef5149b09299 upstream. Reported by Tim Shepard: I was seeing sporadic failures (wedgeups), and the majority of those failures I saw printed the printouts in mwifiex_cmd_timeout_func with cmd = 0xe5 which is CMD_802_11_HS_CFG_ENH. When this happens, two minutes later I get notified that the rtcwake thread is blocked, like this: INFO: task rtcwake:3495 blocked for more than 120 seconds. To get the hung thread unblocked we wake up the cmd wait queue and cancel the ioctl. Reported-by: Tim Shepard Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/cmdevt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 565527aee0ea3f..95382f1ebce02b 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -887,9 +887,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -ETIMEDOUT; - if (cmd_node) { adapter->dbg.timeout_cmd_id = adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; @@ -935,6 +932,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context) dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", adapter->ps_mode, adapter->ps_state); + + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -ETIMEDOUT; + wake_up_interruptible(&adapter->cmd_wait_q.wait); + mwifiex_cancel_pending_ioctl(adapter); + /* reset cmd_sent flag to unblock new commands */ + adapter->cmd_sent = false; + } } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); From 2abb93f3a7de2f2ede17a2c891d665f43fbb478c Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Mon, 15 Oct 2012 14:29:03 +0200 Subject: [PATCH 0632/1071] SCSI: isci: copy fis 0x34 response into proper buffer commit 49bd665c5407a453736d3232ee58f2906b42e83c upstream. SATA MICROCODE DOWNALOAD fails on isci driver. After receiving Register Device to Host (FIS 0x34) frame Initiator resets phy. In the frame handler routine response (FIS 0x34) was copied into wrong buffer and upper layer did not receive any answer which resulted in timeout and reset. This patch corrects this bug. Signed-off-by: Maciej Patelczyk Signed-off-by: Lukasz Dorau Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/isci/request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 7a0431c734932a..94483c9b91f607 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, (void **)&frame_buffer); - sci_controller_copy_sata_response(&ireq->stp.req, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); From bba14defc28e372727bf98d63d2bee9efbd4bda2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 21 Nov 2012 18:37:38 -0500 Subject: [PATCH 0633/1071] drm/radeon: add new SI pci id commit 0181bd5dea2ed0696f84591a92da0b6a1f1a2e62 upstream. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index af1cbaf535edeb..c5c35e629426b5 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -210,6 +210,7 @@ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ From 0ef24e01e9a96a936f893e6abfa5ff89a4af648a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 31 Oct 2012 16:35:30 +0100 Subject: [PATCH 0634/1071] ALSA: ua101, usx2y: fix broken MIDI output commit e99ddfde6ae0dd2662bb40435696002b590e4057 upstream. Commit 88a8516a2128 (ALSA: usbaudio: implement USB autosuspend) added autosuspend code to all files making up the snd-usb-audio driver. However, midi.c is part of snd-usb-lib and is also used by other drivers, not all of which support autosuspend. Thus, calls to usb_autopm_get_interface() could fail, and this unexpected error would result in the MIDI output being completely unusable. Make it work by ignoring the error that is expected with drivers that do not support autosuspend. Reported-by: Colin Fletcher Reported-by: Devin Venable Reported-by: Dr Nick Bailey Reported-by: Jannis Achstetter Reported-by: Rui Nuno Capela Cc: Oliver Neukum Signed-off-by: Clemens Ladisch Signed-off-by: Greg Kroah-Hartman --- sound/usb/midi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c83f6143c0eb34..eeefbce3873c11 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint { struct snd_usb_midi_out_endpoint* ep; struct snd_rawmidi_substream *substream; int active; + bool autopm_reference; uint8_t cable; /* cable number << 4 */ uint8_t state; #define STATE_UNKNOWN 0 @@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) return -ENXIO; } err = usb_autopm_get_interface(umidi->iface); - if (err < 0) + port->autopm_reference = err >= 0; + if (err < 0 && err != -EACCES) return -EIO; substream->runtime->private_data = port; port->state = STATE_UNKNOWN; @@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) { struct snd_usb_midi* umidi = substream->rmidi->private_data; + struct usbmidi_out_port *port = substream->runtime->private_data; substream_open(substream, 0); - usb_autopm_put_interface(umidi->iface); + if (port->autopm_reference) + usb_autopm_put_interface(umidi->iface); return 0; } From 9826d22c720e430e632514c2efcdab33704661d2 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 21 Nov 2012 10:03:10 +0100 Subject: [PATCH 0635/1071] ALSA: hda - Cirrus: Correctly clear line_out_pins when moving to speaker commit 34c3d1926bdaf45d3a891dd577482abcdd9faa34 upstream. If this array is not cleared, the jack related code later might fail to create "Internal Speaker Phantom Jack" on Dell Inspiron 3420 and Dell Vostro 2420. BugLink: https://bugs.launchpad.net/bugs/1076840 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2bb9bee085191b..10fc7108025d3a 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -461,6 +461,7 @@ static int parse_output(struct hda_codec *codec) memcpy(cfg->speaker_pins, cfg->line_out_pins, sizeof(cfg->speaker_pins)); cfg->line_outs = 0; + memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins)); } return 0; From 6be49c441050e8a63407f32c14cb59dc5324f252 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 2 Nov 2012 12:30:53 +0000 Subject: [PATCH 0636/1071] PARISC: fix virtual aliasing issue in get_shared_area() commit 949a05d03490e39e773e8652ccab9157e6f595b4 upstream. On Thu, 2012-11-01 at 16:45 -0700, Michel Lespinasse wrote: > Looking at the arch/parisc/kernel/sys_parisc.c implementation of > get_shared_area(), I do have a concern though. The function basically > ignores the pgoff argument, so that if one creates a shared mapping of > pages 0-N of a file, and then a separate shared mapping of pages 1-N > of that same file, both will have the same cache offset for their > starting address. > > This looks like this would create obvious aliasing issues. Am I > misreading this ? I can't understand how this could work good enough > to be undetected, so there must be something I'm missing here ??? This turns out to be correct and we need to pay attention to the pgoff as well as the address when creating the virtual address for the area. Fortunately, the bug is rarely triggered as most applications which use pgoff tend to use large values (git being the primary one, and it uses pgoff in multiples of 16MB) which are larger than our cache coherency modulus, so the problem isn't often seen in practise. Reported-by: Michel Lespinasse Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/sys_parisc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 7426e40699bdbf..f76c10863c6266 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping, struct vm_area_struct *vma; int offset = mapping ? get_offset(mapping) : 0; + offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000; + addr = DCACHE_ALIGN(addr - offset) + offset; for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { From ad362b2ba5fc62b5bd7740b9aee9ef7c3f4b9466 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 21 Nov 2012 19:27:23 +0000 Subject: [PATCH 0637/1071] PARISC: fix user-triggerable panic on parisc commit 441a179dafc0f99fc8b3a8268eef66958621082e upstream. int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, unsigned int sigsetsize) { sigset_t old_set, new_set; int ret; if (set && get_sigset32(set, &new_set, sigsetsize)) ... static int get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) { compat_sigset_t s; int r; if (sz != sizeof *set) panic("put_sigset32()"); In other words, rt_sigprocmask(69, (void *)69, 69) done by 32bit process will promptly panic the box. Signed-off-by: Al Viro Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/signal32.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index fd49aeda9eb8b0..5dede04f2f3ead 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) { compat_sigset_t s; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; sigset_64to32(&s, set); return copy_to_user(up, &s, sizeof s); @@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) compat_sigset_t s; int r; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; if ((r = copy_from_user(&s, up, sz)) == 0) { sigset_32to64(set, &s); From 4a6195797eb31a910eb13b891612c24f9643df60 Mon Sep 17 00:00:00 2001 From: Jiri Engelthaler Date: Thu, 20 Sep 2012 16:49:50 +0200 Subject: [PATCH 0638/1071] mtd: slram: invalid checking of absolute end address commit c36a7ff4578ab6294885aef5ef241aeec4cdb1f0 upstream. Fixed parsing end absolute address. Signed-off-by: Jiri Engelthaler Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/devices/slram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 8f52fc858e48be..5a5cd2ace4a6b0 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); - devlength = handle_unit(devlength, buffer) - devstart; + devlength = handle_unit(devlength, buffer); if (devlength < devstart) goto err_out; From c7722a17ff0221200ab0bba034759f175c886b4e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 25 Sep 2012 15:27:13 +0530 Subject: [PATCH 0639/1071] mtd: ofpart: Fix incorrect NULL check in parse_ofoldpart_partitions() commit 5a6ea4af0907f995dc06df21a9c9ef764c7cd3bc upstream. The pointer returned by kzalloc should be tested for NULL to avoid potential NULL pointer dereference later. Incorrect pointer was being tested for NULL. Bug introduced by commit fbcf62a3 (mtd: physmap_of: move parse_obsolete_partitions to become separate parser). This patch fixes this bug. Signed-off-by: Sachin Kamat Cc: Dmitry Eremin-Solenikov Cc: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ofpart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 64be8f0848b075..d9127e2ed808ea 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!pparts) + if (!*pparts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); From 4158b8803e984b5400a1180791e23db4459f662a Mon Sep 17 00:00:00 2001 From: Thomas Betker Date: Wed, 17 Oct 2012 22:59:30 +0200 Subject: [PATCH 0640/1071] jffs2: Fix lock acquisition order bug in jffs2_write_begin commit 5ffd3412ae5536a4c57469cb8ea31887121dcb2e upstream. jffs2_write_begin() first acquires the page lock, then f->sem. This causes an AB-BA deadlock with jffs2_garbage_collect_live(), which first acquires f->sem, then the page lock: jffs2_garbage_collect_live mutex_lock(&f->sem) (A) jffs2_garbage_collect_dnode jffs2_gc_fetch_page read_cache_page_async do_read_cache_page lock_page(page) (B) jffs2_write_begin grab_cache_page_write_begin find_lock_page lock_page(page) (B) mutex_lock(&f->sem) (A) We fix this by restructuring jffs2_write_begin() to take f->sem before the page lock. However, we make sure that f->sem is not held when calling jffs2_reserve_space(), as this is not permitted by the locking rules. The deadlock above was observed multiple times on an SoC with a dual ARMv7 (Cortex-A9), running the long-term 3.4.11 kernel; it occurred when using scp to copy files from a host system to the ARM target system. The fix was heavily tested on the same target system. Signed-off-by: Thomas Betker Acked-by: Joakim Tjernlund Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/jffs2/file.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index db3889ba8818dd..8608f8779143ba 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, struct page *pg; struct inode *inode = mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_raw_inode ri; + uint32_t alloc_len = 0; pgoff_t index = pos >> PAGE_CACHE_SHIFT; uint32_t pageofs = index << PAGE_CACHE_SHIFT; int ret = 0; + jffs2_dbg(1, "%s()\n", __func__); + + if (pageofs > inode->i_size) { + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + if (ret) + return ret; + } + + mutex_lock(&f->sem); pg = grab_cache_page_write_begin(mapping, index, flags); - if (!pg) + if (!pg) { + if (alloc_len) + jffs2_complete_reservation(c); + mutex_unlock(&f->sem); return -ENOMEM; + } *pagep = pg; - jffs2_dbg(1, "%s()\n", __func__); - - if (pageofs > inode->i_size) { + if (alloc_len) { /* Make new hole frag from old EOF to new page */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; - uint32_t alloc_len; jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs); - ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); - if (ret) - goto out_page; - - mutex_lock(&f->sem); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, if (IS_ERR(fn)) { ret = PTR_ERR(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } ret = jffs2_add_full_dnode_to_inode(c, f, fn); @@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } jffs2_complete_reservation(c); inode->i_size = pageofs; - mutex_unlock(&f->sem); } /* @@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, * case of a short-copy. */ if (!PageUptodate(pg)) { - mutex_lock(&f->sem); ret = jffs2_do_readpage_nolock(inode, pg); - mutex_unlock(&f->sem); if (ret) goto out_page; } + mutex_unlock(&f->sem); jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); return ret; out_page: unlock_page(pg); page_cache_release(pg); + mutex_unlock(&f->sem); return ret; } From ea95b5107c1cdc7774e986d1db421b4b22e979f9 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Tue, 6 Nov 2012 17:13:44 +0800 Subject: [PATCH 0641/1071] md: Reassigned the parameters if read_seqretry returned true in func md_is_badblock. commit ab05613a0646dcc11049692d54bae76ca9ffa910 upstream. This bug was introduced by commit(v3.0-rc7-126-g2230dfe). So fix is suitable for 3.0.y thru 3.6.y. Signed-off-by: Jianpeng Ma Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 308e87b417e05a..83ad2f8d16312b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7907,9 +7907,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, sector_t *first_bad, int *bad_sectors) { int hi; - int lo = 0; + int lo; u64 *p = bb->page; - int rv = 0; + int rv; sector_t target = s + sectors; unsigned seq; @@ -7924,7 +7924,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, retry: seq = read_seqbegin(&bb->lock); - + lo = 0; + rv = 0; hi = bb->count; /* Binary search between lo and hi for 'target' From fd7cb90238cf1ca0cb9b40364892607331be4acd Mon Sep 17 00:00:00 2001 From: majianpeng Date: Thu, 8 Nov 2012 08:56:27 +0800 Subject: [PATCH 0642/1071] md: Avoid write invalid address if read_seqretry returned true. commit 35f9ac2dcec8f79d7059ce174fd7b7ee3290d620 upstream. If read_seqretry returned true and bbp was changed, it will write invalid address which can cause some serious problem. This bug was introduced by commit v3.0-rc7-130-g2699b67. So fix is suitable for 3.0.y thru 3.6.y. Reported-by: zhuwenfeng@kedacom.com Tested-by: zhuwenfeng@kedacom.com Signed-off-by: Jianpeng Ma Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 83ad2f8d16312b..c7b000fd8d35d1 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1832,10 +1832,10 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) memset(bbp, 0xff, PAGE_SIZE); for (i = 0 ; i < bb->count ; i++) { - u64 internal_bb = *p++; + u64 internal_bb = p[i]; u64 store_bb = ((BB_OFFSET(internal_bb) << 10) | BB_LEN(internal_bb)); - *bbp++ = cpu_to_le64(store_bb); + bbp[i] = cpu_to_le64(store_bb); } bb->changed = 0; if (read_seqretry(&bb->lock, seq)) From 36debf11e12044188601bf32b5e67d0d4a8b9373 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 22 Nov 2012 15:12:09 +1100 Subject: [PATCH 0643/1071] md/raid10: decrement correct pending counter when writing to replacement. commit 884162df2aadd7414bef4935e1a54976fd4e3988 upstream. When a write to a replacement device completes, we carefully and correctly found the rdev that the write actually went to and the blithely called rdev_dec_pending on the primary rdev, even if this write was to the replacement. This means that any writes to an array while a replacement was ongoing would cause the nr_pending count for the primary device to go negative, so it could never be removed. This bug has been present since replacement was introduced in 3.3, so it is suitable for any -stable kernel since then. Reported-by: "George Spelvin" Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a48c215f1262e7..3b636b874c9b13 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error) */ one_write_done(r10_bio); if (dec_rdev) - rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); + rdev_dec_pending(rdev, conf->mddev); } /* From 1840c51ad1842d31d810a64425dc2b52492ba269 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 22 Nov 2012 02:00:11 -0800 Subject: [PATCH 0644/1071] block: Don't access request after it might be freed commit 893d290f1d7496db97c9471bc352ad4a11dc8a25 upstream. After we've done __elv_add_request() and __blk_run_queue() in blk_execute_rq_nowait(), the request might finish and be freed immediately. Therefore checking if the type is REQ_TYPE_PM_RESUME isn't safe afterwards, because if it isn't, rq might be gone. Instead, check beforehand and stash the result in a temporary. This fixes crashes in blk_execute_rq_nowait() I get occasionally when running with lots of memory debugging options enabled -- I think this race is usually harmless because the window for rq to be reallocated is so small. Signed-off-by: Roland Dreier Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-exec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/block/blk-exec.c b/block/blk-exec.c index 8b6dc5bd4dd061..f71eac35c1b942 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, rq_end_io_fn *done) { int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + bool is_pm_resume; WARN_ON(irqs_disabled()); rq->rq_disk = bd_disk; rq->end_io = done; + /* + * need to check this before __blk_run_queue(), because rq can + * be freed before that returns. + */ + is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME; spin_lock_irq(q->queue_lock); @@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, __elv_add_request(q, rq, where); __blk_run_queue(q); /* the queue is stopped so it won't be run */ - if (rq->cmd_type == REQ_TYPE_PM_RESUME) + if (is_pm_resume) q->request_fn(q); spin_unlock_irq(q->queue_lock); } From 7a7c7aafc83b95909f3912bdf880f217acd69e31 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 6 Nov 2012 12:24:26 +0100 Subject: [PATCH 0645/1071] dm: fix deadlock with request based dm and queue request_fn recursion commit a8c32a5c98943d370ea606a2e7dc04717eb92206 upstream. Request based dm attempts to re-run the request queue off the request completion path. If used with a driver that potentially does end_io from its request_fn, we could deadlock trying to recurse back into request dispatch. Fix this by punting the request queue run to kblockd. Tested to fix a quickly reproducible deadlock in such a scenario. Acked-by: Alasdair G Kergon Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 67ffa391edcf1e..42562005874797 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -754,8 +754,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue) if (!md_in_flight(md)) wake_up(&md->wait); + /* + * Run this off this callpath, as drivers could invoke end_io while + * inside their request_fn (and holding the queue lock). Calling + * back into ->request_fn() could deadlock attempting to grab the + * queue lock again. + */ if (run_queue) - blk_run_queue(md->queue); + blk_run_queue_async(md->queue); /* * dm_put() must be at the end of this function. See the comment above From 922dcdcf47703b14023f20a45b5d237f22a3b9e9 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Mon, 26 Nov 2012 16:29:56 -0800 Subject: [PATCH 0646/1071] futex: avoid wake_futex() for a PI futex_q commit aa10990e028cac3d5e255711fb9fb47e00700e35 upstream. Dave Jones reported a bug with futex_lock_pi() that his trinity test exposed. Sometime between queue_me() and taking the q.lock_ptr, the lock_ptr became NULL, resulting in a crash. While futex_wake() is careful to not call wake_futex() on futex_q's with a pi_state or an rt_waiter (which are either waiting for a futex_unlock_pi() or a PI futex_requeue()), futex_wake_op() and futex_requeue() do not perform the same test. Update futex_wake_op() and futex_requeue() to test for q.pi_state and q.rt_waiter and abort with -EINVAL if detected. To ensure any future breakage is caught, add a WARN() to wake_futex() if the same condition is true. This fix has seen 3 hours of testing with "trinity -c futex" on an x86_64 VM with 4 CPUS. [akpm@linux-foundation.org: tidy up the WARN()] Signed-off-by: Darren Hart Reported-by: Dave Jones Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Ingo Molnar Cc: John Kacur Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/futex.c b/kernel/futex.c index 20ef219bbe9b76..19eb089ca003a7 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -843,6 +843,9 @@ static void wake_futex(struct futex_q *q) { struct task_struct *p = q->task; + if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n")) + return; + /* * We set q->lock_ptr = NULL _before_ we wake up the task. If * a non-futex wake up happens on another CPU then the task @@ -1078,6 +1081,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, plist_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key1)) { + if (this->pi_state || this->rt_waiter) { + ret = -EINVAL; + goto out_unlock; + } wake_futex(this); if (++ret >= nr_wake) break; @@ -1090,6 +1097,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, op_ret = 0; plist_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key2)) { + if (this->pi_state || this->rt_waiter) { + ret = -EINVAL; + goto out_unlock; + } wake_futex(this); if (++op_ret >= nr_wake2) break; @@ -1098,6 +1109,7 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, ret += op_ret; } +out_unlock: double_unlock_hb(hb1, hb2); out_put_keys: put_futex_key(&key2); @@ -1387,9 +1399,13 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, /* * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always * be paired with each other and no other futex ops. + * + * We should never be requeueing a futex_q with a pi_state, + * which is awaiting a futex_unlock_pi(). */ if ((requeue_pi && !this->rt_waiter) || - (!requeue_pi && this->rt_waiter)) { + (!requeue_pi && this->rt_waiter) || + this->pi_state) { ret = -EINVAL; break; } From 0596121fd83711fc79382196022a714d255f0989 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 13 Nov 2012 18:43:03 +0100 Subject: [PATCH 0647/1071] mac80211: deinitialize ibss-internals after emptiness check commit b78a4932f5fb11fadf41e69c606a33fa6787574c upstream. The check whether the IBSS is active and can be removed should be performed before deinitializing the fields used for the check/search. Otherwise, the configured BSS will not be found and removed properly. To make it more clear for the future, rename sdata->u.ibss to the local pointer ifibss which is used within the checks. This behaviour was introduced by f3209bea110cade12e2b133da8b8499689cb0e2e ("mac80211: fix IBSS teardown race") Signed-off-by: Simon Wunderlich Cc: Ignacy Gawedzki Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 327aa076c2bb89..a5894dd7256102 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1117,10 +1117,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->u.ibss.mtx); - sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); - sdata->u.ibss.ssid_len = 0; - active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -1141,6 +1137,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) } } + ifibss->state = IEEE80211_IBSS_MLME_SEARCH; + memset(ifibss->bssid, 0, ETH_ALEN); + ifibss->ssid_len = 0; + sta_info_flush(sdata->local, sdata); spin_lock_bh(&ifibss->incomplete_lock); From 0314f284eb000d55ccbac67a9b1fce4912d86937 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 19 Nov 2012 21:17:31 +0100 Subject: [PATCH 0648/1071] radeon: add AGPMode 1 quirk for RV250 commit 45171002b01b2e2ec4f991eca81ffd8430fd0aec upstream. The Intel 82855PM host bridge / Mobility FireGL 9000 RV250 combination in an (outdated) ThinkPad T41 needs AGPMode 1 for suspend/resume (under KMS, that is). So add a quirk for it. (Change R250 to RV250 in comment for preceding quirk too.) Signed-off-by: Paul Bolle Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_agp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index bd2f33e5c91a69..bc6b64fe0e0985 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -70,9 +70,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, PCI_VENDOR_ID_DELL, 0x00e3, 2}, - /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ + /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, PCI_VENDOR_ID_DELL, 0x0149, 1}, + /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_IBM, 0x0531, 1}, /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 0x1025, 0x0061, 1}, From 4735a28cf102492dde4c036f74b0c2d8318ed004 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 21 Nov 2012 22:43:59 +0100 Subject: [PATCH 0649/1071] can: peak_usb: fix hwtstamp assignment commit c9faaa09e2a1335678f09c70a0d0eda095564bab upstream. The skb->tstamp is set to the hardware timestamp when available in the USB urb message. This leads to user visible timestamps which contain the 'uptime' of the USB adapter - and not the usual system generated timestamp. Fix this wrong assignment by applying the available hardware timestamp to the skb_shared_hwtstamps data structure - which is intended for this purpose. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/usb/peak_usb/pcan_usb.c | 8 ++++++-- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 86f26a1ede4c18..25723d8ee20130 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -519,8 +519,10 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, mc->pdev->dev.can.state = new_state; if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { + struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); + peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts->hwtstamp = timeval_to_ktime(tv); } netif_rx(skb); @@ -605,6 +607,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) struct sk_buff *skb; struct can_frame *cf; struct timeval tv; + struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(mc->netdev, &cf); if (!skb) @@ -652,7 +655,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) /* convert timestamp into kernel time */ peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); /* push the skb */ netif_rx(skb); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 629c4ba5d49d95..c95913a097372c 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -532,6 +532,7 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, struct can_frame *can_frame; struct sk_buff *skb; struct timeval tv; + struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(netdev, &can_frame); if (!skb) @@ -549,7 +550,8 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, memcpy(can_frame->data, rx->data, can_frame->can_dlc); peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); netif_rx(skb); netdev->stats.rx_packets++; @@ -570,6 +572,7 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, u8 err_mask = 0; struct sk_buff *skb; struct timeval tv; + struct skb_shared_hwtstamps *hwts; /* nothing should be sent while in BUS_OFF state */ if (dev->can.state == CAN_STATE_BUS_OFF) @@ -664,7 +667,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, dev->can.state = new_state; peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; From dfe66ae640ccae2d78bea2f84e75ab76f42c3cfb Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 26 Nov 2012 22:24:23 +0100 Subject: [PATCH 0650/1071] can: bcm: initialize ifindex for timeouts without previous frame reception commit 81b401100c01d2357031e874689f89bd788d13cd upstream. Set in the rx_ifindex to pass the correct interface index in the case of a message timeout detection. Usually the rx_ifindex value is set at receive time. But when no CAN frame has been received the RX_TIMEOUT notification did not contain a valid value. Reported-by: Andre Naujoks Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- net/can/bcm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/can/bcm.c b/net/can/bcm.c index 151b7730c12c72..3910c1fefd04f7 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1084,6 +1084,9 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, op->sk = sk; op->ifindex = ifindex; + /* ifindex for timeout events w/o previous frame reception */ + op->rx_ifindex = ifindex; + /* initialize uninitialized (kzalloc) structure */ hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); op->timer.function = bcm_rx_timeout_handler; From 1abb8a53f9e49838d8b5b4b8e57c135378fa1bf6 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 23 Nov 2012 14:03:04 +0100 Subject: [PATCH 0651/1071] jbd: Fix lock ordering bug in journal_unmap_buffer() commit 25389bb207987b5774182f763b9fb65ff08761c8 upstream. Commit 09e05d48 introduced a wait for transaction commit into journal_unmap_buffer() in the case we are truncating a buffer undergoing commit in the page stradding i_size on a filesystem with blocksize < pagesize. Sadly we forgot to drop buffer lock before waiting for transaction commit and thus deadlock is possible when kjournald wants to lock the buffer. Fix the problem by dropping the buffer lock before waiting for transaction commit. Since we are still holding page lock (and that is OK), buffer cannot disappear under us. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/jbd/transaction.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 78b7f84241d47b..7f5120bf0ec29c 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1961,7 +1961,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); + unlock_buffer(bh); log_wait_commit(journal, tid); + lock_buffer(bh); goto retry; } /* From cbda50306446b3f359bbf2874a99979990b0627c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 18 Nov 2012 22:27:03 -0500 Subject: [PATCH 0652/1071] sparc64: not any error from do_sigaltstack() should fail rt_sigreturn() commit fae2ae2a900a5c7bb385fe4075f343e7e2d5daa2 upstream. If a signal handler is executed on altstack and another signal comes, we will end up with rt_sigreturn() on return from the second handler getting -EPERM from do_sigaltstack(). It's perfectly OK, since we are not asking to change the settings; in fact, they couldn't have been changed during the second handler execution exactly because we'd been on altstack all along. 64bit sigreturn on sparc treats any error from do_sigaltstack() as "SIGSEGV now"; we need to switch to the same semantics we are using on other architectures. Signed-off-by: Al Viro Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/signal_64.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 867de2f8189c32..689e1ba628097e 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); - - if (err) + if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); From dc541b2ba0e0aa83831ca99ba1e5a574e41d3c5b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 23 Nov 2012 20:55:06 +0100 Subject: [PATCH 0653/1071] PM / QoS: fix wrong error-checking condition commit a7227a0faa117d0bc532aea546ae5ac5f89e8ed7 upstream. dev_pm_qos_add_request() can return 0, 1, or a negative error code, therefore the correct error test is "if (error < 0)." Checking just for non-zero return code leads to erroneous setting of the req->dev pointer to NULL, which then leads to a repeated call to dev_pm_qos_add_ancestor_request() in st1232_ts_irq_handler(). This in turn leads to an Oops, when the I2C host adapter is unloaded and reloaded again because of the inconsistent state of its QoS request list. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/qos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 74a67e0019a2d2..fbbd4ed2edf288 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -451,7 +451,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev, if (ancestor) error = dev_pm_qos_add_request(ancestor, req, value); - if (error) + if (error < 0) req->dev = NULL; return error; From 9c782bac5764db62c6e23f3d13faec003fc973f5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Nov 2012 16:29:51 -0800 Subject: [PATCH 0654/1071] writeback: put unused inodes to LRU after writeback completion commit 4eff96dd5283a102e0c1cac95247090be74a38ed upstream. Commit 169ebd90131b ("writeback: Avoid iput() from flusher thread") removed iget-iput pair from inode writeback. As a side effect, inodes that are dirty during iput_final() call won't be ever added to inode LRU (iput_final() doesn't add dirty inodes to LRU and later when the inode is cleaned there's noone to add the inode there). Thus inodes are effectively unreclaimable until someone looks them up again. The practical effect of this bug is limited by the fact that inodes are pinned by a dentry for long enough that the inode gets cleaned. But still the bug can have nasty consequences leading up to OOM conditions under certain circumstances. Following can easily reproduce the problem: for (( i = 0; i < 1000; i++ )); do mkdir $i for (( j = 0; j < 1000; j++ )); do touch $i/$j echo 2 > /proc/sys/vm/drop_caches done done then one needs to run 'sync; ls -lR' to make inodes reclaimable again. We fix the issue by inserting unused clean inodes into the LRU after writeback finishes in inode_sync_complete(). Signed-off-by: Jan Kara Reported-by: OGAWA Hirofumi Cc: Al Viro Cc: OGAWA Hirofumi Cc: Wu Fengguang Cc: Dave Chinner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/fs-writeback.c | 2 ++ fs/inode.c | 16 ++++++++++++++-- fs/internal.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 5602d73d4ec7a5..af321a6f71ffa4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -228,6 +228,8 @@ static void requeue_io(struct inode *inode, struct bdi_writeback *wb) static void inode_sync_complete(struct inode *inode) { inode->i_state &= ~I_SYNC; + /* If inode is clean an unused, put it into LRU now... */ + inode_add_lru(inode); /* Waiters must see I_SYNC cleared before being woken up */ smp_mb(); wake_up_bit(&inode->i_state, __I_SYNC); diff --git a/fs/inode.c b/fs/inode.c index ac8d904b3f1624..7c14897f9a9ff1 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -408,6 +408,19 @@ static void inode_lru_list_add(struct inode *inode) spin_unlock(&inode->i_sb->s_inode_lru_lock); } +/* + * Add inode to LRU if needed (inode is unused and clean). + * + * Needs inode->i_lock held. + */ +void inode_add_lru(struct inode *inode) +{ + if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) && + !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE) + inode_lru_list_add(inode); +} + + static void inode_lru_list_del(struct inode *inode) { spin_lock(&inode->i_sb->s_inode_lru_lock); @@ -1390,8 +1403,7 @@ static void iput_final(struct inode *inode) if (!drop && (sb->s_flags & MS_ACTIVE)) { inode->i_state |= I_REFERENCED; - if (!(inode->i_state & (I_DIRTY|I_SYNC))) - inode_lru_list_add(inode); + inode_add_lru(inode); spin_unlock(&inode->i_lock); return; } diff --git a/fs/internal.h b/fs/internal.h index 371bcc4b1697df..52813bd2a22906 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -110,6 +110,7 @@ extern int open_check_o_direct(struct file *f); * inode.c */ extern spinlock_t inode_sb_list_lock; +extern void inode_add_lru(struct inode *inode); /* * fs-writeback.c From bfada93d02f730e49c280e3a1c32d1ae7d10260c Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Sat, 6 Oct 2012 17:02:30 +0200 Subject: [PATCH 0655/1071] ALSA: hda - Add new codec ALC283 ALC290 support commit 7ff34ad80b7080fafaac8efa9ef0061708eddd51 upstream. These are compatible with standard ALC269 parser. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f6b5995fce9c9b..9af377b7213295 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7089,6 +7089,8 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, + { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, + { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, From e55fbe2e0605183fcc62753c3cc9c4ad624c14c9 Mon Sep 17 00:00:00 2001 From: Duncan Roe Date: Wed, 10 Oct 2012 14:19:50 +0200 Subject: [PATCH 0656/1071] ALSA: hda - Fix missing beep on ASUS X43U notebook commit 7110005e8d5c3cd418fc4b64f9f124f004422a9a upstream. Signed-off-by: Duncan Roe Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9af377b7213295..48a9adcd9cd91a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4280,6 +4280,7 @@ static void alc_auto_init_std(struct hda_codec *codec) ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) static const struct snd_pci_quirk beep_white_list[] = { + SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), From ca3e1522d28f0ce909e5a7936a26ccaadfaac8b1 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 21 Nov 2012 08:57:58 +0100 Subject: [PATCH 0657/1071] ALSA: hda - Add support for Realtek ALC292 commit af02dde8a609d8d071c4b31a82df811a55690a4a upstream. We found a new codec ID 292, and that just a simple quirk would enable sound output/input on this ALC292 chip. BugLink: https://bugs.launchpad.net/bugs/1081466 Tested-by: Acelan Kao Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 48a9adcd9cd91a..e1b7061d23b630 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7092,6 +7092,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, + { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, From 28bd49d3771d3071fe1345fa4f78240230804604 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Wed, 24 Oct 2012 08:44:32 +0000 Subject: [PATCH 0658/1071] bas_gigaset: fix pre_reset handling commit c6fdd8e5d0c65bb8821dc6da26ee1a2ddd58b3cc upstream. The delayed work function int_in_work() may call usb_reset_device() and thus, indirectly, the driver's pre_reset method. Trying to cancel the work synchronously in that situation would deadlock. Fix by avoiding cancel_work_sync() in the pre_reset method. If the reset was NOT initiated by int_in_work() this might cause int_in_work() to run after the post_reset method, with urb_int_in already resubmitted, so handle that case gracefully. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/gigaset/bas-gigaset.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 5275887089483b..c44950d3eb7b48 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work) if (rc == 0) /* success, resubmit interrupt read URB */ rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc != 0 && rc != -ENODEV) { + + switch (rc) { + case 0: /* success */ + case -ENODEV: /* device gone */ + case -EINVAL: /* URB already resubmitted, or terminal badness */ + break; + default: /* failure: try to recover by resetting the device */ dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); if (rc == 0) { @@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface) } /* gigaset_suspend - * This function is called before the USB connection is suspended. + * This function is called before the USB connection is suspended + * or before the USB device is reset. + * In the latter case, message == PMSG_ON. */ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) { @@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) del_timer_sync(&ucs->timer_atrdy); del_timer_sync(&ucs->timer_cmd_in); del_timer_sync(&ucs->timer_int_in); - cancel_work_sync(&ucs->int_in_wq); + + /* don't try to cancel int_in_wq from within reset as it + * might be the one requesting the reset + */ + if (message.event != PM_EVENT_ON) + cancel_work_sync(&ucs->int_in_wq); gig_dbg(DEBUG_SUSPEND, "suspend complete"); return 0; From ce88af87d72ed98c4f3c989ec802e6ab2c1c856c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 3 Aug 2012 17:02:48 -0700 Subject: [PATCH 0659/1071] pstore/ram: Fix printk format warning commit 0427193b691edc81c846c7d0ebd2561cae8709d8 upstream. Fix printk format warning (on i386) in pstore: fs/pstore/ram.c:409:3: warning: format '%lu' expects type 'long unsigned int', but argument 2 has type 'size_t' Signed-off-by: Randy Dunlap Acked-by: Kees Cook Signed-off-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman --- fs/pstore/ram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 0b311bc18916ab..6a37656fc0a015 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -406,7 +406,7 @@ static int __devinit ramoops_probe(struct platform_device *pdev) goto fail_init_fprz; if (!cxt->przs && !cxt->cprz && !cxt->fprz) { - pr_err("memory size too small, minimum is %lu\n", + pr_err("memory size too small, minimum is %zu\n", cxt->console_size + cxt->record_size + cxt->ftrace_size); goto fail_cnt; From 2da722f9fc67a5a454f07a6109e8534c47b121f4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 5 Aug 2012 23:57:15 +0200 Subject: [PATCH 0660/1071] HID: add quirk for Freescale i.MX28 ROM recovery commit 2843b673d03421e0e73cf061820d1db328f7c8eb upstream. The USB recovery mode present in i.MX28 ROM emulates USB HID. It needs this quirk to behave properly. Signed-off-by: Marek Vasut Cc: Chen Peter Cc: Jiri Kosina [jkosina@suse.cz: fix alphabetical ordering] Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 1dcb76ff51e340..ab8ce9f6d42a35 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -296,6 +296,9 @@ #define USB_VENDOR_ID_EZKEY 0x0518 #define USB_DEVICE_ID_BTC_8193 0x0002 +#define USB_VENDOR_ID_FREESCALE 0x15A2 +#define USB_DEVICE_ID_FREESCALE_MX28 0x004F + #define USB_VENDOR_ID_FRUCTEL 0x25B6 #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 991e85c7325c84..8865fa3ef860f0 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -70,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, From e467125d3c2cd80d100e7d3c12547621a5eb8e2f Mon Sep 17 00:00:00 2001 From: Petr Matousek Date: Tue, 6 Nov 2012 19:24:07 +0100 Subject: [PATCH 0661/1071] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit set (CVE-2012-4461) commit 6d1068b3a98519247d8ba4ec85cd40ac136dbdf9 upstream. On hosts without the XSAVE support unprivileged local user can trigger oops similar to the one below by setting X86_CR4_OSXSAVE bit in guest cr4 register using KVM_SET_SREGS ioctl and later issuing KVM_RUN ioctl. invalid opcode: 0000 [#2] SMP Modules linked in: tun ip6table_filter ip6_tables ebtable_nat ebtables ... Pid: 24935, comm: zoog_kvm_monito Tainted: G D 3.2.0-3-686-pae EIP: 0060:[] EFLAGS: 00210246 CPU: 0 EIP is at kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] EAX: 00000001 EBX: 000f387e ECX: 00000000 EDX: 00000000 ESI: 00000000 EDI: 00000000 EBP: ef5a0060 ESP: d7c63e70 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process zoog_kvm_monito (pid: 24935, ti=d7c62000 task=ed84a0c0 task.ti=d7c62000) Stack: 00000001 f70a1200 f8b940a9 ef5a0060 00000000 00200202 f8769009 00000000 ef5a0060 000f387e eda5c020 8722f9c8 00015bae 00000000 ed84a0c0 ed84a0c0 c12bf02d 0000ae80 ef7f8740 fffffffb f359b740 ef5a0060 f8b85dc1 0000ae80 Call Trace: [] ? kvm_arch_vcpu_ioctl_set_sregs+0x2fe/0x308 [kvm] ... [] ? syscall_call+0x7/0xb Code: 89 e8 e8 14 ee ff ff ba 00 00 04 00 89 e8 e8 98 48 ff ff 85 c0 74 1e 83 7d 48 00 75 18 8b 85 08 07 00 00 31 c9 8b 95 0c 07 00 00 <0f> 01 d1 c7 45 48 01 00 00 00 c7 45 1c 01 00 00 00 0f ae f0 89 EIP: [] kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] SS:ESP 0068:d7c63e70 QEMU first retrieves the supported features via KVM_GET_SUPPORTED_CPUID and then sets them later. So guest's X86_FEATURE_XSAVE should be masked out on hosts without X86_FEATURE_XSAVE, making kvm_set_cr4 with X86_CR4_OSXSAVE fail. Userspaces that allow specifying guest cpuid with X86_FEATURE_XSAVE even on hosts that do not support it, might be susceptible to this attack from inside the guest as well. Allow setting X86_CR4_OSXSAVE bit only if host has XSAVE support. Signed-off-by: Petr Matousek Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/cpuid.h | 3 +++ arch/x86/kvm/x86.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index a10e4601685135..58fc5148882857 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; + if (!static_cpu_has(X86_FEATURE_XSAVE)) + return 0; + best = kvm_find_cpuid_entry(vcpu, 1, 0); return best && (best->ecx & bit(X86_FEATURE_XSAVE)); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2966c847d489d8..a2017902cf5856 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5762,6 +5762,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int pending_vec, max_bits, idx; struct desc_ptr dt; + if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) + return -EINVAL; + dt.size = sregs->idt.limit; dt.address = sregs->idt.base; kvm_x86_ops->set_idt(vcpu, &dt); From 2c531aa6d24cc8372c6aa4c0993309186dfb66af Mon Sep 17 00:00:00 2001 From: "joshua.a.hay@intel.com" Date: Fri, 21 Sep 2012 00:08:21 +0000 Subject: [PATCH 0662/1071] ixgbe: add support for X540-AT1 commit df376f0de167754da9b3ece4afdb5bb8bf3fbf3e upstream. This patch adds device support for Ethernet Controller X540-AT1. Signed-off-by: Josh Hay Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher Signed-off-by: Abdallah Chatila Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 90e41db3cb695b..dbf37e4a45fda7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -70,6 +70,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: return 0; case IXGBE_DEV_ID_82599_T3_LOM: return 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 4326f74f7137a3..1fff36dda62ef2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -114,6 +114,7 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 }, /* required last entry */ {0, } }; @@ -7010,6 +7011,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id, is_wol_supported = 1; break; case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: /* check eeprom to see if enabled wol */ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) || ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) && diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 400f86a3117402..0722f33680926e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -65,6 +65,7 @@ #define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 #define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A +#define IXGBE_DEV_ID_X540T1 0x1560 /* VF Device IDs */ #define IXGBE_DEV_ID_82599_VF 0x10ED From 7e351dcf6764e9d6ab6c12efef6bace6eeeb2b36 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Mon, 29 Oct 2012 18:00:22 -0500 Subject: [PATCH 0663/1071] sata_svw: check DMA start bit before reset commit b03e66a6be91f8389fcd902ab6c1563db1c9c06b upstream. If kdump is triggered with pending IO, controller may not respond causing kdump to fail. http://marc.info/?l=linux-ide&m=133032255424658&w=2 During error recovery ata_do_dev_read_id never completes due hang in mmio_insw. ata_do_dev_read_id ata_sff_data_xfer ioread16_rep mmio_insw if DMA start bit is cleared before reset, PIO command is successful and kdump succeeds. Signed-off-by: David Milburn Signed-off-by: Jeff Garzik Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/ata/sata_svw.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 44a4256533e1bd..08608de87e4e6a 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link, return 0; } +static int k2_sata_softreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return sata_sff_hardreset(link, class, deadline); +} static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { @@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = { static struct ata_port_operations k2_sata_ops = { .inherits = &ata_bmdma_port_ops, + .softreset = k2_sata_softreset, + .hardreset = k2_sata_hardreset, .sff_tf_load = k2_sata_tf_load, .sff_tf_read = k2_sata_tf_read, .sff_check_status = k2_stat_check_status, From 741a51d4a8ba2d22ce9209b34ff66e84f5ca645c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Sep 2012 16:16:00 -0300 Subject: [PATCH 0664/1071] get_dvb_firmware: fix download site for tda10046 firmware commit 25ec43d3e6306978cf66060ed18c4160ce8fc302 upstream. The previous website doesn't exist anymore. Update it to one site that actually exists. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- Documentation/dvb/get_dvb_firmware | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 12d3952e83d5b0..32bc56b13b1c7c 100755 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -116,7 +116,7 @@ sub tda10045 { sub tda10046 { my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip"; - my $url = "http://www.tt-download.com/download/updates/219/$sourcefile"; + my $url = "http://technotrend.com.ua/download/software/219/$sourcefile"; my $hash = "6a7e1e2f2644b162ff0502367553c72d"; my $outfile = "dvb-fe-tda10046.fw"; my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); From ae93d015d1868e5cdfb2329df4e7102b3eddbf1f Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 29 Oct 2012 14:04:43 +0100 Subject: [PATCH 0665/1071] NFC: pn533: Fix use after free commit 770f750bc2b8312489c8e45306f551d08a319d3c upstream. cmd was freed in pn533_dep_link_up regardless of pn533_send_cmd_frame_async return code. Cmd is passed as argument to pn533_in_dep_link_up_complete callback and should be freed there. Signed-off-by: Szymon Janc Signed-off-by: Samuel Ortiz Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/pn533.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index d606f52fec842d..413fcad3833c51 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1759,12 +1759,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, dev->in_maxlen, pn533_in_dep_link_up_complete, cmd, GFP_KERNEL); - if (rc) - goto out; - - -out: - kfree(cmd); + if (rc < 0) + kfree(cmd); return rc; } From 288267200ed15a769b2ec0045873c7afdf759d42 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 15 Nov 2012 18:24:28 +0100 Subject: [PATCH 0666/1071] NFC: Fix pn533 target mode memory leak commit 5b412fd11c918171c98a253d8a3484afa9f69ca5 upstream. In target mode, sent sk_buff were not freed in pn533_tm_send_complete Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/pn533.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 413fcad3833c51..ac520406e13467 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -2014,8 +2014,12 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, static int pn533_tm_send_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { + struct sk_buff *skb_out = arg; + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_kfree_skb(skb_out); + if (params_len < 0) { nfc_dev_err(&dev->interface->dev, "Error %d when sending data", @@ -2053,7 +2057,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, dev->in_maxlen, pn533_tm_send_complete, - NULL, GFP_KERNEL); + skb, GFP_KERNEL); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to send data", rc); From 014703df1078581921afd20edc03b7baec936ad3 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 11 Oct 2012 14:04:00 +0200 Subject: [PATCH 0667/1071] NFC: pn533: Fix mem leak in pn533_in_dep_link_up commit 70418e6efcf4f8652cc08e3f2ab8ae35f0948fd9 upstream. cmd is allocated in pn533_dep_link_up and passed as an arg to pn533_send_cmd_frame_async together with a complete cb. arg is passed to the cb and must be kfreed there. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/pn533.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index ac520406e13467..83ba14e9c6c692 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1618,11 +1618,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { - struct pn533_cmd_jump_dep *cmd; struct pn533_cmd_jump_dep_response *resp; struct nfc_target nfc_target; u8 target_gt_len; int rc; + struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; + u8 active = cmd->active; + + kfree(arg); if (params_len == -ENOENT) { nfc_dev_dbg(&dev->interface->dev, ""); @@ -1644,7 +1647,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } resp = (struct pn533_cmd_jump_dep_response *) params; - cmd = (struct pn533_cmd_jump_dep *) arg; rc = resp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, @@ -1674,7 +1676,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, dev->nfc_dev->targets[0].idx, - !cmd->active, NFC_RF_INITIATOR); + !active, NFC_RF_INITIATOR); return 0; } From 1a46298f9da553d85dbbe39022d2b142b2cd86f0 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Fri, 12 Oct 2012 15:25:43 +0200 Subject: [PATCH 0668/1071] NFC: Fix nfc_llcp_local chained list insertion commit 16a78e9fed5e8baa8480ae3413f4328c4537c599 upstream. list_add was called with swapped parameters Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- net/nfc/llcp/llcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 7dd983a4168843..83a3592f9f7cff 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -1190,7 +1190,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->remote_miu = LLCP_DEFAULT_MIU; local->remote_lto = LLCP_DEFAULT_LTO; - list_add(&llcp_devices, &local->list); + list_add(&local->list, &llcp_devices); return 0; From 8f90c1386466ff66fc9f23ce0dfc7311c5e4a22d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 26 Nov 2012 16:29:48 -0800 Subject: [PATCH 0669/1071] mm: vmscan: check for fatal signals iff the process was throttled commit 50694c28f1e1dbea18272980d265742a5027fb63 upstream. Commit 5515061d22f0 ("mm: throttle direct reclaimers if PF_MEMALLOC reserves are low and swap is backed by network storage") introduced a check for fatal signals after a process gets throttled for network storage. The intention was that if a process was throttled and got killed that it should not trigger the OOM killer. As pointed out by Minchan Kim and David Rientjes, this check is in the wrong place and too broad. If a system is in am OOM situation and a process is exiting, it can loop in __alloc_pages_slowpath() and calling direct reclaim in a loop. As the fatal signal is pending it returns 1 as if it is making forward progress and can effectively deadlock. This patch moves the fatal_signal_pending() check after throttling to throttle_direct_reclaim() where it belongs. If the process is killed while throttled, it will return immediately without direct reclaim except now it will have TIF_MEMDIE set and will use the PFMEMALLOC reserves. Minchan pointed out that it may be better to direct reclaim before returning to avoid using the reserves because there may be pages that can easily reclaim that would avoid using the reserves. However, we do no such targetted reclaim and there is no guarantee that suitable pages are available. As it is expected that this throttling happens when swap-over-NFS is used there is a possibility that the process will instead swap which may allocate network buffers from the PFMEMALLOC reserves. Hence, in the swap-over-nfs case where a process can be throtted and be killed it can use the reserves to exit or it can potentially use reserves to swap a few pages and then exit. This patch takes the option of using the reserves if necessary to allow the process exit quickly. If this patch passes review it should be considered a -stable candidate for 3.6. Signed-off-by: Mel Gorman Cc: David Rientjes Cc: Luigi Semenzato Cc: Dan Magenheimer Cc: KOSAKI Motohiro Cc: Sonny Rao Cc: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index a018dfcbb2f76f..40db7d17ec9828 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2176,9 +2176,12 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat) * Throttle direct reclaimers if backing storage is backed by the network * and the PFMEMALLOC reserve for the preferred node is getting dangerously * depleted. kswapd will continue to make progress and wake the processes - * when the low watermark is reached + * when the low watermark is reached. + * + * Returns true if a fatal signal was delivered during throttling. If this + * happens, the page allocator should not consider triggering the OOM killer. */ -static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist, +static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist, nodemask_t *nodemask) { struct zone *zone; @@ -2193,13 +2196,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist, * processes to block on log_wait_commit(). */ if (current->flags & PF_KTHREAD) - return; + goto out; + + /* + * If a fatal signal is pending, this process should not throttle. + * It should return quickly so it can exit and free its memory + */ + if (fatal_signal_pending(current)) + goto out; /* Check if the pfmemalloc reserves are ok */ first_zones_zonelist(zonelist, high_zoneidx, NULL, &zone); pgdat = zone->zone_pgdat; if (pfmemalloc_watermark_ok(pgdat)) - return; + goto out; /* Account for the throttling */ count_vm_event(PGSCAN_DIRECT_THROTTLE); @@ -2215,12 +2225,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist, if (!(gfp_mask & __GFP_FS)) { wait_event_interruptible_timeout(pgdat->pfmemalloc_wait, pfmemalloc_watermark_ok(pgdat), HZ); - return; + + goto check_pending; } /* Throttle until kswapd wakes the process */ wait_event_killable(zone->zone_pgdat->pfmemalloc_wait, pfmemalloc_watermark_ok(pgdat)); + +check_pending: + if (fatal_signal_pending(current)) + return true; + +out: + return false; } unsigned long try_to_free_pages(struct zonelist *zonelist, int order, @@ -2242,13 +2260,12 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order, .gfp_mask = sc.gfp_mask, }; - throttle_direct_reclaim(gfp_mask, zonelist, nodemask); - /* - * Do not enter reclaim if fatal signal is pending. 1 is returned so - * that the page allocator does not consider triggering OOM + * Do not enter reclaim if fatal signal was delivered while throttled. + * 1 is returned so that the page allocator does not OOM kill at this + * point. */ - if (fatal_signal_pending(current)) + if (throttle_direct_reclaim(gfp_mask, zonelist, nodemask)) return 1; trace_mm_vmscan_direct_reclaim_begin(order, From 996d9a5f19e57371ab68e55ad09477cde2771918 Mon Sep 17 00:00:00 2001 From: Chuansheng Liu Date: Mon, 26 Nov 2012 16:29:54 -0800 Subject: [PATCH 0670/1071] watchdog: using u64 in get_sample_period() commit 8ffeb9b0e6369135bf03a073514f571ef10606b9 upstream. In get_sample_period(), unsigned long is not enough: watchdog_thresh * 2 * (NSEC_PER_SEC / 5) case1: watchdog_thresh is 10 by default, the sample value will be: 0xEE6B2800 case2: set watchdog_thresh is 20, the sample value will be: 0x1 DCD6 5000 In case2, we need use u64 to express the sample period. Otherwise, changing the threshold thru proc often can not be successful. Signed-off-by: liu chuansheng Acked-by: Don Zickus Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- kernel/watchdog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 4b1dfba70f7cf8..775fa0f5e078e2 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -113,7 +113,7 @@ static unsigned long get_timestamp(int this_cpu) return cpu_clock(this_cpu) >> 30LL; /* 2^30 ~= 10^9 */ } -static unsigned long get_sample_period(void) +static u64 get_sample_period(void) { /* * convert watchdog_thresh from seconds to ns @@ -122,7 +122,7 @@ static unsigned long get_sample_period(void) * and hard thresholds) to increment before the * hardlockup detector generates a warning */ - return get_softlockup_thresh() * (NSEC_PER_SEC / 5); + return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); } /* Commands for resetting the watchdog */ From 5433889db1b04159054a9e6357f90c77970cf4ed Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 22 Nov 2012 11:58:22 +0100 Subject: [PATCH 0671/1071] MPI: Fix compilation on MIPS with GCC 4.4 and newer commit a3cea9894157c20a5b1ec08b7e0b5f2019740c10 upstream. Since 4.4 GCC on MIPS no longer recognizes the "h" constraint, leading to this build failure: CC lib/mpi/generic_mpih-mul1.o lib/mpi/generic_mpih-mul1.c: In function 'mpihelp_mul_1': lib/mpi/generic_mpih-mul1.c:50:3: error: impossible constraint in 'asm' This patch updates MPI with the latest umul_ppm implementations for MIPS. Signed-off-by: Manuel Lauss Cc: Linux-MIPS Cc: Dmitry Kasatkin Cc: James Morris Patchwork: https://patchwork.linux-mips.org/patch/4612/ Signed-off-by: Ralf Baechle Cc: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- lib/mpi/longlong.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 29f98624ef93a7..280405b47e7194 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -703,7 +703,14 @@ do { \ ************** MIPS ***************** ***************************************/ #if defined(__mips__) && W_TYPE_SIZE == 32 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + UDItype __ll = (UDItype)(u) * (v); \ + w1 = __ll >> 32; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3" \ : "=l" ((USItype)(w0)), \ @@ -728,7 +735,15 @@ do { \ ************** MIPS/64 ************** ***************************************/ #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ + __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ + w1 = __ll >> 64; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3" \ : "=l" ((UDItype)(w0)), \ From 5770e9ed8a5b8ae7204e6cfe52565f10395091e4 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 20 Sep 2012 11:35:38 -0400 Subject: [PATCH 0672/1071] ext4: remove erroneous ext4_superblock_csum_set() in update_backups() commit bef53b01faeb791e27605cba1a71ba21364cb23e upstream. The update_backups() function is used to backup all the metadata blocks, so we should not take it for granted that 'data' is pointed to a super block and use ext4_superblock_csum_set to calculate the checksum there. In case where the data is a group descriptor block, it will corrupt the last group descriptor, and then e2fsck will complain about it it. As all the metadata checksums should already be OK when we do the backup, remove the wrong ext4_superblock_csum_set and it should be just fine. Reported-by: "Theodore Ts'o" Signed-off-by: Tao Ma Signed-off-by: "Theodore Ts'o" Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 101b41c6844c9f..82e1fde3e0ef38 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -979,8 +979,6 @@ static void update_backups(struct super_block *sb, goto exit_err; } - ext4_superblock_csum_set(sb); - while ((group = ext4_list_backups(sb, &three, &five, &seven)) < last) { struct buffer_head *bh; From db9d0c8d25d316f38fbd7e0c683e30041bf4cc09 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Mon, 17 Sep 2012 04:34:27 +0000 Subject: [PATCH 0673/1071] powerpc/eeh: Lock module while handling EEH event commit feadf7c0a1a7c08c74bebb4a13b755f8c40e3bbc upstream. The EEH core is talking with the PCI device driver to determine the action (purely reset, or PCI device removal). During the period, the driver might be unloaded and in turn causes kernel crash as follows: EEH: Detected PCI bus error on PHB#4-PE#10000 EEH: This PCI device has failed 3 times in the last hour lpfc 0004:01:00.0: 0:2710 PCI channel disable preparing for reset Unable to handle kernel paging request for data at address 0x00000490 Faulting instruction address: 0xd00000000e682c90 cpu 0x1: Vector: 300 (Data Access) at [c000000fc75ffa20] pc: d00000000e682c90: .lpfc_io_error_detected+0x30/0x240 [lpfc] lr: d00000000e682c8c: .lpfc_io_error_detected+0x2c/0x240 [lpfc] sp: c000000fc75ffca0 msr: 8000000000009032 dar: 490 dsisr: 40000000 current = 0xc000000fc79b88b0 paca = 0xc00000000edb0380 softe: 0 irq_happened: 0x00 pid = 3386, comm = eehd enter ? for help [c000000fc75ffca0] c000000fc75ffd30 (unreliable) [c000000fc75ffd30] c00000000004fd3c .eeh_report_error+0x7c/0xf0 [c000000fc75ffdc0] c00000000004ee00 .eeh_pe_dev_traverse+0xa0/0x180 [c000000fc75ffe70] c00000000004ffd8 .eeh_handle_event+0x68/0x300 [c000000fc75fff00] c0000000000503a0 .eeh_event_handler+0x130/0x1a0 [c000000fc75fff90] c000000000020138 .kernel_thread+0x54/0x70 1:mon> The patch increases the reference of the corresponding driver modules while EEH core does the negotiation with PCI device driver so that the corresponding driver modules can't be unloaded during the period and we're safe to refer the callbacks. Reported-by: Alexey Kardashevskiy Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt [ herton: backported for 3.5, adjusted driver assignments, return 0 instead of NULL, assume dev is not NULL ] Signed-off-by: Herton Ronaldo Krzesinski Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/pseries/eeh_driver.c | 95 ++++++++++++++++----- 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index baf92cd9dfab62..041e28d0e702c5 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,41 @@ static inline const char *eeh_pcid_name(struct pci_dev *pdev) return ""; } +/** + * eeh_pcid_get - Get the PCI device driver + * @pdev: PCI device + * + * The function is used to retrieve the PCI device driver for + * the indicated PCI device. Besides, we will increase the reference + * of the PCI device driver to prevent that being unloaded on + * the fly. Otherwise, kernel crash would be seen. + */ +static inline struct pci_driver *eeh_pcid_get(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return NULL; + + if (!try_module_get(pdev->driver->driver.owner)) + return NULL; + + return pdev->driver; +} + +/** + * eeh_pcid_put - Dereference on the PCI device driver + * @pdev: PCI device + * + * The function is called to do dereference on the PCI device + * driver of the indicated PCI device. + */ +static inline void eeh_pcid_put(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return; + + module_put(pdev->driver->driver.owner); +} + #if 0 static void print_device_node_tree(struct pci_dn *pdn, int dent) { @@ -126,18 +162,20 @@ static void eeh_enable_irq(struct pci_dev *dev) static int eeh_report_error(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_frozen; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_disable_irq(dev); if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen); @@ -145,6 +183,7 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata) if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -160,12 +199,16 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata) static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; + + driver = eeh_pcid_get(dev); + if (!driver) return 0; - if (!driver || - !driver->err_handler || - !driver->err_handler->mmio_enabled) + if (!driver->err_handler || + !driver->err_handler->mmio_enabled) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->mmio_enabled(dev); @@ -173,6 +216,7 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -189,18 +233,20 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) static int eeh_report_reset(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; - - if (!driver) - return 0; + struct pci_driver *driver; dev->error_state = pci_channel_io_normal; + driver = eeh_pcid_get(dev); + if (!driver) return 0; + eeh_enable_irq(dev); if (!driver->err_handler || - !driver->err_handler->slot_reset) + !driver->err_handler->slot_reset) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->slot_reset(dev); if ((*res == PCI_ERS_RESULT_NONE) || @@ -208,6 +254,7 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata) if (*res == PCI_ERS_RESULT_DISCONNECT && rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -222,21 +269,24 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata) */ static int eeh_report_resume(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_normal; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_enable_irq(dev); if (!driver->err_handler || - !driver->err_handler->resume) + !driver->err_handler->resume) { + eeh_pcid_put(dev); return 0; + } driver->err_handler->resume(dev); + eeh_pcid_put(dev); return 0; } @@ -250,21 +300,24 @@ static int eeh_report_resume(struct pci_dev *dev, void *userdata) */ static int eeh_report_failure(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_perm_failure; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_disable_irq(dev); if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); + eeh_pcid_put(dev); return 0; } From 2087b40bec809ed98810ca80526ae092f58ac5d9 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Wed, 19 Sep 2012 14:43:33 +0800 Subject: [PATCH 0674/1071] mmc: sdhci-s3c: fix the wrong number of max bus clocks commit 5feb54a1ab91a237e247c013b8c4fb100ea347b1 upstream. We can use up to four bus-clocks; but on module remove, we didn't disable the fourth bus clock. Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci-s3c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index a50c205ea2085f..02b7a4aeeb9fa6 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -656,7 +656,7 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - for (ptr = 0; ptr < 3; ptr++) { + for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); From 8486cea66096dba0ba22bbfc49979aa13268bc43 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 22 Nov 2012 14:42:49 +1100 Subject: [PATCH 0675/1071] md/raid10: close race that lose writes lost when replacement completes. commit e7c0c3fa29280d62aa5e11101a674bb3064bd791 upstream. When a replacement operation completes there is a small window when the original device is marked 'faulty' and the replacement still looks like a replacement. The faulty should be removed and the replacement moved in place very quickly, bit it isn't instant. So the code write out to the array must handle the possibility that the only working device for some slot in the replacement - but it doesn't. If the primary device is faulty it just gives up. This can lead to corruption. So make the code more robust: if either the primary or the replacement is present and working, write to them. Only when neither are present do we give up. This bug has been present since replacement was introduced in 3.3, so it is suitable for any -stable kernel since then. Reported-by: "George Spelvin" Cc: stable@vger.kernel.org Signed-off-by: NeilBrown Signed-off-by: George Spelvin Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 110 +++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 3b636b874c9b13..c52d8936e86499 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1287,18 +1287,21 @@ static void make_request(struct mddev *mddev, struct bio * bio) blocked_rdev = rrdev; break; } + if (rdev && (test_bit(Faulty, &rdev->flags) + || test_bit(Unmerged, &rdev->flags))) + rdev = NULL; if (rrdev && (test_bit(Faulty, &rrdev->flags) || test_bit(Unmerged, &rrdev->flags))) rrdev = NULL; r10_bio->devs[i].bio = NULL; r10_bio->devs[i].repl_bio = NULL; - if (!rdev || test_bit(Faulty, &rdev->flags) || - test_bit(Unmerged, &rdev->flags)) { + + if (!rdev && !rrdev) { set_bit(R10BIO_Degraded, &r10_bio->state); continue; } - if (test_bit(WriteErrorSeen, &rdev->flags)) { + if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) { sector_t first_bad; sector_t dev_sector = r10_bio->devs[i].addr; int bad_sectors; @@ -1340,8 +1343,10 @@ static void make_request(struct mddev *mddev, struct bio * bio) max_sectors = good_sectors; } } - r10_bio->devs[i].bio = bio; - atomic_inc(&rdev->nr_pending); + if (rdev) { + r10_bio->devs[i].bio = bio; + atomic_inc(&rdev->nr_pending); + } if (rrdev) { r10_bio->devs[i].repl_bio = bio; atomic_inc(&rrdev->nr_pending); @@ -1397,58 +1402,57 @@ static void make_request(struct mddev *mddev, struct bio * bio) for (i = 0; i < conf->copies; i++) { struct bio *mbio; int d = r10_bio->devs[i].devnum; - if (!r10_bio->devs[i].bio) - continue; - - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].bio = mbio; - mbio->bi_sector = (r10_bio->devs[i].addr+ - choose_data_offset(r10_bio, - conf->mirrors[d].rdev)); - mbio->bi_bdev = conf->mirrors[d].rdev->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua; - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!mddev_check_plugged(mddev)) - md_wakeup_thread(mddev->thread); - - if (!r10_bio->devs[i].repl_bio) - continue; + if (r10_bio->devs[i].bio) { + struct md_rdev *rdev = conf->mirrors[d].rdev; + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr + + choose_data_offset(r10_bio, rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua; + mbio->bi_private = r10_bio; - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].repl_bio = mbio; + atomic_inc(&r10_bio->remaining); + spin_lock_irqsave(&conf->device_lock, flags); + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!mddev_check_plugged(mddev)) + md_wakeup_thread(mddev->thread); + } - /* We are actively writing to the original device - * so it cannot disappear, so the replacement cannot - * become NULL here - */ - mbio->bi_sector = (r10_bio->devs[i].addr + - choose_data_offset( - r10_bio, - conf->mirrors[d].replacement)); - mbio->bi_bdev = conf->mirrors[d].replacement->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua; - mbio->bi_private = r10_bio; + if (r10_bio->devs[i].repl_bio) { + struct md_rdev *rdev = conf->mirrors[d].replacement; + if (rdev == NULL) { + /* Replacement just got moved to main 'rdev' */ + smp_mb(); + rdev = conf->mirrors[d].rdev; + } + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].repl_bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr + + choose_data_offset(r10_bio, rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua; + mbio->bi_private = r10_bio; - atomic_inc(&r10_bio->remaining); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!mddev_check_plugged(mddev)) - md_wakeup_thread(mddev->thread); + atomic_inc(&r10_bio->remaining); + spin_lock_irqsave(&conf->device_lock, flags); + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!mddev_check_plugged(mddev)) + md_wakeup_thread(mddev->thread); + } } /* Don't remove the bias on 'remaining' (one_write_done) until From 072e44f15d6cfabe5b5f02c58ca7b058c03cc111 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 3 Dec 2012 11:39:49 -0800 Subject: [PATCH 0676/1071] Linux 3.6.9 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c5cc2f05256772..978af72b03219b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 6 -SUBLEVEL = 8 +SUBLEVEL = 9 EXTRAVERSION = NAME = Terrified Chipmunk From 68919cf996b530722dd7e61904d79c4c6aac17d9 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 7 Jun 2012 10:54:33 +0200 Subject: [PATCH 0677/1071] mmc: atmel-mci: remove not needed DMA capability test The test about DMA capability is not needed as it is performed in DMA-only functions: so remove it. Signed-off-by: Nicolas Ferre --- drivers/mmc/host/atmel-mci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index a53c7c478e054c..630b9bcffede85 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -774,9 +774,8 @@ static void atmci_dma_complete(void *arg) dev_vdbg(&host->pdev->dev, "DMA complete\n"); - if (host->caps.has_dma) - /* Disable DMA hardware handshaking on MCI */ - atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); + /* Disable DMA hardware handshaking on MCI */ + atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); atmci_dma_cleanup(host); From e94addf903b8e6bbaf4e1ce8a4159490420587f8 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 14 Mar 2012 12:46:18 +0100 Subject: [PATCH 0678/1071] ARM: at91/atmel-mci: remove unused setup_dma_addr() macro This macro is not used anymove in atmel-mci driver. It has been removed by a patch that was dealing with dw_dmac.c e2b35f3: (dmaengine/dw_dmac: Fix dw_dmac user drivers to adapt to slave_config changes) We are now using the dmaengine API to specify the slave DMA parameters: dmaengine_slave_config(). Signed-off-by: Nicolas Ferre Acked-by: Ludovic Desroches Cc: Chris Ball Cc: --- arch/arm/mach-at91/include/mach/atmel-mci.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h index 998cb0c0713564..5d84fe302ac691 100644 --- a/arch/arm/mach-at91/include/mach/atmel-mci.h +++ b/arch/arm/mach-at91/include/mach/atmel-mci.h @@ -14,11 +14,4 @@ struct mci_dma_data { #define slave_data_ptr(s) (&(s)->sdata) #define find_slave_dev(s) ((s)->sdata.dma_dev) -#define setup_dma_addr(s, t, r) do { \ - if (s) { \ - (s)->sdata.tx_reg = (t); \ - (s)->sdata.rx_reg = (r); \ - } \ -} while (0) - #endif /* __MACH_ATMEL_MCI_H */ From b4002177226a2a7c5055489a40206d1ffc0e68b7 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 6 Sep 2011 17:49:35 +0200 Subject: [PATCH 0679/1071] mmc: atmel-mci: support 8-bit buswidth This patch adds support for 8-bit buswidth. Relevant SDCR value modified. Derived from a patch by Jaehoon Chung on dw_mmc. Signed-off-by: Nicolas Ferre --- drivers/mmc/host/atmel-mci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 630b9bcffede85..68917dee3375f4 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1201,6 +1201,9 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_BUS_WIDTH_4: slot->sdc_reg |= ATMCI_SDCBUS_4BIT; break; + case MMC_BUS_WIDTH_8: + slot->sdc_reg |= ATMCI_SDCBUS_8BIT; + break; } if (ios->clock) { From 1252324656561b924dd5ad378ce4c2512c06a8b2 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 7 Sep 2012 14:54:25 +0800 Subject: [PATCH 0680/1071] usb: gadget: at91_udc: move the dereference below the NULL test The dereference should be moved below the NULL test. spatch with a semantic match is used to found this. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 660fd53e28a5f3..89d90b5fb78749 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -469,7 +469,7 @@ static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); - struct at91_udc *udc = ep->udc; + struct at91_udc *udc; u16 maxpacket; u32 tmp; unsigned long flags; @@ -483,6 +483,7 @@ static int at91_ep_enable(struct usb_ep *_ep, return -EINVAL; } + udc = ep->udc; if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) { DBG("bogus device state\n"); return -ESHUTDOWN; From ad1931ae394e603d49b90880b4027f71412acbc6 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 24 Oct 2012 18:31:50 +0200 Subject: [PATCH 0681/1071] ARM: at91: drop duplicated config SOC_AT91SAM9 entry Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index c8050b14e615ef..6eec0074d1f8f8 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -19,21 +19,15 @@ config AT91_SAM9G45_RESET config SOC_AT91SAM9 bool - select GENERIC_CLOCKEVENTS select CPU_ARM926T + select GENERIC_CLOCKEVENTS + select MULTI_IRQ_HANDLER + select SPARSE_IRQ menu "Atmel AT91 System-on-Chip" comment "Atmel AT91 Processor" -config SOC_AT91SAM9 - bool - select CPU_ARM926T - select MULTI_IRQ_HANDLER - select SPARSE_IRQ - select AT91_SAM9_TIME - select AT91_SAM9_SMC - config SOC_AT91RM9200 bool "AT91RM9200" select CPU_ARM920T From f9b75b0a6baefe25e66fe895ceccce4443cc7919 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 26 Oct 2012 22:49:09 +0200 Subject: [PATCH 0682/1071] ARM: at91: fix at91x40 build patch 738a0fd7 "ARM: at91: fix external interrupts in non-DT case" fixed a run-time error on some at91 platforms but did not apply the same change to at91x40, which now doesn't build. This changes at91x40 in the same way that the other platforms were changed. Signed-off-by: Arnd Bergmann Acked-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/mach-at91/at91x40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c index 46090e642d8eb0..efbb93fe4b6dfb 100644 --- a/arch/arm/mach-at91/at91x40.c +++ b/arch/arm/mach-at91/at91x40.c @@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS]) if (!priority) priority = at91x40_default_irq_priority; - at91_aic_init(priority); + at91_aic_init(priority, at91_extern_irq); } From aa7b21a112cdceb71aa547676aa9e7d593275b6f Mon Sep 17 00:00:00 2001 From: Nikolaus Voss Date: Tue, 8 Nov 2011 11:49:24 +0100 Subject: [PATCH 0683/1071] i2c: at91: remove old polling driver It will get replaced by a superior one. Safe to remove since this one depends on BROKEN anyhow. Signed-off-by: Nikolaus Voss Tested-by: Ludovic Desroches Reviewed-by: Nicolas Ferre [wsa: added commit message] Signed-off-by: Wolfram Sang --- arch/arm/mach-at91/include/mach/at91_twi.h | 68 ----- drivers/i2c/busses/Makefile | 1 - drivers/i2c/busses/i2c-at91.c | 315 --------------------- 3 files changed, 384 deletions(-) delete mode 100644 arch/arm/mach-at91/include/mach/at91_twi.h delete mode 100644 drivers/i2c/busses/i2c-at91.c diff --git a/arch/arm/mach-at91/include/mach/at91_twi.h b/arch/arm/mach-at91/include/mach/at91_twi.h deleted file mode 100644 index bb2880f6ba37d5..00000000000000 --- a/arch/arm/mach-at91/include/mach/at91_twi.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * arch/arm/mach-at91/include/mach/at91_twi.h - * - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) SAN People - * - * Two-wire Interface (TWI) registers. - * Based on AT91RM9200 datasheet revision E. - * - * 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. - */ - -#ifndef AT91_TWI_H -#define AT91_TWI_H - -#define AT91_TWI_CR 0x00 /* Control Register */ -#define AT91_TWI_START (1 << 0) /* Send a Start Condition */ -#define AT91_TWI_STOP (1 << 1) /* Send a Stop Condition */ -#define AT91_TWI_MSEN (1 << 2) /* Master Transfer Enable */ -#define AT91_TWI_MSDIS (1 << 3) /* Master Transfer Disable */ -#define AT91_TWI_SVEN (1 << 4) /* Slave Transfer Enable [SAM9260 only] */ -#define AT91_TWI_SVDIS (1 << 5) /* Slave Transfer Disable [SAM9260 only] */ -#define AT91_TWI_SWRST (1 << 7) /* Software Reset */ - -#define AT91_TWI_MMR 0x04 /* Master Mode Register */ -#define AT91_TWI_IADRSZ (3 << 8) /* Internal Device Address Size */ -#define AT91_TWI_IADRSZ_NO (0 << 8) -#define AT91_TWI_IADRSZ_1 (1 << 8) -#define AT91_TWI_IADRSZ_2 (2 << 8) -#define AT91_TWI_IADRSZ_3 (3 << 8) -#define AT91_TWI_MREAD (1 << 12) /* Master Read Direction */ -#define AT91_TWI_DADR (0x7f << 16) /* Device Address */ - -#define AT91_TWI_SMR 0x08 /* Slave Mode Register [SAM9260 only] */ -#define AT91_TWI_SADR (0x7f << 16) /* Slave Address */ - -#define AT91_TWI_IADR 0x0c /* Internal Address Register */ - -#define AT91_TWI_CWGR 0x10 /* Clock Waveform Generator Register */ -#define AT91_TWI_CLDIV (0xff << 0) /* Clock Low Divisor */ -#define AT91_TWI_CHDIV (0xff << 8) /* Clock High Divisor */ -#define AT91_TWI_CKDIV (7 << 16) /* Clock Divider */ - -#define AT91_TWI_SR 0x20 /* Status Register */ -#define AT91_TWI_TXCOMP (1 << 0) /* Transmission Complete */ -#define AT91_TWI_RXRDY (1 << 1) /* Receive Holding Register Ready */ -#define AT91_TWI_TXRDY (1 << 2) /* Transmit Holding Register Ready */ -#define AT91_TWI_SVREAD (1 << 3) /* Slave Read [SAM9260 only] */ -#define AT91_TWI_SVACC (1 << 4) /* Slave Access [SAM9260 only] */ -#define AT91_TWI_GACC (1 << 5) /* General Call Access [SAM9260 only] */ -#define AT91_TWI_OVRE (1 << 6) /* Overrun Error [AT91RM9200 only] */ -#define AT91_TWI_UNRE (1 << 7) /* Underrun Error [AT91RM9200 only] */ -#define AT91_TWI_NACK (1 << 8) /* Not Acknowledged */ -#define AT91_TWI_ARBLST (1 << 9) /* Arbitration Lost [SAM9260 only] */ -#define AT91_TWI_SCLWS (1 << 10) /* Clock Wait State [SAM9260 only] */ -#define AT91_TWI_EOSACC (1 << 11) /* End of Slave Address [SAM9260 only] */ - -#define AT91_TWI_IER 0x24 /* Interrupt Enable Register */ -#define AT91_TWI_IDR 0x28 /* Interrupt Disable Register */ -#define AT91_TWI_IMR 0x2c /* Interrupt Mask Register */ -#define AT91_TWI_RHR 0x30 /* Receive Holding Register */ -#define AT91_TWI_THR 0x34 /* Transmit Holding Register */ - -#endif - diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 37c4182cc98bb2..e9d93b095b7efa 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -28,7 +28,6 @@ obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o # Embedded system I2C/SMBus host controller drivers -obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c deleted file mode 100644 index e24484beef078d..00000000000000 --- a/drivers/i2c/busses/i2c-at91.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - i2c Support for Atmel's AT91 Two-Wire Interface (TWI) - - Copyright (C) 2004 Rick Bronson - Converted to 2.6 by Andrew Victor - - Borrowed heavily from original work by: - Copyright (C) 2000 Philip Edelbrock - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define TWI_CLOCK 100000 /* Hz. max 400 Kbits/sec */ - - -static struct clk *twi_clk; -static void __iomem *twi_base; - -#define at91_twi_read(reg) __raw_readl(twi_base + (reg)) -#define at91_twi_write(reg, val) __raw_writel((val), twi_base + (reg)) - - -/* - * Initialize the TWI hardware registers. - */ -static void __devinit at91_twi_hwinit(void) -{ - unsigned long cdiv, ckdiv; - - at91_twi_write(AT91_TWI_IDR, 0xffffffff); /* Disable all interrupts */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); /* Reset peripheral */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); /* Set Master mode */ - - /* Calcuate clock dividers */ - cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3; - cdiv = cdiv + 1; /* round up */ - ckdiv = 0; - while (cdiv > 255) { - ckdiv++; - cdiv = cdiv >> 1; - } - - if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */ - if (ckdiv > 5) { - printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n"); - ckdiv = 5; - } - } - - at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv); -} - -/* - * Poll the i2c status register until the specified bit is set. - * Returns 0 if timed out (100 msec). - */ -static short at91_poll_status(unsigned long bit) -{ - int loop_cntr = 10000; - - do { - udelay(10); - } while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0)); - - return (loop_cntr > 0); -} - -static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - /* Send Start */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_START); - - /* Read data */ - while (length--) { - if (!length) /* need to send Stop before reading last byte */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); - if (!at91_poll_status(AT91_TWI_RXRDY)) { - dev_dbg(&adap->dev, "RXRDY timeout\n"); - return -ETIMEDOUT; - } - *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff); - } - - return 0; -} - -static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - /* Load first byte into transmitter */ - at91_twi_write(AT91_TWI_THR, *buf++); - - /* Send Start */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_START); - - do { - if (!at91_poll_status(AT91_TWI_TXRDY)) { - dev_dbg(&adap->dev, "TXRDY timeout\n"); - return -ETIMEDOUT; - } - - length--; /* byte was transmitted */ - - if (length > 0) /* more data to send? */ - at91_twi_write(AT91_TWI_THR, *buf++); - } while (length); - - /* Send Stop */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); - - return 0; -} - -/* - * Generic i2c master transfer entrypoint. - * - * Note: We do not use Atmel's feature of storing the "internal device address". - * Instead the "internal device address" has to be written using a separate - * i2c message. - * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html - */ -static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num) -{ - int i, ret; - - dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); - - for (i = 0; i < num; i++) { - dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, - pmsg->flags & I2C_M_RD ? "read" : "writ", - pmsg->len, pmsg->len > 1 ? "s" : "", - pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); - - at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16) - | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0)); - - if (pmsg->len && pmsg->buf) { /* sanity check */ - if (pmsg->flags & I2C_M_RD) - ret = xfer_read(adap, pmsg->buf, pmsg->len); - else - ret = xfer_write(adap, pmsg->buf, pmsg->len); - - if (ret) - return ret; - - /* Wait until transfer is finished */ - if (!at91_poll_status(AT91_TWI_TXCOMP)) { - dev_dbg(&adap->dev, "TXCOMP timeout\n"); - return -ETIMEDOUT; - } - } - dev_dbg(&adap->dev, "transfer complete\n"); - pmsg++; /* next message */ - } - return i; -} - -/* - * Return list of supported functionality. - */ -static u32 at91_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm at91_algorithm = { - .master_xfer = at91_xfer, - .functionality = at91_func, -}; - -/* - * Main initialization routine. - */ -static int __devinit at91_i2c_probe(struct platform_device *pdev) -{ - struct i2c_adapter *adapter; - struct resource *res; - int rc; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - if (!request_mem_region(res->start, resource_size(res), "at91_i2c")) - return -EBUSY; - - twi_base = ioremap(res->start, resource_size(res)); - if (!twi_base) { - rc = -ENOMEM; - goto fail0; - } - - twi_clk = clk_get(NULL, "twi_clk"); - if (IS_ERR(twi_clk)) { - dev_err(&pdev->dev, "no clock defined\n"); - rc = -ENODEV; - goto fail1; - } - - adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (adapter == NULL) { - dev_err(&pdev->dev, "can't allocate inteface!\n"); - rc = -ENOMEM; - goto fail2; - } - snprintf(adapter->name, sizeof(adapter->name), "AT91"); - adapter->algo = &at91_algorithm; - adapter->class = I2C_CLASS_HWMON; - adapter->dev.parent = &pdev->dev; - /* adapter->id == 0 ... only one TWI controller for now */ - - platform_set_drvdata(pdev, adapter); - - clk_enable(twi_clk); /* enable peripheral clock */ - at91_twi_hwinit(); /* initialize TWI controller */ - - rc = i2c_add_numbered_adapter(adapter); - if (rc) { - dev_err(&pdev->dev, "Adapter %s registration failed\n", - adapter->name); - goto fail3; - } - - dev_info(&pdev->dev, "AT91 i2c bus driver.\n"); - return 0; - -fail3: - platform_set_drvdata(pdev, NULL); - kfree(adapter); - clk_disable(twi_clk); -fail2: - clk_put(twi_clk); -fail1: - iounmap(twi_base); -fail0: - release_mem_region(res->start, resource_size(res)); - - return rc; -} - -static int __devexit at91_i2c_remove(struct platform_device *pdev) -{ - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct resource *res; - int rc; - - rc = i2c_del_adapter(adapter); - platform_set_drvdata(pdev, NULL); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(twi_base); - release_mem_region(res->start, resource_size(res)); - - clk_disable(twi_clk); /* disable peripheral clock */ - clk_put(twi_clk); - - return rc; -} - -#ifdef CONFIG_PM - -/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */ - -static int at91_i2c_suspend(struct device *dev) -{ - clk_disable(twi_clk); - return 0; -} - -static int at91_i2c_resume(struct device *dev) -{ - return clk_enable(twi_clk); -} - -static SIMPLE_DEV_PM_OPS(at91_i2c_pm, at91_i2c_suspend, at91_i2c_resume); -#define AT91_I2C_PM (&at91_i2c_pm) - -#else -#define AT91_I2C_PM NULL -#endif - -static struct platform_driver at91_i2c_driver = { - .probe = at91_i2c_probe, - .remove = __devexit_p(at91_i2c_remove), - .driver = { - .name = "at91_i2c", - .owner = THIS_MODULE, - .pm = AT91_I2C_PM, - }, -}; - -module_platform_driver(at91_i2c_driver); - -MODULE_AUTHOR("Rick Bronson"); -MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:at91_i2c"); From f9adebb1f6f2946bccafeb3a17f6162c21b229e4 Mon Sep 17 00:00:00 2001 From: Nikolaus Voss Date: Tue, 8 Nov 2011 11:49:46 +0100 Subject: [PATCH 0684/1071] i2c: at91: add new driver This driver has the following properties compared to the old driver: 1. Support for multiple interfaces. 2. Interrupt driven I/O as opposed to polling/busy waiting. 3. Support for _one_ repeated start (Sr) condition, which is enough for most real-world applications including all SMBus transfer types. (The hardware does not support issuing arbitrary Sr conditions on the bus.) testing: SoC: at91sam9g45 - BQ20Z80 battery SMBus client. - on a 2.6.38 kernel with several i2c clients (temp-sensor, audio-codec, touchscreen-controller, w1-bridge, io-expanders) Signed-off-by: Nikolaus Voss Reviewed-by: Felipe Balbi Tested-by: Hubert Feurstein Tested-by: Ludovic Desroches Reviewed-by: Nicolas Ferre [wsa: squashed with the following patches from Ludovic to have some flaws fixed: i2c: at91: use managed resources i2c: at91: add warning about transmission issues for some devices i2c: at91: use an id table for SoC dependent parameters ] Signed-off-by: Ludovic Desroches Signed-off-by: Wolfram Sang --- arch/arm/mach-at91/at91rm9200.c | 1 + arch/arm/mach-at91/at91rm9200_devices.c | 2 +- arch/arm/mach-at91/at91sam9260.c | 2 + arch/arm/mach-at91/at91sam9260_devices.c | 8 +- arch/arm/mach-at91/at91sam9261.c | 2 + arch/arm/mach-at91/at91sam9261_devices.c | 8 +- arch/arm/mach-at91/at91sam9263.c | 1 + arch/arm/mach-at91/at91sam9263_devices.c | 2 +- arch/arm/mach-at91/at91sam9g45.c | 2 + arch/arm/mach-at91/at91sam9g45_devices.c | 4 +- arch/arm/mach-at91/at91sam9rl.c | 2 + arch/arm/mach-at91/at91sam9rl_devices.c | 2 +- drivers/i2c/busses/Kconfig | 17 +- drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-at91.c | 505 +++++++++++++++++++++++ 15 files changed, 545 insertions(+), 14 deletions(-) create mode 100644 drivers/i2c/busses/i2c-at91.c diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 6f50c6722276dc..b4f0565aff638a 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -187,6 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index d5a49132ef633e..884459c266ca51 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -495,7 +495,7 @@ static struct resource twi_resources[] = { }; static struct platform_device at91rm9200_twi_device = { - .name = "at91_i2c", + .name = "i2c-at91rm9200", .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 30c7f26a4668c3..5bd19a442365ec 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -211,6 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk), CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk), /* more usart lookup table for DT entries */ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck), CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk), diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 18ca240537e131..51a8356525f9ed 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -503,7 +503,6 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9260_twi_device = { - .name = "at91_i2c", .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), @@ -511,6 +510,13 @@ static struct platform_device at91sam9260_twi_device = { void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) { + /* IP version is not the same on 9260 and g20 */ + if (cpu_is_at91sam9g20()) { + at91sam9260_twi_device.name = "i2c-at91sam9g20"; + } else { + at91sam9260_twi_device.name = "i2c-at91sam9260"; + } + /* pins used for TWI interface */ at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */ at91_set_multi_drive(AT91_PIN_PA23, 1); diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index f40762c5fedee8..8d999eb1a137f1 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -178,6 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk), CLKDEV_CON_ID("pioA", &pioA_clk), CLKDEV_CON_ID("pioB", &pioB_clk), CLKDEV_CON_ID("pioC", &pioC_clk), diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 2495de8c32bf69..233b735d846bf1 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -317,7 +317,6 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9261_twi_device = { - .name = "at91_i2c", .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), @@ -325,6 +324,13 @@ static struct platform_device at91sam9261_twi_device = { void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) { + /* IP version is not the same on 9261 and g10 */ + if (cpu_is_at91sam9g10()) { + at91sam9261_twi_device.name = "i2c-at91sam9g10"; + } else { + at91sam9261_twi_device.name = "i2c-at91sam9261"; + } + /* pins used for TWI interface */ at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */ at91_set_multi_drive(AT91_PIN_PA7, 1); diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 84b38105231e91..e6b595658e758c 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -193,6 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 9877963c29e77c..68117a8d3a44d4 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -574,7 +574,7 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9263_twi_device = { - .name = "at91_i2c", + .name = "i2c-at91sam9260", .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index ef6cedd52e3c2e..858f032e510297 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -237,6 +237,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk), diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index bdbbbbcc66efd2..57f67387548d21 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -653,7 +653,7 @@ static struct resource twi0_resources[] = { }; static struct platform_device at91sam9g45_twi0_device = { - .name = "at91_i2c", + .name = "i2c-at91sam9g10", .id = 0, .resource = twi0_resources, .num_resources = ARRAY_SIZE(twi0_resources), @@ -673,7 +673,7 @@ static struct resource twi1_resources[] = { }; static struct platform_device at91sam9g45_twi1_device = { - .name = "at91_i2c", + .name = "i2c-at91sam9g10", .id = 1, .resource = twi1_resources, .num_resources = ARRAY_SIZE(twi1_resources), diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 72ce50a50de5a2..72e90841222261 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -186,6 +186,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk), CLKDEV_CON_ID("pioA", &pioA_clk), CLKDEV_CON_ID("pioB", &pioB_clk), CLKDEV_CON_ID("pioC", &pioC_clk), diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index c82a4276b1d5ac..68561e9960a97b 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -346,7 +346,7 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9rl_twi_device = { - .name = "at91_i2c", + .name = "i2c-at91sam9g20", .id = -1, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 970a1612e79556..150d40c0a21133 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -291,18 +291,21 @@ comment "I2C system bus drivers (mostly embedded / system-on-chip)" config I2C_AT91 tristate "Atmel AT91 I2C Two-Wire interface (TWI)" - depends on ARCH_AT91 && EXPERIMENTAL && BROKEN + depends on ARCH_AT91 && EXPERIMENTAL help This supports the use of the I2C interface on Atmel AT91 processors. - This driver is BROKEN because the controller which it uses - will easily trigger RX overrun and TX underrun errors. Using - low I2C clock rates may partially work around those issues - on some systems. Another serious problem is that there is no - documented way to issue repeated START conditions, as needed + A serious problem is that there is no documented way to issue + repeated START conditions for more than two messages, as needed to support combined I2C messages. Use the i2c-gpio driver - unless your system can cope with those limitations. + unless your system can cope with this limitation. + + Caution! at91rm9200, at91sam9261, at91sam9260, at91sam9263 devices + don't have clock stretching in transmission mode. For that reason, + you can encounter underrun issues causing premature stop sendings if + the latency to fill the transmission register is too long. If you + are facing this situation, use the i2c-gpio driver. config I2C_AU1550 tristate "Au1550/Au1200/Au1300 SMBus interface" diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index e9d93b095b7efa..37c4182cc98bb2 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o # Embedded system I2C/SMBus host controller drivers +obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c new file mode 100644 index 00000000000000..78bcad031d6a11 --- /dev/null +++ b/drivers/i2c/busses/i2c-at91.c @@ -0,0 +1,505 @@ +/* + * i2c Support for Atmel's AT91 Two-Wire Interface (TWI) + * + * Copyright (C) 2011 Weinmann Medical GmbH + * Author: Nikolaus Voss + * + * Evolved from original work by: + * Copyright (C) 2004 Rick Bronson + * Converted to 2.6 by Andrew Victor + * + * Borrowed heavily from original work by: + * Copyright (C) 2000 Philip Edelbrock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TWI_CLK_HZ 100000 /* max 400 Kbits/s */ +#define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ + +/* AT91 TWI register definitions */ +#define AT91_TWI_CR 0x0000 /* Control Register */ +#define AT91_TWI_START 0x0001 /* Send a Start Condition */ +#define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */ +#define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ +#define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ +#define AT91_TWI_SWRST 0x0080 /* Software Reset */ + +#define AT91_TWI_MMR 0x0004 /* Master Mode Register */ +#define AT91_TWI_IADRSZ_1 0x0100 /* Internal Device Address Size */ +#define AT91_TWI_MREAD 0x1000 /* Master Read Direction */ + +#define AT91_TWI_IADR 0x000c /* Internal Address Register */ + +#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */ + +#define AT91_TWI_SR 0x0020 /* Status Register */ +#define AT91_TWI_TXCOMP 0x0001 /* Transmission Complete */ +#define AT91_TWI_RXRDY 0x0002 /* Receive Holding Register Ready */ +#define AT91_TWI_TXRDY 0x0004 /* Transmit Holding Register Ready */ + +#define AT91_TWI_OVRE 0x0040 /* Overrun Error */ +#define AT91_TWI_UNRE 0x0080 /* Underrun Error */ +#define AT91_TWI_NACK 0x0100 /* Not Acknowledged */ + +#define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */ +#define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */ +#define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */ +#define AT91_TWI_RHR 0x0030 /* Receive Holding Register */ +#define AT91_TWI_THR 0x0034 /* Transmit Holding Register */ + +struct at91_twi_pdata { + unsigned clk_max_div; + unsigned clk_offset; + bool has_unre_flag; +}; + +struct at91_twi_dev { + struct device *dev; + void __iomem *base; + struct completion cmd_complete; + struct clk *clk; + u8 *buf; + size_t buf_len; + struct i2c_msg *msg; + int irq; + unsigned transfer_status; + struct i2c_adapter adapter; + unsigned twi_cwgr_reg; + struct at91_twi_pdata *pdata; +}; + +static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg) +{ + return readl_relaxed(dev->base + reg); +} + +static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val) +{ + writel_relaxed(val, dev->base + reg); +} + +static void at91_disable_twi_interrupts(struct at91_twi_dev *dev) +{ + at91_twi_write(dev, AT91_TWI_IDR, + AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); +} + +static void at91_init_twi_bus(struct at91_twi_dev *dev) +{ + at91_disable_twi_interrupts(dev); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS); + at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg); +} + +/* + * Calculate symmetric clock as stated in datasheet: + * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset)) + */ +static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk) +{ + int ckdiv, cdiv, div; + struct at91_twi_pdata *pdata = dev->pdata; + int offset = pdata->clk_offset; + int max_ckdiv = pdata->clk_max_div; + + div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk), + 2 * twi_clk) - offset); + ckdiv = fls(div >> 8); + cdiv = div >> ckdiv; + + if (ckdiv > max_ckdiv) { + dev_warn(dev->dev, "%d exceeds ckdiv max value which is %d.\n", + ckdiv, max_ckdiv); + ckdiv = max_ckdiv; + cdiv = 255; + } + + dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv; + dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv); +} + +static void at91_twi_write_next_byte(struct at91_twi_dev *dev) +{ + if (dev->buf_len <= 0) + return; + + at91_twi_write(dev, AT91_TWI_THR, *dev->buf); + + /* send stop when last byte has been written */ + if (--dev->buf_len == 0) + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); + + dev_dbg(dev->dev, "wrote 0x%x, to go %d\n", *dev->buf, dev->buf_len); + + ++dev->buf; +} + +static void at91_twi_read_next_byte(struct at91_twi_dev *dev) +{ + if (dev->buf_len <= 0) + return; + + *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff; + --dev->buf_len; + + /* handle I2C_SMBUS_BLOCK_DATA */ + if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) { + dev->msg->flags &= ~I2C_M_RECV_LEN; + dev->buf_len += *dev->buf; + dev->msg->len = dev->buf_len + 1; + dev_dbg(dev->dev, "received block length %d\n", dev->buf_len); + } + + /* send stop if second but last byte has been read */ + if (dev->buf_len == 1) + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); + + dev_dbg(dev->dev, "read 0x%x, to go %d\n", *dev->buf, dev->buf_len); + + ++dev->buf; +} + +static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) +{ + struct at91_twi_dev *dev = dev_id; + const unsigned status = at91_twi_read(dev, AT91_TWI_SR); + const unsigned irqstatus = status & at91_twi_read(dev, AT91_TWI_IMR); + + if (!irqstatus) + return IRQ_NONE; + else if (irqstatus & AT91_TWI_RXRDY) + at91_twi_read_next_byte(dev); + else if (irqstatus & AT91_TWI_TXRDY) + at91_twi_write_next_byte(dev); + + /* catch error flags */ + dev->transfer_status |= status; + + if (irqstatus & AT91_TWI_TXCOMP) { + at91_disable_twi_interrupts(dev); + complete(&dev->cmd_complete); + } + + return IRQ_HANDLED; +} + +static int at91_do_twi_transfer(struct at91_twi_dev *dev) +{ + int ret; + bool has_unre_flag = dev->pdata->has_unre_flag; + + dev_dbg(dev->dev, "transfer: %s %d bytes.\n", + (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len); + + INIT_COMPLETION(dev->cmd_complete); + dev->transfer_status = 0; + if (dev->msg->flags & I2C_M_RD) { + unsigned start_flags = AT91_TWI_START; + + if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) { + dev_err(dev->dev, "RXRDY still set!"); + at91_twi_read(dev, AT91_TWI_RHR); + } + + /* if only one byte is to be read, immediately stop transfer */ + if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN)) + start_flags |= AT91_TWI_STOP; + at91_twi_write(dev, AT91_TWI_CR, start_flags); + at91_twi_write(dev, AT91_TWI_IER, + AT91_TWI_TXCOMP | AT91_TWI_RXRDY); + } else { + at91_twi_write_next_byte(dev); + at91_twi_write(dev, AT91_TWI_IER, + AT91_TWI_TXCOMP | AT91_TWI_TXRDY); + } + + ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, + dev->adapter.timeout); + if (ret == 0) { + dev_err(dev->dev, "controller timed out\n"); + at91_init_twi_bus(dev); + return -ETIMEDOUT; + } + if (dev->transfer_status & AT91_TWI_NACK) { + dev_dbg(dev->dev, "received nack\n"); + return -EREMOTEIO; + } + if (dev->transfer_status & AT91_TWI_OVRE) { + dev_err(dev->dev, "overrun while reading\n"); + return -EIO; + } + if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) { + dev_err(dev->dev, "underrun while writing\n"); + return -EIO; + } + dev_dbg(dev->dev, "transfer complete\n"); + + return 0; +} + +static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) +{ + struct at91_twi_dev *dev = i2c_get_adapdata(adap); + int ret; + unsigned int_addr_flag = 0; + struct i2c_msg *m_start = msg; + + dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); + + /* + * The hardware can handle at most two messages concatenated by a + * repeated start via it's internal address feature. + */ + if (num > 2) { + dev_err(dev->dev, + "cannot handle more than two concatenated messages.\n"); + return 0; + } else if (num == 2) { + int internal_address = 0; + int i; + + if (msg->flags & I2C_M_RD) { + dev_err(dev->dev, "first transfer must be write.\n"); + return -EINVAL; + } + if (msg->len > 3) { + dev_err(dev->dev, "first message size must be <= 3.\n"); + return -EINVAL; + } + + /* 1st msg is put into the internal address, start with 2nd */ + m_start = &msg[1]; + for (i = 0; i < msg->len; ++i) { + const unsigned addr = msg->buf[msg->len - 1 - i]; + + internal_address |= addr << (8 * i); + int_addr_flag += AT91_TWI_IADRSZ_1; + } + at91_twi_write(dev, AT91_TWI_IADR, internal_address); + } + + at91_twi_write(dev, AT91_TWI_MMR, (m_start->addr << 16) | int_addr_flag + | ((m_start->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0)); + + dev->buf_len = m_start->len; + dev->buf = m_start->buf; + dev->msg = m_start; + + ret = at91_do_twi_transfer(dev); + + return (ret < 0) ? ret : num; +} + +static u32 at91_twi_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL + | I2C_FUNC_SMBUS_READ_BLOCK_DATA; +} + +static struct i2c_algorithm at91_twi_algorithm = { + .master_xfer = at91_twi_xfer, + .functionality = at91_twi_func, +}; + +static struct at91_twi_pdata at91rm9200_config = { + .clk_max_div = 5, + .clk_offset = 3, + .has_unre_flag = true, +}; + +static struct at91_twi_pdata at91sam9261_config = { + .clk_max_div = 5, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static struct at91_twi_pdata at91sam9260_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static struct at91_twi_pdata at91sam9g20_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static struct at91_twi_pdata at91sam9g10_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static const struct platform_device_id at91_twi_devtypes[] = { + { + .name = "i2c-at91rm9200", + .driver_data = (unsigned long) &at91rm9200_config, + }, { + .name = "i2c-at91sam9261", + .driver_data = (unsigned long) &at91sam9261_config, + }, { + .name = "i2c-at91sam9260", + .driver_data = (unsigned long) &at91sam9260_config, + }, { + .name = "i2c-at91sam9g20", + .driver_data = (unsigned long) &at91sam9g20_config, + }, { + .name = "i2c-at91sam9g10", + .driver_data = (unsigned long) &at91sam9g10_config, + }, { + /* sentinel */ + } +}; + +static int __devinit at91_twi_probe(struct platform_device *pdev) +{ + struct at91_twi_dev *dev; + struct resource *mem; + int rc; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + init_completion(&dev->cmd_complete); + dev->dev = &pdev->dev; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -ENODEV; + + dev->pdata = at91_twi_get_driver_data(pdev); + if (!dev->pdata) + return -ENODEV; + + dev->base = devm_request_and_ioremap(&pdev->dev, mem); + if (!dev->base) + return -EBUSY; + + dev->irq = platform_get_irq(pdev, 0); + if (dev->irq < 0) + return dev->irq; + + rc = devm_request_irq(&pdev->dev, dev->irq, atmel_twi_interrupt, 0, + dev_name(dev->dev), dev); + if (rc) { + dev_err(dev->dev, "Cannot get irq %d: %d\n", dev->irq, rc); + return rc; + } + + platform_set_drvdata(pdev, dev); + + dev->clk = devm_clk_get(dev->dev, NULL); + if (IS_ERR(dev->clk)) { + dev_err(dev->dev, "no clock defined\n"); + return -ENODEV; + } + clk_prepare_enable(dev->clk); + + at91_calc_twi_clock(dev, TWI_CLK_HZ); + at91_init_twi_bus(dev); + + snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91"); + i2c_set_adapdata(&dev->adapter, dev); + dev->adapter.owner = THIS_MODULE; + dev->adapter.class = I2C_CLASS_HWMON; + dev->adapter.algo = &at91_twi_algorithm; + dev->adapter.dev.parent = dev->dev; + dev->adapter.nr = pdev->id; + dev->adapter.timeout = AT91_I2C_TIMEOUT; + + rc = i2c_add_numbered_adapter(&dev->adapter); + if (rc) { + dev_err(dev->dev, "Adapter %s registration failed\n", + dev->adapter.name); + clk_disable_unprepare(dev->clk); + return rc; + } + + dev_info(dev->dev, "AT91 i2c bus driver.\n"); + return 0; +} + +static int __devexit at91_twi_remove(struct platform_device *pdev) +{ + struct at91_twi_dev *dev = platform_get_drvdata(pdev); + int rc; + + rc = i2c_del_adapter(&dev->adapter); + clk_disable_unprepare(dev->clk); + + return rc; +} + +#ifdef CONFIG_PM + +static int at91_twi_runtime_suspend(struct device *dev) +{ + struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); + + clk_disable(twi_dev->clk); + + return 0; +} + +static int at91_twi_runtime_resume(struct device *dev) +{ + struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); + + return clk_enable(twi_dev->clk); +} + +static const struct dev_pm_ops at91_twi_pm = { + .runtime_suspend = at91_twi_runtime_suspend, + .runtime_resume = at91_twi_runtime_resume, +}; + +#define at91_twi_pm_ops (&at91_twi_pm) +#else +#define at91_twi_pm_ops NULL +#endif + +static struct platform_driver at91_twi_driver = { + .probe = at91_twi_probe, + .remove = __devexit_p(at91_twi_remove), + .id_table = at91_twi_devtypes, + .driver = { + .name = "at91_i2c", + .owner = THIS_MODULE, + .pm = at91_twi_pm_ops, + }, +}; + +static int __init at91_twi_init(void) +{ + return platform_driver_register(&at91_twi_driver); +} + +static void __exit at91_twi_exit(void) +{ + platform_driver_unregister(&at91_twi_driver); +} + +subsys_initcall(at91_twi_init); +module_exit(at91_twi_exit); + +MODULE_AUTHOR("Nikolaus Voss "); +MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:at91_i2c"); From 91c484625f26c90545e652a33c2bddf63685c7e3 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 12 Sep 2012 08:42:14 +0200 Subject: [PATCH 0685/1071] i2c: at91: add dt support to i2c-at91 Signed-off-by: Ludovic Desroches Acked-by: Nikolaus Voss Acked-by: Nicolas Ferre Signed-off-by: Wolfram Sang --- .../devicetree/bindings/i2c/atmel-i2c.txt | 30 ++++++++++++ drivers/i2c/busses/i2c-at91.c | 49 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/atmel-i2c.txt diff --git a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt new file mode 100644 index 00000000000000..b689a0d9441c73 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt @@ -0,0 +1,30 @@ +I2C for Atmel platforms + +Required properties : +- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c", + "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c" + or "atmel,at91sam9x5-i2c" +- reg: physical base address of the controller and length of memory mapped + region. +- interrupts: interrupt number to the cpu. +- #address-cells = <1>; +- #size-cells = <0>; + +Optional properties: +- Child nodes conforming to i2c bus binding + +Examples : + +i2c0: i2c@fff84000 { + compatible = "atmel,at91sam9g20-i2c"; + reg = <0xfff84000 0x100>; + interrupts = <12 4 6>; + #address-cells = <1>; + #size-cells = <0>; + + 24c512@50 { + compatible = "24c512"; + reg = <0x50>; + pagesize = <128>; + } +} diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 78bcad031d6a11..aa59a254be2c3e 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include #include @@ -347,6 +350,12 @@ static struct at91_twi_pdata at91sam9g10_config = { .has_unre_flag = false, }; +static struct at91_twi_pdata at91sam9x5_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = false, +}; + static const struct platform_device_id at91_twi_devtypes[] = { { .name = "i2c-at91rm9200", @@ -368,6 +377,42 @@ static const struct platform_device_id at91_twi_devtypes[] = { } }; +#if defined(CONFIG_OF) +static const struct of_device_id atmel_twi_dt_ids[] = { + { + .compatible = "atmel,at91sam9260-i2c", + .data = &at91sam9260_config, + } , { + .compatible = "atmel,at91sam9g20-i2c", + .data = &at91sam9g20_config, + } , { + .compatible = "atmel,at91sam9g10-i2c", + .data = &at91sam9g10_config, + }, { + .compatible = "atmel,at91sam9x5-i2c", + .data = &at91sam9x5_config, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids); +#else +#define atmel_twi_dt_ids NULL +#endif + +static struct at91_twi_pdata * __devinit at91_twi_get_driver_data( + struct platform_device *pdev) +{ + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node); + if (!match) + return NULL; + return match->data; + } + return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data; +} + static int __devinit at91_twi_probe(struct platform_device *pdev) { struct at91_twi_dev *dev; @@ -423,6 +468,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev) dev->adapter.dev.parent = dev->dev; dev->adapter.nr = pdev->id; dev->adapter.timeout = AT91_I2C_TIMEOUT; + dev->adapter.dev.of_node = pdev->dev.of_node; rc = i2c_add_numbered_adapter(&dev->adapter); if (rc) { @@ -432,6 +478,8 @@ static int __devinit at91_twi_probe(struct platform_device *pdev) return rc; } + of_i2c_register_devices(&dev->adapter); + dev_info(dev->dev, "AT91 i2c bus driver.\n"); return 0; } @@ -482,6 +530,7 @@ static struct platform_driver at91_twi_driver = { .driver = { .name = "at91_i2c", .owner = THIS_MODULE, + .of_match_table = atmel_twi_dt_ids, .pm = at91_twi_pm_ops, }, }; From 1a04dd29f97d936355bf14a5430204e0f54272f0 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Fri, 9 Nov 2012 17:46:46 +0100 Subject: [PATCH 0686/1071] i2c: at91: fix SMBus quick command The driver claims to support SMBus quick command but it was not the case. This patch fixes this issue. Signed-off-by: Ludovic Desroches --- drivers/i2c/busses/i2c-at91.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index aa59a254be2c3e..c02bf208084f0a 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -39,6 +39,7 @@ #define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */ #define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ #define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ +#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */ #define AT91_TWI_SWRST 0x0080 /* Software Reset */ #define AT91_TWI_MMR 0x0004 /* Master Mode Register */ @@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) INIT_COMPLETION(dev->cmd_complete); dev->transfer_status = 0; - if (dev->msg->flags & I2C_M_RD) { + + if (!dev->buf_len) { + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK); + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else if (dev->msg->flags & I2C_M_RD) { unsigned start_flags = AT91_TWI_START; if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) { From 9741db478156b2ac4803aa012a82e7041c55cf5c Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 20 Mar 2012 18:41:48 +0100 Subject: [PATCH 0687/1071] mmc: atmel-mci: add device tree support Signed-off-by: Ludovic Desroches --- .../devicetree/bindings/mmc/atmel-hsmci.txt | 67 +++++++++++++++ drivers/mmc/host/atmel-mci.c | 85 ++++++++++++++++++- 2 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/atmel-hsmci.txt diff --git a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt new file mode 100644 index 00000000000000..81c20ccec728b3 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt @@ -0,0 +1,67 @@ +* Atmel High Speed MultiMedia Card Interface + +This controller on atmel products provides an interface for MMC, SD and SDIO +types of memory cards. + +1) MCI node + +Required properties: +- compatible: no blank "atmel,hsmci" +- reg: should contain HSMCI registers location and length +- interrupts: should contain HSMCI interrupt number +- #address-cells: should be one. The cell is the slot id. +- #size-cells: should be zero. +- at least one slot node + +The node contains child nodes for each slot that the platform uses + +Example MCI node: + +mmc0: mmc@f0008000 { + compatible = "atmel,hsmci"; + reg = <0xf0008000 0x600>; + interrupts = <12 4>; + #address-cells = <1>; + #size-cells = <0>; + + [ child node definitions...] +}; + +2) slot nodes + +Required properties: +- reg: should contain the slot id. +- bus-width: number of data lines connected to the controller + +Optional properties: +- cd-gpios: specify GPIOs for card detection +- cd-inverted: invert the value of external card detect gpio line +- wp-gpios: specify GPIOs for write protection + +Example slot node: + +slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 15 0> + cd-inverted; +}; + +Example full MCI node: +mmc0: mmc@f0008000 { + compatible = "atmel,hsmci"; + reg = <0xf0008000 0x600>; + interrupts = <12 4>; + #address-cells = <1>; + #size-cells = <0>; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 15 0> + cd-inverted; + }; + slot@1 { + reg = <1>; + bus-width = <4>; + }; +}; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 68917dee3375f4..a53602d7cb35c6 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -500,6 +503,70 @@ static void atmci_init_debugfs(struct atmel_mci_slot *slot) dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); } +#if defined(CONFIG_OF) +static const struct of_device_id atmci_dt_ids[] = { + { .compatible = "atmel,hsmci" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmci_dt_ids); + +static struct mci_platform_data __devinit* +atmci_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *cnp; + struct mci_platform_data *pdata; + u32 slot_id; + + if (!np) { + dev_err(&pdev->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, "could not allocate memory for pdata\n"); + return ERR_PTR(-ENOMEM); + } + + for_each_child_of_node(np, cnp) { + if (of_property_read_u32(cnp, "reg", &slot_id)) { + dev_warn(&pdev->dev, "reg property is missing for %s\n", + cnp->full_name); + continue; + } + + if (slot_id >= ATMCI_MAX_NR_SLOTS) { + dev_warn(&pdev->dev, "can't have more than %d slots\n", + ATMCI_MAX_NR_SLOTS); + break; + } + + if (of_property_read_u32(cnp, "bus-width", + &pdata->slot[slot_id].bus_width)) + pdata->slot[slot_id].bus_width = 1; + + pdata->slot[slot_id].detect_pin = + of_get_named_gpio(cnp, "cd-gpios", 0); + + pdata->slot[slot_id].detect_is_active_high = + of_property_read_bool(cnp, "cd-inverted"); + + pdata->slot[slot_id].wp_pin = + of_get_named_gpio(cnp, "wp-gpios", 0); + } + + return pdata; +} +#else /* CONFIG_OF */ +static inline struct mci_platform_data* +atmci_of_init(struct platform_device *dev) +{ + return ERR_PTR(-EINVAL); +} +#endif + static inline unsigned int atmci_get_version(struct atmel_mci *host) { return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; @@ -2048,6 +2115,13 @@ static int __init atmci_init_slot(struct atmel_mci *host, slot->sdc_reg = sdc_reg; slot->sdio_irq = sdio_irq; + dev_dbg(&mmc->class_dev, + "slot[%u]: bus_width=%u, detect_pin=%d, " + "detect_is_active_high=%s, wp_pin=%d\n", + id, slot_data->bus_width, slot_data->detect_pin, + slot_data->detect_is_active_high ? "true" : "false", + slot_data->wp_pin); + mmc->ops = &atmci_ops; mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); mmc->f_max = host->bus_hz / 2; @@ -2270,8 +2344,14 @@ static int __init atmci_probe(struct platform_device *pdev) if (!regs) return -ENXIO; pdata = pdev->dev.platform_data; - if (!pdata) - return -ENXIO; + if (!pdata) { + pdata = atmci_of_init(pdev); + if (IS_ERR(pdata)) { + dev_err(&pdev->dev, "platform data not available\n"); + return PTR_ERR(pdata); + } + } + irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -2489,6 +2569,7 @@ static struct platform_driver atmci_driver = { .driver = { .name = "atmel_mci", .pm = ATMCI_PM_OPS, + .of_match_table = of_match_ptr(atmci_dt_ids), }, }; From bd38e8165a92437cbe38b6a4f5f98b7f284ac561 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 20 Jun 2012 18:05:56 +0200 Subject: [PATCH 0688/1071] MMC: atmel-mci: add device tree property for configuration Configuration option is now handled by the "dma" device tree property that links to the corresponding DMA controller. Signed-off-by: Nicolas Ferre --- drivers/mmc/host/atmel-mci.c | 82 +++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index a53602d7cb35c6..a3f648290170f6 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -511,12 +511,65 @@ static const struct of_device_id atmci_dt_ids[] = { MODULE_DEVICE_TABLE(of, atmci_dt_ids); +static int atmci_dma_of_init(struct device_node *np, + struct at_dma_slave *atslave) +{ + struct of_phandle_args dma_spec; + struct device_node *dmac_np; + struct platform_device *dmac_pdev; + const __be32 *nbcells; + int ret; + + ret = of_parse_phandle_with_args(np, "dma", "#dma-cells", 0, &dma_spec); + if (ret || !dma_spec.np) { + pr_err("%s: can't parse dma property (%d)\n", np->full_name, ret); + goto err0; + } + dmac_np = dma_spec.np; + + /* check property format */ + nbcells = of_get_property(dmac_np, "#dma-cells", NULL); + if (!nbcells) { + pr_err("%s: #dma-cells property is required\n", np->full_name); + ret = -EINVAL; + goto err1; + } + + if (dma_spec.args_count != be32_to_cpup(nbcells) + || dma_spec.args_count != 1) { + pr_err("%s: wrong #dma-cells for %s\n", + np->full_name, dmac_np->full_name); + ret = -EINVAL; + goto err1; + } + + /* retreive DMA controller information */ + dmac_pdev = of_find_device_by_node(dmac_np); + if (!dmac_pdev) { + pr_err("%s: unable to find pdev from DMA controller\n", + dmac_np->full_name); + ret = -EINVAL; + goto err1; + } + + /* now fill in the at_dma_slave structure */ + atslave->dma_dev = &dmac_pdev->dev; + atslave->cfg = dma_spec.args[0]; + +err1: + of_node_put(dma_spec.np); +err0: + pr_debug("%s exited with status %d\n", __func__, ret); + return ret; +} + static struct mci_platform_data __devinit* atmci_of_init(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct device_node *cnp; struct mci_platform_data *pdata; + struct at_dma_slave *atslave; u32 slot_id; if (!np) { @@ -530,6 +583,24 @@ atmci_of_init(struct platform_device *pdev) return ERR_PTR(-ENOMEM); } + pdata->dma_slave = devm_kzalloc(&pdev->dev, + sizeof(*(pdata->dma_slave)), + GFP_KERNEL); + if (!pdata->dma_slave) { + dev_err(&pdev->dev, "could not allocate memory for dma_slave\n"); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-ENOMEM); + } + atslave = &pdata->dma_slave->sdata; + + /* retrive DMA configuration first */ + if (atmci_dma_of_init(np, atslave)) { + dev_err(&pdev->dev, "could not find DMA parameters\n"); + devm_kfree(&pdev->dev, pdata->dma_slave); + devm_kfree(&pdev->dev, pdata); + return ERR_PTR(-EINVAL); + } + for_each_child_of_node(np, cnp) { if (of_property_read_u32(cnp, "reg", &slot_id)) { dev_warn(&pdev->dev, "reg property is missing for %s\n", @@ -2236,16 +2307,13 @@ static bool atmci_filter(struct dma_chan *chan, void *slave) } } -static bool atmci_configure_dma(struct atmel_mci *host) +static bool atmci_configure_dma(struct atmel_mci *host, + struct mci_platform_data *pdata) { - struct mci_platform_data *pdata; - if (host == NULL) return false; - pdata = host->pdev->dev.platform_data; - - if (pdata && find_slave_dev(pdata->dma_slave)) { + if (pdata && pdata->dma_slave && find_slave_dev(pdata->dma_slave)) { dma_cap_mask_t mask; /* Try to grab a DMA channel */ @@ -2390,7 +2458,7 @@ static int __init atmci_probe(struct platform_device *pdev) /* Get MCI capabilities and set operations according to it */ atmci_get_cap(host); - if (host->caps.has_dma && atmci_configure_dma(host)) { + if (host->caps.has_dma && atmci_configure_dma(host, pdata)) { host->prepare_data = &atmci_prepare_data_dma; host->submit_data = &atmci_submit_data_dma; host->stop_transfer = &atmci_stop_transfer_dma; From f69a533da1125249e309608209a309862db35cac Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Thu, 31 May 2012 18:09:20 +0800 Subject: [PATCH 0689/1071] MTD: at91: extract hw ecc initialization to one function This patch moves hw ecc initialization code to one function. Signed-off-by: Hong Xu Signed-off-by: Josh Wu --- drivers/mtd/nand/atmel_nand.c | 127 ++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 61 deletions(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 97ac6712bb1926..7a41a04beb8728 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -527,6 +527,66 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host, } #endif +static int __init atmel_hw_nand_init_params(struct platform_device *pdev, + struct atmel_nand_host *host) +{ + struct mtd_info *mtd = &host->mtd; + struct nand_chip *nand_chip = &host->nand_chip; + struct resource *regs; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!regs) { + dev_err(host->dev, + "Can't get I/O resource regs, use software ECC\n"); + nand_chip->ecc.mode = NAND_ECC_SOFT; + return 0; + } + + host->ecc = ioremap(regs->start, resource_size(regs)); + if (host->ecc == NULL) { + dev_err(host->dev, "ioremap failed\n"); + return -EIO; + } + + /* ECC is calculated for the whole page (1 step) */ + nand_chip->ecc.size = mtd->writesize; + + /* set ECC page size and oob layout */ + switch (mtd->writesize) { + case 512: + nand_chip->ecc.layout = &atmel_oobinfo_small; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528); + break; + case 1024: + nand_chip->ecc.layout = &atmel_oobinfo_large; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056); + break; + case 2048: + nand_chip->ecc.layout = &atmel_oobinfo_large; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112); + break; + case 4096: + nand_chip->ecc.layout = &atmel_oobinfo_large; + ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224); + break; + default: + /* page size not handled by HW ECC */ + /* switching back to soft ECC */ + nand_chip->ecc.mode = NAND_ECC_SOFT; + return 0; + } + + /* set up for HW ECC */ + nand_chip->ecc.calculate = atmel_nand_calculate; + nand_chip->ecc.correct = atmel_nand_correct; + nand_chip->ecc.hwctl = atmel_nand_hwctl; + nand_chip->ecc.read_page = atmel_nand_read_page; + nand_chip->ecc.bytes = 4; + nand_chip->ecc.strength = 1; + + return 0; +} + /* * Probe for the NAND device. */ @@ -535,7 +595,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev) struct atmel_nand_host *host; struct mtd_info *mtd; struct nand_chip *nand_chip; - struct resource *regs; struct resource *mem; struct mtd_part_parser_data ppdata = {}; int res; @@ -587,29 +646,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->dev_ready = atmel_nand_device_ready; nand_chip->ecc.mode = host->board.ecc_mode; - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) { - printk(KERN_ERR "atmel_nand: can't get I/O resource " - "regs\nFalling back on software ECC\n"); - nand_chip->ecc.mode = NAND_ECC_SOFT; - } - - if (nand_chip->ecc.mode == NAND_ECC_HW) { - host->ecc = ioremap(regs->start, resource_size(regs)); - if (host->ecc == NULL) { - printk(KERN_ERR "atmel_nand: ioremap failed\n"); - res = -EIO; - goto err_ecc_ioremap; - } - nand_chip->ecc.calculate = atmel_nand_calculate; - nand_chip->ecc.correct = atmel_nand_correct; - nand_chip->ecc.hwctl = atmel_nand_hwctl; - nand_chip->ecc.read_page = atmel_nand_read_page; - nand_chip->ecc.bytes = 4; - nand_chip->ecc.strength = 1; - } - nand_chip->chip_delay = 20; /* 20us command delay time */ if (host->board.bus_width_16) /* 16-bit bus width */ @@ -661,40 +697,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev) } if (nand_chip->ecc.mode == NAND_ECC_HW) { - /* ECC is calculated for the whole page (1 step) */ - nand_chip->ecc.size = mtd->writesize; - - /* set ECC page size and oob layout */ - switch (mtd->writesize) { - case 512: - nand_chip->ecc.layout = &atmel_oobinfo_small; - ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528); - break; - case 1024: - nand_chip->ecc.layout = &atmel_oobinfo_large; - ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056); - break; - case 2048: - nand_chip->ecc.layout = &atmel_oobinfo_large; - ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112); - break; - case 4096: - nand_chip->ecc.layout = &atmel_oobinfo_large; - ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224); - break; - default: - /* page size not handled by HW ECC */ - /* switching back to soft ECC */ - nand_chip->ecc.mode = NAND_ECC_SOFT; - nand_chip->ecc.calculate = NULL; - nand_chip->ecc.correct = NULL; - nand_chip->ecc.hwctl = NULL; - nand_chip->ecc.read_page = NULL; - nand_chip->ecc.postpad = 0; - nand_chip->ecc.prepad = 0; - nand_chip->ecc.bytes = 0; - break; - } + res = atmel_hw_nand_init_params(pdev, host); + if (res != 0) + goto err_hw_ecc; } /* second phase scan */ @@ -711,15 +716,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) return res; err_scan_tail: + if (host->ecc) + iounmap(host->ecc); +err_hw_ecc: err_scan_ident: err_no_card: atmel_nand_disable(host); platform_set_drvdata(pdev, NULL); if (host->dma_chan) dma_release_channel(host->dma_chan); - if (host->ecc) - iounmap(host->ecc); -err_ecc_ioremap: iounmap(host->io_base); err_nand_ioremap: kfree(host); From a7f57777403b55cacf34c7c5a9767629e58581e4 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Tue, 26 Jun 2012 17:42:22 +0800 Subject: [PATCH 0690/1071] MTD: at91: add dt parameters for Atmel PMECC Add DT support for PMECC parameters. Signed-off-by: Hong Xu Signed-off-by: Josh Wu Acked-by: Nicolas Ferre --- .../devicetree/bindings/mtd/atmel-nand.txt | 40 +++++++++++++- drivers/mtd/nand/atmel_nand.c | 52 ++++++++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt index a20069502f5aae..d555421ea49f82 100644 --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt @@ -3,7 +3,9 @@ Atmel NAND flash Required properties: - compatible : "atmel,at91rm9200-nand". - reg : should specify localbus address and size used for the chip, - and if availlable the ECC. + and hardware ECC controller if available. + If the hardware ECC is PMECC, it should contain address and size for + PMECC, PMECC Error Location controller and ROM which has lookup tables. - atmel,nand-addr-offset : offset for the address latch. - atmel,nand-cmd-offset : offset for the command latch. - #address-cells, #size-cells : Must be present if the device has sub-nodes @@ -16,6 +18,15 @@ Optional properties: - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default. Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", "soft_bch". +- atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware. + Only supported by at91sam9x5 or later sam9 product. +- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC + Controller. Supported values are: 2, 4, 8, 12, 24. +- atmel,pmecc-sector-size : sector size for ECC computation. Supported values + are: 512, 1024. +- atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM + for different sector size. First one is for sector size 512, the next is for + sector size 1024. - nand-bus-width : 8 or 16 bus width if not present 8 - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false @@ -39,3 +50,30 @@ nand0: nand@40000000,0 { ... }; }; + +/* for PMECC supported chips */ +nand0: nand@40000000 { + compatible = "atmel,at91rm9200-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = < 0x40000000 0x10000000 /* bus addr & size */ + 0xffffe000 0x00000600 /* PMECC addr & size */ + 0xffffe600 0x00000200 /* PMECC ERRLOC addr & size */ + 0x00100000 0x00100000 /* ROM addr & size */ + >; + atmel,nand-addr-offset = <21>; /* ale */ + atmel,nand-cmd-offset = <22>; /* cle */ + nand-on-flash-bbt; + nand-ecc-mode = "hw"; + atmel,has-pmecc; /* enable PMECC */ + atmel,pmecc-cap = <2>; + atmel,pmecc-sector-size = <512>; + atmel,pmecc-lookup-table-offset = <0x8000 0x10000>; + gpios = <&pioD 5 0 /* rdy */ + &pioD 4 0 /* nce */ + 0 /* cd */ + >; + partition@0 { + ... + }; +}; diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 7a41a04beb8728..b97ad9f78d3971 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -93,6 +93,11 @@ struct atmel_nand_host { struct completion comp; struct dma_chan *dma_chan; + + bool has_pmecc; + u8 pmecc_corr_cap; + u16 pmecc_sector_size; + u32 pmecc_lookup_table_offset; }; static int cpu_has_dma(void) @@ -481,7 +486,8 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) static int __devinit atmel_of_init_port(struct atmel_nand_host *host, struct device_node *np) { - u32 val; + u32 val, table_offset; + u32 offset[2]; int ecc_mode; struct atmel_nand_data *board = &host->board; enum of_gpio_flags flags; @@ -517,6 +523,50 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host, board->enable_pin = of_get_gpio(np, 1); board->det_pin = of_get_gpio(np, 2); + host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); + + if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc) + return 0; /* Not using PMECC */ + + /* use PMECC, get correction capability, sector size and lookup + * table offset. + */ + if (of_property_read_u32(np, "atmel,pmecc-cap", &val) != 0) { + dev_err(host->dev, "Cannot decide PMECC Capability\n"); + return -EINVAL; + } else if ((val != 2) && (val != 4) && (val != 8) && (val != 12) && + (val != 24)) { + dev_err(host->dev, + "Unsupported PMECC correction capability: %d; should be 2, 4, 8, 12 or 24\n", + val); + return -EINVAL; + } + host->pmecc_corr_cap = (u8)val; + + if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) != 0) { + dev_err(host->dev, "Cannot decide PMECC Sector Size\n"); + return -EINVAL; + } else if ((val != 512) && (val != 1024)) { + dev_err(host->dev, + "Unsupported PMECC sector size: %d; should be 512 or 1024 bytes\n", + val); + return -EINVAL; + } + host->pmecc_sector_size = (u16)val; + + if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset", + offset, 2) != 0) { + dev_err(host->dev, "Cannot get PMECC lookup table offset\n"); + return -EINVAL; + } + table_offset = host->pmecc_sector_size == 512 ? offset[0] : offset[1]; + + if (!table_offset) { + dev_err(host->dev, "Invalid PMECC lookup table offset\n"); + return -EINVAL; + } + host->pmecc_lookup_table_offset = table_offset; + return 0; } #else From 8b1a74bc4fa2c25952167c0900d7525ac4a8d452 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Fri, 29 Jun 2012 15:29:21 +0800 Subject: [PATCH 0691/1071] MTD: at91: atmel_nand: Update driver to support Programmable Multibit ECC controller The Programmable Multibit ECC (PMECC) controller is a programmable binary BCH(Bose, Chaudhuri and Hocquenghem) encoder and decoder. This controller can be used to support both SLC and MLC NAND Flash devices. It supports to generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector of data. To use PMECC in this driver, the user needs to set the address and size of PMECC, PMECC error location controllers and ROM. And also needs to pass the correction capability, the sector size and ROM lookup table offsets via dt. This driver has been tested on AT91SAM9X5-EK and AT91SAM9N12-EK with JFFS2, YAFFS2, UBIFS and mtd-utils. Signed-off-by: Hong Xu Signed-off-by: Josh Wu Tested-by: Richard Genoud Acked-by: Nicolas Ferre --- drivers/mtd/nand/atmel_nand.c | 747 +++++++++++++++++++++++++++++- drivers/mtd/nand/atmel_nand_ecc.h | 114 ++++- 2 files changed, 859 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index b97ad9f78d3971..000d710954b5a6 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -15,6 +15,8 @@ * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c) * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas * + * Add Programmable Multibit ECC support for various AT91 SoC + * (C) Copyright 2012 ATMEL, Hong Xu * * 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 @@ -98,8 +100,31 @@ struct atmel_nand_host { u8 pmecc_corr_cap; u16 pmecc_sector_size; u32 pmecc_lookup_table_offset; + + int pmecc_bytes_per_sector; + int pmecc_sector_number; + int pmecc_degree; /* Degree of remainders */ + int pmecc_cw_len; /* Length of codeword */ + + void __iomem *pmerrloc_base; + void __iomem *pmecc_rom_base; + + /* lookup table for alpha_to and index_of */ + void __iomem *pmecc_alpha_to; + void __iomem *pmecc_index_of; + + /* data for pmecc computation */ + int16_t *pmecc_partial_syn; + int16_t *pmecc_si; + int16_t *pmecc_smu; /* Sigma table */ + int16_t *pmecc_lmu; /* polynomal order */ + int *pmecc_mu; + int *pmecc_dmu; + int *pmecc_delta; }; +static struct nand_ecclayout atmel_pmecc_oobinfo; + static int cpu_has_dma(void) { return cpu_is_at91sam9rl() || cpu_is_at91sam9g45(); @@ -292,6 +317,703 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) atmel_write_buf8(mtd, buf, len); } +/* + * Return number of ecc bytes per sector according to sector size and + * correction capability + * + * Following table shows what at91 PMECC supported: + * Correction Capability Sector_512_bytes Sector_1024_bytes + * ===================== ================ ================= + * 2-bits 4-bytes 4-bytes + * 4-bits 7-bytes 7-bytes + * 8-bits 13-bytes 14-bytes + * 12-bits 20-bytes 21-bytes + * 24-bits 39-bytes 42-bytes + */ +static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size) +{ + int m = 12 + sector_size / 512; + return (m * cap + 7) / 8; +} + +static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, + int oobsize, int ecc_len) +{ + int i; + + layout->eccbytes = ecc_len; + + /* ECC will occupy the last ecc_len bytes continuously */ + for (i = 0; i < ecc_len; i++) + layout->eccpos[i] = oobsize - ecc_len + i; + + layout->oobfree[0].offset = 2; + layout->oobfree[0].length = + oobsize - ecc_len - layout->oobfree[0].offset; +} + +static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) +{ + int table_size; + + table_size = host->pmecc_sector_size == 512 ? + PMECC_LOOKUP_TABLE_SIZE_512 : PMECC_LOOKUP_TABLE_SIZE_1024; + + return host->pmecc_rom_base + host->pmecc_lookup_table_offset + + table_size * sizeof(int16_t); +} + +static void pmecc_data_free(struct atmel_nand_host *host) +{ + kfree(host->pmecc_partial_syn); + kfree(host->pmecc_si); + kfree(host->pmecc_lmu); + kfree(host->pmecc_smu); + kfree(host->pmecc_mu); + kfree(host->pmecc_dmu); + kfree(host->pmecc_delta); +} + +static int __devinit pmecc_data_alloc(struct atmel_nand_host *host) +{ + const int cap = host->pmecc_corr_cap; + + host->pmecc_partial_syn = kzalloc((2 * cap + 1) * sizeof(int16_t), + GFP_KERNEL); + host->pmecc_si = kzalloc((2 * cap + 1) * sizeof(int16_t), GFP_KERNEL); + host->pmecc_lmu = kzalloc((cap + 1) * sizeof(int16_t), GFP_KERNEL); + host->pmecc_smu = kzalloc((cap + 2) * (2 * cap + 1) * sizeof(int16_t), + GFP_KERNEL); + host->pmecc_mu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); + host->pmecc_dmu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); + host->pmecc_delta = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); + + if (host->pmecc_partial_syn && + host->pmecc_si && + host->pmecc_lmu && + host->pmecc_smu && + host->pmecc_mu && + host->pmecc_dmu && + host->pmecc_delta) + return 0; + + /* error happened */ + pmecc_data_free(host); + return -ENOMEM; +} + +static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) +{ + struct nand_chip *nand_chip = mtd->priv; + struct atmel_nand_host *host = nand_chip->priv; + int i; + uint32_t value; + + /* Fill odd syndromes */ + for (i = 0; i < host->pmecc_corr_cap; i++) { + value = pmecc_readl_rem_relaxed(host->ecc, sector, i / 2); + if (i & 1) + value >>= 16; + value &= 0xffff; + host->pmecc_partial_syn[(2 * i) + 1] = (int16_t)value; + } +} + +static void pmecc_substitute(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = mtd->priv; + struct atmel_nand_host *host = nand_chip->priv; + int16_t __iomem *alpha_to = host->pmecc_alpha_to; + int16_t __iomem *index_of = host->pmecc_index_of; + int16_t *partial_syn = host->pmecc_partial_syn; + const int cap = host->pmecc_corr_cap; + int16_t *si; + int i, j; + + /* si[] is a table that holds the current syndrome value, + * an element of that table belongs to the field + */ + si = host->pmecc_si; + + memset(&si[1], 0, sizeof(int16_t) * (2 * cap - 1)); + + /* Computation 2t syndromes based on S(x) */ + /* Odd syndromes */ + for (i = 1; i < 2 * cap; i += 2) { + for (j = 0; j < host->pmecc_degree; j++) { + if (partial_syn[i] & ((unsigned short)0x1 << j)) + si[i] = readw_relaxed(alpha_to + i * j) ^ si[i]; + } + } + /* Even syndrome = (Odd syndrome) ** 2 */ + for (i = 2, j = 1; j <= cap; i = ++j << 1) { + if (si[j] == 0) { + si[i] = 0; + } else { + int16_t tmp; + + tmp = readw_relaxed(index_of + si[j]); + tmp = (tmp * 2) % host->pmecc_cw_len; + si[i] = readw_relaxed(alpha_to + tmp); + } + } + + return; +} + +static void pmecc_get_sigma(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = mtd->priv; + struct atmel_nand_host *host = nand_chip->priv; + + int16_t *lmu = host->pmecc_lmu; + int16_t *si = host->pmecc_si; + int *mu = host->pmecc_mu; + int *dmu = host->pmecc_dmu; /* Discrepancy */ + int *delta = host->pmecc_delta; /* Delta order */ + int cw_len = host->pmecc_cw_len; + const int16_t cap = host->pmecc_corr_cap; + const int num = 2 * cap + 1; + int16_t __iomem *index_of = host->pmecc_index_of; + int16_t __iomem *alpha_to = host->pmecc_alpha_to; + int i, j, k; + uint32_t dmu_0_count, tmp; + int16_t *smu = host->pmecc_smu; + + /* index of largest delta */ + int ro; + int largest; + int diff; + + dmu_0_count = 0; + + /* First Row */ + + /* Mu */ + mu[0] = -1; + + memset(smu, 0, sizeof(int16_t) * num); + smu[0] = 1; + + /* discrepancy set to 1 */ + dmu[0] = 1; + /* polynom order set to 0 */ + lmu[0] = 0; + delta[0] = (mu[0] * 2 - lmu[0]) >> 1; + + /* Second Row */ + + /* Mu */ + mu[1] = 0; + /* Sigma(x) set to 1 */ + memset(&smu[num], 0, sizeof(int16_t) * num); + smu[num] = 1; + + /* discrepancy set to S1 */ + dmu[1] = si[1]; + + /* polynom order set to 0 */ + lmu[1] = 0; + + delta[1] = (mu[1] * 2 - lmu[1]) >> 1; + + /* Init the Sigma(x) last row */ + memset(&smu[(cap + 1) * num], 0, sizeof(int16_t) * num); + + for (i = 1; i <= cap; i++) { + mu[i + 1] = i << 1; + /* Begin Computing Sigma (Mu+1) and L(mu) */ + /* check if discrepancy is set to 0 */ + if (dmu[i] == 0) { + dmu_0_count++; + + tmp = ((cap - (lmu[i] >> 1) - 1) / 2); + if ((cap - (lmu[i] >> 1) - 1) & 0x1) + tmp += 2; + else + tmp += 1; + + if (dmu_0_count == tmp) { + for (j = 0; j <= (lmu[i] >> 1) + 1; j++) + smu[(cap + 1) * num + j] = + smu[i * num + j]; + + lmu[cap + 1] = lmu[i]; + return; + } + + /* copy polynom */ + for (j = 0; j <= lmu[i] >> 1; j++) + smu[(i + 1) * num + j] = smu[i * num + j]; + + /* copy previous polynom order to the next */ + lmu[i + 1] = lmu[i]; + } else { + ro = 0; + largest = -1; + /* find largest delta with dmu != 0 */ + for (j = 0; j < i; j++) { + if ((dmu[j]) && (delta[j] > largest)) { + largest = delta[j]; + ro = j; + } + } + + /* compute difference */ + diff = (mu[i] - mu[ro]); + + /* Compute degree of the new smu polynomial */ + if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff)) + lmu[i + 1] = lmu[i]; + else + lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2; + + /* Init smu[i+1] with 0 */ + for (k = 0; k < num; k++) + smu[(i + 1) * num + k] = 0; + + /* Compute smu[i+1] */ + for (k = 0; k <= lmu[ro] >> 1; k++) { + int16_t a, b, c; + + if (!(smu[ro * num + k] && dmu[i])) + continue; + a = readw_relaxed(index_of + dmu[i]); + b = readw_relaxed(index_of + dmu[ro]); + c = readw_relaxed(index_of + smu[ro * num + k]); + tmp = a + (cw_len - b) + c; + a = readw_relaxed(alpha_to + tmp % cw_len); + smu[(i + 1) * num + (k + diff)] = a; + } + + for (k = 0; k <= lmu[i] >> 1; k++) + smu[(i + 1) * num + k] ^= smu[i * num + k]; + } + + /* End Computing Sigma (Mu+1) and L(mu) */ + /* In either case compute delta */ + delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1; + + /* Do not compute discrepancy for the last iteration */ + if (i >= cap) + continue; + + for (k = 0; k <= (lmu[i + 1] >> 1); k++) { + tmp = 2 * (i - 1); + if (k == 0) { + dmu[i + 1] = si[tmp + 3]; + } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) { + int16_t a, b, c; + a = readw_relaxed(index_of + + smu[(i + 1) * num + k]); + b = si[2 * (i - 1) + 3 - k]; + c = readw_relaxed(index_of + b); + tmp = a + c; + tmp %= cw_len; + dmu[i + 1] = readw_relaxed(alpha_to + tmp) ^ + dmu[i + 1]; + } + } + } + + return; +} + +static int pmecc_err_location(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = mtd->priv; + struct atmel_nand_host *host = nand_chip->priv; + unsigned long end_time; + const int cap = host->pmecc_corr_cap; + const int num = 2 * cap + 1; + int sector_size = host->pmecc_sector_size; + int err_nbr = 0; /* number of error */ + int roots_nbr; /* number of roots */ + int i; + uint32_t val; + int16_t *smu = host->pmecc_smu; + + pmerrloc_writel(host->pmerrloc_base, ELDIS, PMERRLOC_DISABLE); + + for (i = 0; i <= host->pmecc_lmu[cap + 1] >> 1; i++) { + pmerrloc_writel_sigma_relaxed(host->pmerrloc_base, i, + smu[(cap + 1) * num + i]); + err_nbr++; + } + + val = (err_nbr - 1) << 16; + if (sector_size == 1024) + val |= 1; + + pmerrloc_writel(host->pmerrloc_base, ELCFG, val); + pmerrloc_writel(host->pmerrloc_base, ELEN, + sector_size * 8 + host->pmecc_degree * cap); + + end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); + while (!(pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR) + & PMERRLOC_CALC_DONE)) { + if (unlikely(time_after(jiffies, end_time))) { + dev_err(host->dev, "PMECC: Timeout to calculate error location.\n"); + return -1; + } + cpu_relax(); + } + + roots_nbr = (pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR) + & PMERRLOC_ERR_NUM_MASK) >> 8; + /* Number of roots == degree of smu hence <= cap */ + if (roots_nbr == host->pmecc_lmu[cap + 1] >> 1) + return err_nbr - 1; + + /* Number of roots does not match the degree of smu + * unable to correct error */ + return -1; +} + +static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, + int sector_num, int extra_bytes, int err_nbr) +{ + struct nand_chip *nand_chip = mtd->priv; + struct atmel_nand_host *host = nand_chip->priv; + int i = 0; + int byte_pos, bit_pos, sector_size, pos; + uint32_t tmp; + uint8_t err_byte; + + sector_size = host->pmecc_sector_size; + + while (err_nbr) { + tmp = pmerrloc_readl_el_relaxed(host->pmerrloc_base, i) - 1; + byte_pos = tmp / 8; + bit_pos = tmp % 8; + + if (byte_pos >= (sector_size + extra_bytes)) + BUG(); /* should never happen */ + + if (byte_pos < sector_size) { + err_byte = *(buf + byte_pos); + *(buf + byte_pos) ^= (1 << bit_pos); + + pos = sector_num * host->pmecc_sector_size + byte_pos; + dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", + pos, bit_pos, err_byte, *(buf + byte_pos)); + } else { + /* Bit flip in OOB area */ + tmp = sector_num * host->pmecc_bytes_per_sector + + (byte_pos - sector_size); + err_byte = ecc[tmp]; + ecc[tmp] ^= (1 << bit_pos); + + pos = tmp + nand_chip->ecc.layout->eccpos[0]; + dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", + pos, bit_pos, err_byte, ecc[tmp]); + } + + i++; + err_nbr--; + } + + return; +} + +static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, + u8 *ecc) +{ + struct nand_chip *nand_chip = mtd->priv; + struct atmel_nand_host *host = nand_chip->priv; + int i, err_nbr, eccbytes; + uint8_t *buf_pos; + + eccbytes = nand_chip->ecc.bytes; + for (i = 0; i < eccbytes; i++) + if (ecc[i] != 0xff) + goto normal_check; + /* Erased page, return OK */ + return 0; + +normal_check: + for (i = 0; i < host->pmecc_sector_number; i++) { + err_nbr = 0; + if (pmecc_stat & 0x1) { + buf_pos = buf + i * host->pmecc_sector_size; + + pmecc_gen_syndrome(mtd, i); + pmecc_substitute(mtd); + pmecc_get_sigma(mtd); + + err_nbr = pmecc_err_location(mtd); + if (err_nbr == -1) { + dev_err(host->dev, "PMECC: Too many errors\n"); + mtd->ecc_stats.failed++; + return -EIO; + } else { + pmecc_correct_data(mtd, buf_pos, ecc, i, + host->pmecc_bytes_per_sector, err_nbr); + mtd->ecc_stats.corrected += err_nbr; + } + } + pmecc_stat >>= 1; + } + + return 0; +} + +static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int oob_required, int page) +{ + struct atmel_nand_host *host = chip->priv; + int eccsize = chip->ecc.size; + uint8_t *oob = chip->oob_poi; + uint32_t *eccpos = chip->ecc.layout->eccpos; + uint32_t stat; + unsigned long end_time; + + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); + pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) + & ~PMECC_CFG_WRITE_OP) | PMECC_CFG_AUTO_ENABLE); + + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA); + + chip->read_buf(mtd, buf, eccsize); + chip->read_buf(mtd, oob, mtd->oobsize); + + end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); + while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) { + if (unlikely(time_after(jiffies, end_time))) { + dev_err(host->dev, "PMECC: Timeout to get error status.\n"); + return -EIO; + } + cpu_relax(); + } + + stat = pmecc_readl_relaxed(host->ecc, ISR); + if (stat != 0) + if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0) + return -EIO; + + return 0; +} + +static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, int oob_required) +{ + struct atmel_nand_host *host = chip->priv; + uint32_t *eccpos = chip->ecc.layout->eccpos; + int i, j; + unsigned long end_time; + + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); + + pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) | + PMECC_CFG_WRITE_OP) & ~PMECC_CFG_AUTO_ENABLE); + + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA); + + chip->write_buf(mtd, (u8 *)buf, mtd->writesize); + + end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); + while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) { + if (unlikely(time_after(jiffies, end_time))) { + dev_err(host->dev, "PMECC: Timeout to get ECC value.\n"); + return -EIO; + } + cpu_relax(); + } + + for (i = 0; i < host->pmecc_sector_number; i++) { + for (j = 0; j < host->pmecc_bytes_per_sector; j++) { + int pos; + + pos = i * host->pmecc_bytes_per_sector + j; + chip->oob_poi[eccpos[pos]] = + pmecc_readb_ecc_relaxed(host->ecc, i, j); + } + } + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; +} + +static void atmel_pmecc_core_init(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = mtd->priv; + struct atmel_nand_host *host = nand_chip->priv; + uint32_t val = 0; + struct nand_ecclayout *ecc_layout; + + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); + + switch (host->pmecc_corr_cap) { + case 2: + val = PMECC_CFG_BCH_ERR2; + break; + case 4: + val = PMECC_CFG_BCH_ERR4; + break; + case 8: + val = PMECC_CFG_BCH_ERR8; + break; + case 12: + val = PMECC_CFG_BCH_ERR12; + break; + case 24: + val = PMECC_CFG_BCH_ERR24; + break; + } + + if (host->pmecc_sector_size == 512) + val |= PMECC_CFG_SECTOR512; + else if (host->pmecc_sector_size == 1024) + val |= PMECC_CFG_SECTOR1024; + + switch (host->pmecc_sector_number) { + case 1: + val |= PMECC_CFG_PAGE_1SECTOR; + break; + case 2: + val |= PMECC_CFG_PAGE_2SECTORS; + break; + case 4: + val |= PMECC_CFG_PAGE_4SECTORS; + break; + case 8: + val |= PMECC_CFG_PAGE_8SECTORS; + break; + } + + val |= (PMECC_CFG_READ_OP | PMECC_CFG_SPARE_DISABLE + | PMECC_CFG_AUTO_DISABLE); + pmecc_writel(host->ecc, CFG, val); + + ecc_layout = nand_chip->ecc.layout; + pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1); + pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]); + pmecc_writel(host->ecc, EADDR, + ecc_layout->eccpos[ecc_layout->eccbytes - 1]); + /* See datasheet about PMECC Clock Control Register */ + pmecc_writel(host->ecc, CLK, 2); + pmecc_writel(host->ecc, IDR, 0xff); + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); +} + +static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, + struct atmel_nand_host *host) +{ + struct mtd_info *mtd = &host->mtd; + struct nand_chip *nand_chip = &host->nand_chip; + struct resource *regs, *regs_pmerr, *regs_rom; + int cap, sector_size, err_no; + + cap = host->pmecc_corr_cap; + sector_size = host->pmecc_sector_size; + dev_info(host->dev, "Initialize PMECC params, cap: %d, sector: %d\n", + cap, sector_size); + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!regs) { + dev_warn(host->dev, + "Can't get I/O resource regs for PMECC controller, rolling back on software ECC\n"); + nand_chip->ecc.mode = NAND_ECC_SOFT; + return 0; + } + + host->ecc = ioremap(regs->start, resource_size(regs)); + if (host->ecc == NULL) { + dev_err(host->dev, "ioremap failed\n"); + err_no = -EIO; + goto err_pmecc_ioremap; + } + + regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2); + regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); + if (regs_pmerr && regs_rom) { + host->pmerrloc_base = ioremap(regs_pmerr->start, + resource_size(regs_pmerr)); + host->pmecc_rom_base = ioremap(regs_rom->start, + resource_size(regs_rom)); + } + + if (!host->pmerrloc_base || !host->pmecc_rom_base) { + dev_err(host->dev, + "Can not get I/O resource for PMECC ERRLOC controller or ROM!\n"); + err_no = -EIO; + goto err_pmloc_ioremap; + } + + /* ECC is calculated for the whole page (1 step) */ + nand_chip->ecc.size = mtd->writesize; + + /* set ECC page size and oob layout */ + switch (mtd->writesize) { + case 2048: + host->pmecc_degree = PMECC_GF_DIMENSION_13; + host->pmecc_cw_len = (1 << host->pmecc_degree) - 1; + host->pmecc_sector_number = mtd->writesize / sector_size; + host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes( + cap, sector_size); + host->pmecc_alpha_to = pmecc_get_alpha_to(host); + host->pmecc_index_of = host->pmecc_rom_base + + host->pmecc_lookup_table_offset; + + nand_chip->ecc.steps = 1; + nand_chip->ecc.strength = cap; + nand_chip->ecc.bytes = host->pmecc_bytes_per_sector * + host->pmecc_sector_number; + if (nand_chip->ecc.bytes > mtd->oobsize - 2) { + dev_err(host->dev, "No room for ECC bytes\n"); + err_no = -EINVAL; + goto err_no_ecc_room; + } + pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, + mtd->oobsize, + nand_chip->ecc.bytes); + nand_chip->ecc.layout = &atmel_pmecc_oobinfo; + break; + case 512: + case 1024: + case 4096: + /* TODO */ + dev_warn(host->dev, + "Unsupported page size for PMECC, use Software ECC\n"); + default: + /* page size not handled by HW ECC */ + /* switching back to soft ECC */ + nand_chip->ecc.mode = NAND_ECC_SOFT; + return 0; + } + + /* Allocate data for PMECC computation */ + err_no = pmecc_data_alloc(host); + if (err_no) { + dev_err(host->dev, + "Cannot allocate memory for PMECC computation!\n"); + goto err_pmecc_data_alloc; + } + + nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; + nand_chip->ecc.write_page = atmel_nand_pmecc_write_page; + + atmel_pmecc_core_init(mtd); + + return 0; + +err_pmecc_data_alloc: +err_no_ecc_room: +err_pmloc_ioremap: + iounmap(host->ecc); + if (host->pmerrloc_base) + iounmap(host->pmerrloc_base); + if (host->pmecc_rom_base) + iounmap(host->pmecc_rom_base); +err_pmecc_ioremap: + return err_no; +} + /* * Calculate HW ECC * @@ -747,7 +1469,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev) } if (nand_chip->ecc.mode == NAND_ECC_HW) { - res = atmel_hw_nand_init_params(pdev, host); + if (host->has_pmecc) + res = atmel_pmecc_nand_init_params(pdev, host); + else + res = atmel_hw_nand_init_params(pdev, host); + if (res != 0) goto err_hw_ecc; } @@ -766,8 +1492,16 @@ static int __init atmel_nand_probe(struct platform_device *pdev) return res; err_scan_tail: + if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) { + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); + pmecc_data_free(host); + } if (host->ecc) iounmap(host->ecc); + if (host->pmerrloc_base) + iounmap(host->pmerrloc_base); + if (host->pmecc_rom_base) + iounmap(host->pmecc_rom_base); err_hw_ecc: err_scan_ident: err_no_card: @@ -793,8 +1527,19 @@ static int __exit atmel_nand_remove(struct platform_device *pdev) atmel_nand_disable(host); + if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) { + pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); + pmerrloc_writel(host->pmerrloc_base, ELDIS, + PMERRLOC_DISABLE); + pmecc_data_free(host); + } + if (host->ecc) iounmap(host->ecc); + if (host->pmecc_rom_base) + iounmap(host->pmecc_rom_base); + if (host->pmerrloc_base) + iounmap(host->pmerrloc_base); if (host->dma_chan) dma_release_channel(host->dma_chan); diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h index 578c776e135632..8a1e9a686759fb 100644 --- a/drivers/mtd/nand/atmel_nand_ecc.h +++ b/drivers/mtd/nand/atmel_nand_ecc.h @@ -3,7 +3,7 @@ * Based on AT91SAM9260 datasheet revision B. * * Copyright (C) 2007 Andrew Victor - * Copyright (C) 2007 Atmel Corporation. + * Copyright (C) 2007 - 2012 Atmel Corporation. * * 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 @@ -36,4 +36,116 @@ #define ATMEL_ECC_NPR 0x10 /* NParity register */ #define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */ +/* PMECC Register Definitions */ +#define ATMEL_PMECC_CFG 0x000 /* Configuration Register */ +#define PMECC_CFG_BCH_ERR2 (0 << 0) +#define PMECC_CFG_BCH_ERR4 (1 << 0) +#define PMECC_CFG_BCH_ERR8 (2 << 0) +#define PMECC_CFG_BCH_ERR12 (3 << 0) +#define PMECC_CFG_BCH_ERR24 (4 << 0) + +#define PMECC_CFG_SECTOR512 (0 << 4) +#define PMECC_CFG_SECTOR1024 (1 << 4) + +#define PMECC_CFG_PAGE_1SECTOR (0 << 8) +#define PMECC_CFG_PAGE_2SECTORS (1 << 8) +#define PMECC_CFG_PAGE_4SECTORS (2 << 8) +#define PMECC_CFG_PAGE_8SECTORS (3 << 8) + +#define PMECC_CFG_READ_OP (0 << 12) +#define PMECC_CFG_WRITE_OP (1 << 12) + +#define PMECC_CFG_SPARE_ENABLE (1 << 16) +#define PMECC_CFG_SPARE_DISABLE (0 << 16) + +#define PMECC_CFG_AUTO_ENABLE (1 << 20) +#define PMECC_CFG_AUTO_DISABLE (0 << 20) + +#define ATMEL_PMECC_SAREA 0x004 /* Spare area size */ +#define ATMEL_PMECC_SADDR 0x008 /* PMECC starting address */ +#define ATMEL_PMECC_EADDR 0x00c /* PMECC ending address */ +#define ATMEL_PMECC_CLK 0x010 /* PMECC clock control */ +#define PMECC_CLK_133MHZ (2 << 0) + +#define ATMEL_PMECC_CTRL 0x014 /* PMECC control register */ +#define PMECC_CTRL_RST (1 << 0) +#define PMECC_CTRL_DATA (1 << 1) +#define PMECC_CTRL_USER (1 << 2) +#define PMECC_CTRL_ENABLE (1 << 4) +#define PMECC_CTRL_DISABLE (1 << 5) + +#define ATMEL_PMECC_SR 0x018 /* PMECC status register */ +#define PMECC_SR_BUSY (1 << 0) +#define PMECC_SR_ENABLE (1 << 4) + +#define ATMEL_PMECC_IER 0x01c /* PMECC interrupt enable */ +#define PMECC_IER_ENABLE (1 << 0) +#define ATMEL_PMECC_IDR 0x020 /* PMECC interrupt disable */ +#define PMECC_IER_DISABLE (1 << 0) +#define ATMEL_PMECC_IMR 0x024 /* PMECC interrupt mask */ +#define PMECC_IER_MASK (1 << 0) +#define ATMEL_PMECC_ISR 0x028 /* PMECC interrupt status */ +#define ATMEL_PMECC_ECCx 0x040 /* PMECC ECC x */ +#define ATMEL_PMECC_REMx 0x240 /* PMECC REM x */ + +/* PMERRLOC Register Definitions */ +#define ATMEL_PMERRLOC_ELCFG 0x000 /* Error location config */ +#define PMERRLOC_ELCFG_SECTOR_512 (0 << 0) +#define PMERRLOC_ELCFG_SECTOR_1024 (1 << 0) +#define PMERRLOC_ELCFG_NUM_ERRORS(n) ((n) << 16) + +#define ATMEL_PMERRLOC_ELPRIM 0x004 /* Error location primitive */ +#define ATMEL_PMERRLOC_ELEN 0x008 /* Error location enable */ +#define ATMEL_PMERRLOC_ELDIS 0x00c /* Error location disable */ +#define PMERRLOC_DISABLE (1 << 0) + +#define ATMEL_PMERRLOC_ELSR 0x010 /* Error location status */ +#define PMERRLOC_ELSR_BUSY (1 << 0) +#define ATMEL_PMERRLOC_ELIER 0x014 /* Error location int enable */ +#define ATMEL_PMERRLOC_ELIDR 0x018 /* Error location int disable */ +#define ATMEL_PMERRLOC_ELIMR 0x01c /* Error location int mask */ +#define ATMEL_PMERRLOC_ELISR 0x020 /* Error location int status */ +#define PMERRLOC_ERR_NUM_MASK (0x1f << 8) +#define PMERRLOC_CALC_DONE (1 << 0) +#define ATMEL_PMERRLOC_SIGMAx 0x028 /* Error location SIGMA x */ +#define ATMEL_PMERRLOC_ELx 0x08c /* Error location x */ + +/* Register access macros for PMECC */ +#define pmecc_readl_relaxed(addr, reg) \ + readl_relaxed((addr) + ATMEL_PMECC_##reg) + +#define pmecc_writel(addr, reg, value) \ + writel((value), (addr) + ATMEL_PMECC_##reg) + +#define pmecc_readb_ecc_relaxed(addr, sector, n) \ + readb_relaxed((addr) + ATMEL_PMECC_ECCx + ((sector) * 0x40) + (n)) + +#define pmecc_readl_rem_relaxed(addr, sector, n) \ + readl_relaxed((addr) + ATMEL_PMECC_REMx + ((sector) * 0x40) + ((n) * 4)) + +#define pmerrloc_readl_relaxed(addr, reg) \ + readl_relaxed((addr) + ATMEL_PMERRLOC_##reg) + +#define pmerrloc_writel(addr, reg, value) \ + writel((value), (addr) + ATMEL_PMERRLOC_##reg) + +#define pmerrloc_writel_sigma_relaxed(addr, n, value) \ + writel_relaxed((value), (addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4)) + +#define pmerrloc_readl_sigma_relaxed(addr, n) \ + readl_relaxed((addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4)) + +#define pmerrloc_readl_el_relaxed(addr, n) \ + readl_relaxed((addr) + ATMEL_PMERRLOC_ELx + ((n) * 4)) + +/* Galois field dimension */ +#define PMECC_GF_DIMENSION_13 13 +#define PMECC_GF_DIMENSION_14 14 + +#define PMECC_LOOKUP_TABLE_SIZE_512 0x2000 +#define PMECC_LOOKUP_TABLE_SIZE_1024 0x4000 + +/* Time out value for reading PMECC status register */ +#define PMECC_MAX_TIMEOUT_MS 100 + #endif From e282e400c5345c7280724b00d53a70c8c72089ab Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Mon, 25 Jun 2012 15:15:54 +0800 Subject: [PATCH 0692/1071] MTD: nand: add return value for write_page()/write_page_raw() functions in structure of nand_ecc_ctrl. There is an implemention of hardware ECC write page function which may return an error indication. For instance, using Atmel HW PMECC to write one page into a nand flash, the hardware engine will compute the BCH ecc code for this page. so we need read a the status register to theck whether the ecc code is generated. But we cannot assume the status register always can be ready, for example, incorrect hardware configuration or hardware issue, in such case we need write_page() to return a error code. Since the definition of 'write_page' function in struct nand_ecc_ctrl is 'void'. So this patch will: 1. add return 'int' value for 'write_page' function. 2. to be consitent, add return 'int' value for 'write_page_raw' fuctions too. 3. add code to test the return value, and if negative, indicate an error happend when write page with ECC. 4. fix the compile warning in all impacted nand flash driver. Note: I couldn't compile-test all of these easily, as some had ARCH dependencies. Signed-off-by: Josh Wu --- drivers/mtd/nand/nand_base.c | 27 +++++++++++++++++++-------- include/linux/mtd/nand.h | 4 ++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c429abd00b8709..2a07bbd775281b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1927,12 +1927,14 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ -static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, +static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { chip->write_buf(mtd, buf, mtd->writesize); if (oob_required) chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; } /** @@ -1944,7 +1946,7 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * * We need a special oob layout and handling even when ECC isn't checked. */ -static void nand_write_page_raw_syndrome(struct mtd_info *mtd, +static int nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { @@ -1974,6 +1976,8 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, size = mtd->oobsize - (oob - chip->oob_poi); if (size) chip->write_buf(mtd, oob, size); + + return 0; } /** * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function @@ -1982,7 +1986,7 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB */ -static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, +static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; @@ -1999,7 +2003,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; i < chip->ecc.total; i++) chip->oob_poi[eccpos[i]] = ecc_calc[i]; - chip->ecc.write_page_raw(mtd, chip, buf, 1); + return chip->ecc.write_page_raw(mtd, chip, buf, 1); } /** @@ -2009,7 +2013,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB */ -static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, +static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; @@ -2029,6 +2033,8 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, chip->oob_poi[eccpos[i]] = ecc_calc[i]; chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; } /** @@ -2041,7 +2047,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ -static void nand_write_page_syndrome(struct mtd_info *mtd, +static int nand_write_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { @@ -2075,6 +2081,8 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, i = mtd->oobsize - (oob - chip->oob_poi); if (i) chip->write_buf(mtd, oob, i); + + return 0; } /** @@ -2096,9 +2104,12 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (unlikely(raw)) - chip->ecc.write_page_raw(mtd, chip, buf, oob_required); + status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required); else - chip->ecc.write_page(mtd, chip, buf, oob_required); + status = chip->ecc.write_page(mtd, chip, buf, oob_required); + + if (status < 0) + return status; /* * Cached progamming disabled for now. Not sure if it's worth the diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index e5cf2c8407ce3b..36821e048bd308 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -358,13 +358,13 @@ struct nand_ecc_ctrl { uint8_t *calc_ecc); int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page); - void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, + int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required); int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page); int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offs, uint32_t len, uint8_t *buf); - void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, + int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required); int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, int page); From 6daccff0ac82e73e54c60eba964a2439c2974b85 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 24 Sep 2012 14:57:08 +0200 Subject: [PATCH 0693/1071] MTD: atmel_nand: add 9x5 to list of SoC with DMA Temporary: may have to be replaced by a device-tree property. Signed-off-by: Nicolas Ferre --- drivers/mtd/nand/atmel_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 000d710954b5a6..8c61e55c91b51c 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -127,7 +127,7 @@ static struct nand_ecclayout atmel_pmecc_oobinfo; static int cpu_has_dma(void) { - return cpu_is_at91sam9rl() || cpu_is_at91sam9g45(); + return cpu_is_at91sam9rl() || cpu_is_at91sam9g45() || cpu_is_at91sam9x5(); } /* From 9c3d0912ed22c2577733326b37bde85d52877402 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 24 Sep 2012 15:07:06 +0200 Subject: [PATCH 0694/1071] MTD: atmel_nand: POI fall back is not an issue: change log Signed-off-by: Nicolas Ferre --- drivers/mtd/nand/atmel_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 8c61e55c91b51c..aca810841ddaea 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -281,7 +281,7 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, dma_unmap_single(dma_dev->dev, phys_addr, len, dir); err_buf: if (err != 0) - dev_warn(host->dev, "Fall back to CPU I/O\n"); + dev_dbg(host->dev, "Fall back to CPU I/O\n"); return err; } From 890921e06cf31f01dfdda43c3c167f7040143bad Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 8 Oct 2012 16:55:29 +0200 Subject: [PATCH 0695/1071] MTD: atmel_nand: add 9n12 to list of SoC with DMA Temporary: may have to be replaced by a device-tree property. Signed-off-by: Nicolas Ferre --- drivers/mtd/nand/atmel_nand.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index aca810841ddaea..58bb70a1828906 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -127,7 +127,8 @@ static struct nand_ecclayout atmel_pmecc_oobinfo; static int cpu_has_dma(void) { - return cpu_is_at91sam9rl() || cpu_is_at91sam9g45() || cpu_is_at91sam9x5(); + return cpu_is_at91sam9rl() || cpu_is_at91sam9g45() + || cpu_is_at91sam9x5() || cpu_is_at91sam9n12(); } /* From 4c6281600040f57251a3b5567a81cadfc95dc989 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Mon, 24 Sep 2012 14:50:45 +0800 Subject: [PATCH 0696/1071] mtd: atmel_nand: add 4k page nand flash support for PMECC. --- drivers/mtd/nand/atmel_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 58bb70a1828906..40220ec8e01e4c 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -952,6 +952,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, /* set ECC page size and oob layout */ switch (mtd->writesize) { case 2048: + case 4096: host->pmecc_degree = PMECC_GF_DIMENSION_13; host->pmecc_cw_len = (1 << host->pmecc_degree) - 1; host->pmecc_sector_number = mtd->writesize / sector_size; @@ -977,7 +978,6 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, break; case 512: case 1024: - case 4096: /* TODO */ dev_warn(host->dev, "Unsupported page size for PMECC, use Software ECC\n"); From 2ab23c380096622e3a4769c2fdae2675acfae2a0 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Mon, 24 Sep 2012 14:58:38 +0800 Subject: [PATCH 0697/1071] mtd: atmel_nand: incease the chip_delay time(tR) for support big flash chips such like MT29F8G08ABABA. --- drivers/mtd/nand/atmel_nand.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 40220ec8e01e4c..ad00cdbddf2231 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1419,7 +1419,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->dev_ready = atmel_nand_device_ready; nand_chip->ecc.mode = host->board.ecc_mode; - nand_chip->chip_delay = 20; /* 20us command delay time */ + + /* For support 4k-page flash, incease the delay time to 25us. + * In P.108 of MT29F8G08ABABA datasheet, tR max is 25us. + */ + nand_chip->chip_delay = 25; if (host->board.bus_width_16) /* 16-bit bus width */ nand_chip->options |= NAND_BUSWIDTH_16; From 34a3a02a637d2608045d8183e151c69016f5151e Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 12 Jul 2012 13:20:22 +0800 Subject: [PATCH 0698/1071] MTD: atmel nand: fix gpio missing request without this the gpio will not be muxed as a gpio by the current custom pinmux or later by the pinctrl Acked-by: Linus Walleij Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/mtd/nand/atmel_nand.c | 50 ++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index ad00cdbddf2231..d68e8c23c7ba45 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1415,8 +1415,41 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->IO_ADDR_W = host->io_base; nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; - if (gpio_is_valid(host->board.rdy_pin)) + if (gpio_is_valid(host->board.rdy_pin)) { + res = devm_gpio_request(&pdev->dev, + host->board.rdy_pin, "nand_rdy"); + if (res < 0) { + dev_err(&pdev->dev, + "can't request rdy gpio %d\n", host->board.rdy_pin); + goto err_ecc_ioremap; + } + + res = gpio_direction_input(host->board.rdy_pin); + if (res < 0) { + dev_err(&pdev->dev, + "can't request input direction rdy gpio %d\n", host->board.rdy_pin); + goto err_ecc_ioremap; + } + nand_chip->dev_ready = atmel_nand_device_ready; + } + + if (gpio_is_valid(host->board.enable_pin)) { + res = devm_gpio_request(&pdev->dev, + host->board.enable_pin, "nand_enable"); + if (res < 0) { + dev_err(&pdev->dev, + "can't request enable gpio %d\n", host->board.enable_pin); + goto err_ecc_ioremap; + } + + res = gpio_direction_output(host->board.enable_pin, 1); + if (res < 0) { + dev_err(&pdev->dev, + "can't request output direction enable gpio %d\n", host->board.enable_pin); + goto err_ecc_ioremap; + } + } nand_chip->ecc.mode = host->board.ecc_mode; @@ -1435,6 +1468,21 @@ static int __init atmel_nand_probe(struct platform_device *pdev) atmel_nand_enable(host); if (gpio_is_valid(host->board.det_pin)) { + res = devm_gpio_request(&pdev->dev, + host->board.det_pin, "nand_det"); + if (res < 0) { + dev_err(&pdev->dev, + "can't request det gpio %d\n", host->board.det_pin); + goto err_no_card; + } + + res = gpio_direction_input(host->board.det_pin); + if (res < 0) { + dev_err(&pdev->dev, + "can't request input direction det gpio %d\n", host->board.det_pin); + goto err_no_card; + } + if (gpio_get_value(host->board.det_pin)) { printk(KERN_INFO "No SmartMedia card inserted.\n"); res = -ENXIO; From 005c98f91fc6d5f58623da5cc8fd70ae45b45900 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 12 Jul 2012 23:31:39 +0800 Subject: [PATCH 0699/1071] MTD: atmel_nand: add pinctrl consumer support Acked-by: Nicolas Ferre Acked-by: Artem Bityutskiy Acked-by: Linus Walleij Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/mtd/nand/atmel_nand.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index d68e8c23c7ba45..15e541c22c308b 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -1371,6 +1372,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) struct resource *mem; struct mtd_part_parser_data ppdata = {}; int res; + struct pinctrl *pinctrl; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { @@ -1415,6 +1417,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->IO_ADDR_W = host->io_base; nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + dev_err(host->dev, "Failed to request pinctrl\n"); + res = PTR_ERR(pinctrl); + goto err_ecc_ioremap; + } + if (gpio_is_valid(host->board.rdy_pin)) { res = devm_gpio_request(&pdev->dev, host->board.rdy_pin, "nand_rdy"); From 1a5a5adf4eb18974535bc13eec8473023a725dd6 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Mon, 24 Sep 2012 08:06:30 +0800 Subject: [PATCH 0700/1071] mtd: atmel_nand: fix the compile error which miss label "err_ecc_ioremap" Add err_ecc_ioremap label to fix following errors: ---8<--- CC drivers/mtd/nand/atmel_nand.o drivers/mtd/nand/atmel_nand.c: In function 'atmel_nand_probe': drivers/mtd/nand/atmel_nand.c:1423: error: label 'err_ecc_ioremap' used but not defined make[3]: *** [drivers/mtd/nand/atmel_nand.o] Error 1 make[2]: *** [drivers/mtd/nand] Error 2 make[1]: *** [drivers/mtd] Error 2 make: *** [drivers] Error 2 --->8--- This error was introduced in b654a9a46fc2100b318050483f8c5b5d0f187303 (mtd: atmel nand: fix gpio missing request) Signed-off-by: Josh Wu Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/mtd/nand/atmel_nand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 15e541c22c308b..5219bcb2be0faa 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1402,7 +1402,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) if (pdev->dev.of_node) { res = atmel_of_init_port(host, pdev->dev.of_node); if (res) - goto err_nand_ioremap; + goto err_ecc_ioremap; } else { memcpy(&host->board, pdev->dev.platform_data, sizeof(struct atmel_nand_data)); @@ -1558,6 +1558,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev) pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); pmecc_data_free(host); } + +err_ecc_ioremap: if (host->ecc) iounmap(host->ecc); if (host->pmerrloc_base) From 66b7ed9cbbee1135aee466169cb40396ce3cddaf Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Wed, 17 Nov 2010 12:28:13 +0100 Subject: [PATCH 0701/1071] input: atmel_tsadcc: add support for ARCH_AT91SAM9X5 XXX: split header creation in a new patch (or don't do it) Signed-off-by: Josh Wu --- drivers/input/touchscreen/atmel_tsadcc.c | 150 +++++++++------------ drivers/input/touchscreen/atmel_tsadcc.h | 162 +++++++++++++++++++++++ 2 files changed, 222 insertions(+), 90 deletions(-) create mode 100644 drivers/input/touchscreen/atmel_tsadcc.h diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 201b2d2ec1b3bb..a0e8d52dcda610 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -25,74 +25,9 @@ #include #include -/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ - -#define ATMEL_TSADCC_CR 0x00 /* Control register */ -#define ATMEL_TSADCC_SWRST (1 << 0) /* Software Reset*/ -#define ATMEL_TSADCC_START (1 << 1) /* Start conversion */ - -#define ATMEL_TSADCC_MR 0x04 /* Mode register */ -#define ATMEL_TSADCC_TSAMOD (3 << 0) /* ADC mode */ -#define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */ -#define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */ -#define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ -#define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ -#define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ -#define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */ -#define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ -#define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */ -#define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ -#define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ -#define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ - -#define ATMEL_TSADCC_TRGR 0x08 /* Trigger register */ -#define ATMEL_TSADCC_TRGMOD (7 << 0) /* Trigger mode */ -#define ATMEL_TSADCC_TRGMOD_NONE (0 << 0) -#define ATMEL_TSADCC_TRGMOD_EXT_RISING (1 << 0) -#define ATMEL_TSADCC_TRGMOD_EXT_FALLING (2 << 0) -#define ATMEL_TSADCC_TRGMOD_EXT_ANY (3 << 0) -#define ATMEL_TSADCC_TRGMOD_PENDET (4 << 0) -#define ATMEL_TSADCC_TRGMOD_PERIOD (5 << 0) -#define ATMEL_TSADCC_TRGMOD_CONTINUOUS (6 << 0) -#define ATMEL_TSADCC_TRGPER (0xffff << 16) /* Trigger period */ - -#define ATMEL_TSADCC_TSR 0x0C /* Touch Screen register */ -#define ATMEL_TSADCC_TSFREQ (0xf << 0) /* TS Frequency in Interleaved mode */ -#define ATMEL_TSADCC_TSSHTIM (0xf << 24) /* Sample & Hold time */ - -#define ATMEL_TSADCC_CHER 0x10 /* Channel Enable register */ -#define ATMEL_TSADCC_CHDR 0x14 /* Channel Disable register */ -#define ATMEL_TSADCC_CHSR 0x18 /* Channel Status register */ -#define ATMEL_TSADCC_CH(n) (1 << (n)) /* Channel number */ - -#define ATMEL_TSADCC_SR 0x1C /* Status register */ -#define ATMEL_TSADCC_EOC(n) (1 << ((n)+0)) /* End of conversion for channel N */ -#define ATMEL_TSADCC_OVRE(n) (1 << ((n)+8)) /* Overrun error for channel N */ -#define ATMEL_TSADCC_DRDY (1 << 16) /* Data Ready */ -#define ATMEL_TSADCC_GOVRE (1 << 17) /* General Overrun Error */ -#define ATMEL_TSADCC_ENDRX (1 << 18) /* End of RX Buffer */ -#define ATMEL_TSADCC_RXBUFF (1 << 19) /* TX Buffer full */ -#define ATMEL_TSADCC_PENCNT (1 << 20) /* Pen contact */ -#define ATMEL_TSADCC_NOCNT (1 << 21) /* No contact */ - -#define ATMEL_TSADCC_LCDR 0x20 /* Last Converted Data register */ -#define ATMEL_TSADCC_DATA (0x3ff << 0) /* Channel data */ - -#define ATMEL_TSADCC_IER 0x24 /* Interrupt Enable register */ -#define ATMEL_TSADCC_IDR 0x28 /* Interrupt Disable register */ -#define ATMEL_TSADCC_IMR 0x2C /* Interrupt Mask register */ -#define ATMEL_TSADCC_CDR0 0x30 /* Channel Data 0 */ -#define ATMEL_TSADCC_CDR1 0x34 /* Channel Data 1 */ -#define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */ -#define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */ -#define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ -#define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ - -#define ATMEL_TSADCC_XPOS 0x50 -#define ATMEL_TSADCC_Z1DAT 0x54 -#define ATMEL_TSADCC_Z2DAT 0x58 - -#define PRESCALER_VAL(x) ((x) >> 8) +#include "atmel_tsadcc.h" + +#define cpu_has_9x5_adc() (cpu_is_at91sam9x5()) #define ADC_DEFAULT_CLOCK 100000 @@ -124,12 +59,17 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) if (status & ATMEL_TSADCC_NOCNT) { /* Contact lost */ - reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC; - - atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); + if (cpu_has_9x5_adc()) { + /* 9X5 using TSMR to set PENDBC time */ + reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR) | ATMEL_TSADCC_PENDBC; + atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg); + } else { + reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC; + atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); + } atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); atmel_tsadcc_write(ATMEL_TSADCC_IDR, - ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT); + ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT); atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); input_report_key(input_dev, BTN_TOUCH, 0); @@ -138,23 +78,31 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) } else if (status & ATMEL_TSADCC_PENCNT) { /* Pen detected */ - reg = atmel_tsadcc_read(ATMEL_TSADCC_MR); - reg &= ~ATMEL_TSADCC_PENDBC; + if (cpu_has_9x5_adc()) { + reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR); + reg &= ~ATMEL_TSADCC_PENDBC; + atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg); + } else { + reg = atmel_tsadcc_read(ATMEL_TSADCC_MR); + reg &= ~ATMEL_TSADCC_PENDBC; + atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); + } atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT); - atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); atmel_tsadcc_write(ATMEL_TSADCC_IER, - ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT); + ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT); atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16)); - } else if (status & ATMEL_TSADCC_EOC(3)) { + } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) { /* Conversion finished */ if (ts_dev->bufferedmeasure) { /* Last measurement is always discarded, since it can * be erroneous. * Always report previous measurement */ + dev_dbg(&input_dev->dev, "x = %d, y = %d\n", + ts_dev->prev_absx, ts_dev->prev_absy); input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); input_report_key(input_dev, BTN_TOUCH, 1); @@ -163,11 +111,16 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) ts_dev->bufferedmeasure = 1; /* Now make new measurement */ - ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; - ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); - - ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; - ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); + if (cpu_has_9x5_adc()) { + ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR) & 0xffff; + ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR) & 0xffff; + } else { + ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; + ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); + + ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; + ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); + } } return IRQ_HANDLED; @@ -284,18 +237,35 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc); - reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | - ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ - ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ - (prsc << 8) | - ((0x26 << 16) & ATMEL_TSADCC_STARTUP) | - ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC); + if (cpu_has_9x5_adc()) { + reg = ((0x01 << 5) & ATMEL_TSADCC_SLEEP) | /* Sleep Mode */ + (prsc << 8) | + ((0x8 << 16) & ATMEL_TSADCC_STARTUP) | + ((pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TRACKTIM); + } else { + reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | + ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ + ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ + (prsc << 8) | + ((0x26 << 16) & ATMEL_TSADCC_STARTUP) | + ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC); + } atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST); atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); - atmel_tsadcc_write(ATMEL_TSADCC_TSR, - (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM); + + if (cpu_has_9x5_adc()) { + atmel_tsadcc_write(ATMEL_TSADCC_TSMR, + ATMEL_TSADCC_TSMODE_4WIRE_NO_PRESS | + ATMEL_TSADCC_NOTSDMA | + ATMEL_TSADCC_PENDET_ENA | + (pdata->pendet_debounce << 28) | + (0x0 << 8)); + } else { + atmel_tsadcc_write(ATMEL_TSADCC_TSR, + (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM); + } atmel_tsadcc_read(ATMEL_TSADCC_SR); atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h new file mode 100644 index 00000000000000..5918c20383bd0d --- /dev/null +++ b/drivers/input/touchscreen/atmel_tsadcc.h @@ -0,0 +1,162 @@ +/* + * Header file for AT91/AT32 ADC + touchscreen Controller + * + * Data structure and register user interface + * + * Copyright (C) 2010 Atmel Corporation + * + * 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 __ATMEL_TSADCC_H__ +#define __ATMEL_TSADCC_H__ + +/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ +#define ATMEL_TSADCC_CR 0x00 /* Control register */ +#define ATMEL_TSADCC_SWRST (1 << 0) /* Software Reset*/ +#define ATMEL_TSADCC_START (1 << 1) /* Start conversion */ + +#define ATMEL_TSADCC_MR 0x04 /* Mode register */ +#define ATMEL_TSADCC_TSAMOD (3 << 0) /* ADC mode */ +#define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */ +#define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */ +#define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ +#define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ +#define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ +#define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */ +#define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ +#define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */ +#define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ +#define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ +#define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ + +#define ATMEL_TSADCC_TRGR 0x08 /* Trigger register */ +#define ATMEL_TSADCC_TRGMOD (7 << 0) /* Trigger mode */ +#define ATMEL_TSADCC_TRGMOD_NONE (0 << 0) +#define ATMEL_TSADCC_TRGMOD_EXT_RISING (1 << 0) +#define ATMEL_TSADCC_TRGMOD_EXT_FALLING (2 << 0) +#define ATMEL_TSADCC_TRGMOD_EXT_ANY (3 << 0) +#define ATMEL_TSADCC_TRGMOD_PENDET (4 << 0) +#define ATMEL_TSADCC_TRGMOD_PERIOD (5 << 0) +#define ATMEL_TSADCC_TRGMOD_CONTINUOUS (6 << 0) +#define ATMEL_TSADCC_TRGPER (0xffff << 16) /* Trigger period */ + +#define ATMEL_TSADCC_TSR 0x0C /* Touch Screen register */ +#define ATMEL_TSADCC_TSFREQ (0xf << 0) /* TS Frequency in Interleaved mode */ +#define ATMEL_TSADCC_TSSHTIM (0xf << 24) /* Sample & Hold time */ + +#define ATMEL_TSADCC_CHER 0x10 /* Channel Enable register */ +#define ATMEL_TSADCC_CHDR 0x14 /* Channel Disable register */ +#define ATMEL_TSADCC_CHSR 0x18 /* Channel Status register */ +#define ATMEL_TSADCC_CH(n) (1 << (n)) /* Channel number */ + +#define ATMEL_TSADCC_SR 0x1C /* Status register */ +#define ATMEL_TSADCC_EOC(n) (1 << ((n)+0)) /* End of conversion for channel N */ +#define ATMEL_TSADCC_OVRE(n) (1 << ((n)+8)) /* Overrun error for channel N */ +#define ATMEL_TSADCC_DRDY (1 << 16) /* Data Ready */ +#define ATMEL_TSADCC_GOVRE (1 << 17) /* General Overrun Error */ +#define ATMEL_TSADCC_ENDRX (1 << 18) /* End of RX Buffer */ +#define ATMEL_TSADCC_RXBUFF (1 << 19) /* TX Buffer full */ +#define ATMEL_TSADCC_PENCNT (1 << 20) /* Pen contact */ +#define ATMEL_TSADCC_NOCNT (1 << 21) /* No contact */ + +#define ATMEL_TSADCC_LCDR 0x20 /* Last Converted Data register */ +#define ATMEL_TSADCC_DATA (0x3ff << 0) /* Channel data */ + +#define ATMEL_TSADCC_IER 0x24 /* Interrupt Enable register */ +#define ATMEL_TSADCC_IDR 0x28 /* Interrupt Disable register */ +#define ATMEL_TSADCC_IMR 0x2C /* Interrupt Mask register */ +#define ATMEL_TSADCC_CDR0 0x30 /* Channel Data 0 */ +#define ATMEL_TSADCC_CDR1 0x34 /* Channel Data 1 */ +#define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */ +#define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */ +#define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ +#define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ + +#define ATMEL_TSADCC_XPOS 0x50 +#define ATMEL_TSADCC_Z1DAT 0x54 +#define ATMEL_TSADCC_Z2DAT 0x58 + +#define ATMEL_TSADCC_CONVERSION_END (ATMEL_TSADCC_EOC(3)) + +/* Register definitions based on AT91SAM9X5 preliminary draft datasheet */ +#define ATMEL_TSADCC_TRACKTIM (0x0f << 24) /* Tracking Time */ + +#define ATMEL_TSADCC_ISR 0x30 /* Interrupt Status register */ +#define ATMEL_TSADCC_XRDY (1 << 20) /* Measure XPOS Ready */ +#define ATMEL_TSADCC_YRDY (1 << 21) /* Measure YPOS Ready */ +#define ATMEL_TSADCC_PRDY (1 << 22) /* Measure Pressure Ready */ +#define ATMEL_TSADCC_COMPE (1 << 26) /* Comparison Event */ +#define ATMEL_TSADCC_PEN (1 << 29) /* Pen Contact */ +#define ATMEL_TSADCC_NOPEN (1 << 30) /* No Pen Contact */ +#define ATMEL_TSADCC_PENDET_STATUS (1 << 31) /* Pen Detect Status (not interrupt source) */ + +#define ATMEL_TSADCC_TSMR 0xb0 +#define ATMEL_TSADCC_TSMODE (3 << 0) /* Touch Screen Mode */ +#define ATMEL_TSADCC_TSMODE_NO (0 << 0) /* No Touch Screen */ +#define ATMEL_TSADCC_TSMODE_4WIRE_NO_PRESS (1 << 0) /* 4-wire Touch Screen without pressure measurement */ +#define ATMEL_TSADCC_TSMODE_4WIRE_PRESS (2 << 0) /* 4-wire Touch Screen with pressure measurement */ +#define ATMEL_TSADCC_TSMODE_5WIRE (3 << 0) /* 5-wire Touch Screen */ +#define ATMEL_TSADCC_TSAV (3 << 4) /* Touch Screen Average */ +#define ATMEL_TSADCC_TSAV_1 (0 << 4) /* No filtering. Only one conversion ADC per measure */ +#define ATMEL_TSADCC_TSAV_2 (1 << 4) /* Averages 2 ADC conversions */ +#define ATMEL_TSADCC_TSAV_4 (2 << 4) /* Averages 4 ADC conversions */ +#define ATMEL_TSADCC_TSAV_8 (3 << 4) /* Averages 8 ADC conversions */ +#define ATMEL_TSADCC_TSSCTIM (0x0f << 16) /* Touch Screen switches closure time */ + +#define ATMEL_TSADCC_NOTSDMA (1 << 22) /* No Touchscreen DMA */ +#define ATMEL_TSADCC_PENDET_DIS (0 << 24) /* Pen contact detection disable */ +#define ATMEL_TSADCC_PENDET_ENA (1 << 24) /* Pen contact detection enable */ + +#define ATMEL_TSADCC_XPOSR 0xb4 +#define ATMEL_TSADCC_XSCALE (0x3ff << 16) /* Scale of X Position */ + +#define ATMEL_TSADCC_YPOSR 0xb8 +#define ATMEL_TSADCC_YPOS (0x3ff << 0) /* Y Position */ +#define ATMEL_TSADCC_YSCALE (0x3ff << 16) /* Scale of Y Position */ + +/* 9x5 ADC registers which conflict with previous definition */ +#ifdef CONFIG_ARCH_AT91SAM9X5 +#undef ATMEL_TSADCC_TRGR +#undef ATMEL_TSADCC_SR +#define ATMEL_TSADCC_SR ATMEL_TSADCC_ISR +#define ATMEL_TSADCC_TRGR 0xc0 + +/* For code compatiable, redefine with 9x5 value */ +#undef ATMEL_TSADCC_STARTUP +#define ATMEL_TSADCC_STARTUP (0x0f << 16) /* Startup Time */ +#undef ATMEL_TSADCC_DRDY +#define ATMEL_TSADCC_DRDY (1 << 24) /* Data Ready */ +#undef ATMEL_TSADCC_GOVRE +#define ATMEL_TSADCC_GOVRE (1 << 25) /* General Overrun */ +#undef ATMEL_TSADCC_TSFREQ +#define ATMEL_TSADCC_TSFREQ (0x0f << 8) /* Touch Screen Frequency */ +#undef ATMEL_TSADCC_PENDET +#define ATMEL_TSADCC_PENDET (1 << 24) /* Pen Contact Detection Enable */ +#undef ATMEL_TSADCC_XPOS +#define ATMEL_TSADCC_XPOS (0x3ff << 0) /* X Position */ + +#undef ATMEL_TSADCC_NOCNT +#define ATMEL_TSADCC_NOCNT ATMEL_TSADCC_NOPEN +#undef ATMEL_TSADCC_PENCNT +#define ATMEL_TSADCC_PENCNT ATMEL_TSADCC_PEN +#undef ATMEL_TSADCC_CONVERSION_END +#define ATMEL_TSADCC_CONVERSION_END (ATMEL_TSADCC_XRDY | ATMEL_TSADCC_YRDY | ATMEL_TSADCC_PRDY) + +#endif + +/* Retrieve prescaler value */ +#define PRESCALER_VAL(x) ((x) >> 8) + +#endif /* __ATMEL_TSADCC_H__ */ From fe2597df03740da09074337ee3ac95763cd5ba33 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Wed, 17 Nov 2010 13:12:11 +0100 Subject: [PATCH 0702/1071] input: atmel_tsadcc: add touch screen pressure measurement Signed-off-by: Josh Wu --- drivers/input/touchscreen/atmel_tsadcc.c | 26 +++++++++++++++++++++--- drivers/input/touchscreen/atmel_tsadcc.h | 4 ++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index a0e8d52dcda610..b6a1630e197b4a 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -38,6 +38,7 @@ struct atmel_tsadcc { int irq; unsigned int prev_absx; unsigned int prev_absy; + unsigned int prev_absz; unsigned char bufferedmeasure; }; @@ -53,6 +54,9 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) unsigned int status; unsigned int reg; + unsigned int z1, z2; + unsigned int Rxp = 1; + unsigned int factor = 1000; status = atmel_tsadcc_read(ATMEL_TSADCC_SR); status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR); @@ -101,11 +105,15 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) /* Last measurement is always discarded, since it can * be erroneous. * Always report previous measurement */ - dev_dbg(&input_dev->dev, "x = %d, y = %d\n", - ts_dev->prev_absx, ts_dev->prev_absy); + dev_dbg(&input_dev->dev, + "x = %d, y = %d, pressure = %d\n", + ts_dev->prev_absx, ts_dev->prev_absy, + ts_dev->prev_absz); input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); input_report_key(input_dev, BTN_TOUCH, 1); + if (cpu_has_9x5_adc()) + input_report_abs(input_dev, ABS_PRESSURE, ts_dev->prev_absz); input_sync(input_dev); } else ts_dev->bufferedmeasure = 1; @@ -114,6 +122,17 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) if (cpu_has_9x5_adc()) { ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR) & 0xffff; ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR) & 0xffff; + + /* calculate the pressure */ + reg = atmel_tsadcc_read(ATMEL_TSADCC_PRESSR); + z1 = reg & ATMEL_TSADCC_PRESSR_Z1; + z2 = (reg & ATMEL_TSADCC_PRESSR_Z2) >> 16; + + if (z1 != 0) + ts_dev->prev_absz = Rxp * (ts_dev->prev_absx * factor / 1024) * (z2 * factor / z1 - factor) / factor; + else + ts_dev->prev_absz = 0; + } else { ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); @@ -209,6 +228,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) __set_bit(EV_ABS, input_dev->evbit); input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xffffff, 0, 0); input_set_capability(input_dev, EV_KEY, BTN_TOUCH); @@ -257,7 +277,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) if (cpu_has_9x5_adc()) { atmel_tsadcc_write(ATMEL_TSADCC_TSMR, - ATMEL_TSADCC_TSMODE_4WIRE_NO_PRESS | + ATMEL_TSADCC_TSMODE_4WIRE_PRESS | ATMEL_TSADCC_NOTSDMA | ATMEL_TSADCC_PENDET_ENA | (pdata->pendet_debounce << 28) | diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h index 5918c20383bd0d..231497e72daeae 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.h +++ b/drivers/input/touchscreen/atmel_tsadcc.h @@ -126,6 +126,10 @@ #define ATMEL_TSADCC_YPOS (0x3ff << 0) /* Y Position */ #define ATMEL_TSADCC_YSCALE (0x3ff << 16) /* Scale of Y Position */ +#define ATMEL_TSADCC_PRESSR 0xbc /* Touchscreen Pressure Register */ +#define ATMEL_TSADCC_PRESSR_Z1 (0x3ff << 0) /* Data of Z1 Measurement */ +#define ATMEL_TSADCC_PRESSR_Z2 (0x3ff << 16) /* Data of Z2 Measurement */ + /* 9x5 ADC registers which conflict with previous definition */ #ifdef CONFIG_ARCH_AT91SAM9X5 #undef ATMEL_TSADCC_TRGR From 5d154f68d429834721f76b0c730878d1461791f6 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 5 Apr 2011 17:30:03 +0200 Subject: [PATCH 0703/1071] input: atmel_tsadcc: enable touchscreen averaging and add fast wake up Enable the touchscreen average to improve the resulting events. For this to work the trigger period needs to be reduced. This puts a field into at91_tsadcc_data to allow platforms to specify the number of conversions to average over. XXX: should the trigger period passed by the platform, too, as this depends on the number of conversions? XXX: seperate fast wake up into a seperate patch? What does it? XXX: don't use bare constants Signed-off-by: Ludovic Desroches --- drivers/input/touchscreen/atmel_tsadcc.c | 14 ++++++++------ drivers/input/touchscreen/atmel_tsadcc.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index b6a1630e197b4a..48faecb8a6ed0a 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -96,7 +96,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT); atmel_tsadcc_write(ATMEL_TSADCC_TRGR, - ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16)); + ATMEL_TSADCC_TRGMOD_PERIOD | (0x00D0 << 16)); } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) { /* Conversion finished */ @@ -259,6 +259,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) if (cpu_has_9x5_adc()) { reg = ((0x01 << 5) & ATMEL_TSADCC_SLEEP) | /* Sleep Mode */ + ((0x01 << 6) & ATMEL_TSADCC_FWUP) | /* Fast Wake Up */ (prsc << 8) | ((0x8 << 16) & ATMEL_TSADCC_STARTUP) | ((pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TRACKTIM); @@ -277,11 +278,12 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) if (cpu_has_9x5_adc()) { atmel_tsadcc_write(ATMEL_TSADCC_TSMR, - ATMEL_TSADCC_TSMODE_4WIRE_PRESS | - ATMEL_TSADCC_NOTSDMA | - ATMEL_TSADCC_PENDET_ENA | - (pdata->pendet_debounce << 28) | - (0x0 << 8)); + ATMEL_TSADCC_TSMODE_4WIRE_PRESS | + (pdata->filtering_average << 4) | /* Touchscreen average */ + ATMEL_TSADCC_NOTSDMA | + ATMEL_TSADCC_PENDET_ENA | + (pdata->pendet_debounce << 28) | + (0x3 << 8)); /* Touchscreen freq */ } else { atmel_tsadcc_write(ATMEL_TSADCC_TSR, (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM); diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h index 231497e72daeae..572770aa3f2442 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.h +++ b/drivers/input/touchscreen/atmel_tsadcc.h @@ -34,6 +34,7 @@ #define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ #define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ #define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ +#define ATMEL_TSADCC_FWUP (1 << 6) /* Fast Wake Up selection (5series) */ #define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */ #define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ #define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */ From ca7ec75942b287bfc62c21a15c0d08b98c3201c4 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Fri, 6 May 2011 17:54:45 +0200 Subject: [PATCH 0704/1071] input: atmel_tsadcc: add ACR register and change trigger period value Add ACR register which allows to configure internal ADC resistor, that should prevent from adding resistor on display module. Furthermore increase trigger period which seems to be related with resistor value. A Too small value causes continuous irq. Signed-off-by: Ludovic Desroches --- drivers/input/touchscreen/atmel_tsadcc.c | 30 +++++++++++++++++++++++- drivers/input/touchscreen/atmel_tsadcc.h | 3 +++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 48faecb8a6ed0a..20154ba9aba920 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -47,6 +47,17 @@ static void __iomem *tsc_base; #define atmel_tsadcc_read(reg) __raw_readl(tsc_base + (reg)) #define atmel_tsadcc_write(reg, val) __raw_writel((val), tsc_base + (reg)) +static void atmel_tsadcc_dump_conf(struct platform_device *pdev) +{ + dev_info(&pdev->dev, "--- configuration ---\n"); + dev_info(&pdev->dev, "Mode Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_MR)); + dev_info(&pdev->dev, "Trigger Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_TRGR)); + dev_info(&pdev->dev, "Touchscreen Mode Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_TSMR)); + dev_info(&pdev->dev, "Analog Control Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_ACR)); + dev_info(&pdev->dev, "ADC Channel Status Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_CHSR)); + dev_info(&pdev->dev, "---------------------\n"); +} + static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) { struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; @@ -95,8 +106,14 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT); atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT); + /* this value is related to the resistor bits value of + * ACR register and R64. If internal resistor value is + * increased then this value has to be increased. This + * behavior seems to happen only with averaging on 8 + * values + */ atmel_tsadcc_write(ATMEL_TSADCC_TRGR, - ATMEL_TSADCC_TRGMOD_PERIOD | (0x00D0 << 16)); + ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FF << 16)); } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) { /* Conversion finished */ @@ -289,9 +306,20 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM); } + /* Change adc internal resistor value for better pen detection, + * default value is 100 kOhm. + * 0 = 200 kOhm, 1 = 150 kOhm, 2 = 100 kOhm, 3 = 50 kOhm + * option only available on ES2 and higher + */ + if (cpu_has_9x5_adc()) { + atmel_tsadcc_write(ATMEL_TSADCC_ACR, pdata->pendet_sensitivity); + } + atmel_tsadcc_read(ATMEL_TSADCC_SR); atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); + /* atmel_tsadcc_dump_conf(pdev); */ + /* All went ok, so register to the input system */ err = input_register_device(input_dev); if (err) diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h index 572770aa3f2442..fe74506bf34a76 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.h +++ b/drivers/input/touchscreen/atmel_tsadcc.h @@ -103,6 +103,9 @@ #define ATMEL_TSADCC_NOPEN (1 << 30) /* No Pen Contact */ #define ATMEL_TSADCC_PENDET_STATUS (1 << 31) /* Pen Detect Status (not interrupt source) */ +#define ATMEL_TSADCC_ACR 0x94 /* Analog Control Register */ +#define ATMEL_TSADCC_PENDET_SENSITIVITY (0x3 << 0) /* ADC internal resistor */ + #define ATMEL_TSADCC_TSMR 0xb0 #define ATMEL_TSADCC_TSMODE (3 << 0) /* Touch Screen Mode */ #define ATMEL_TSADCC_TSMODE_NO (0 << 0) /* No Touch Screen */ From 807ba1af4949699ee67de06c76bb4e63764af789 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 16 Jun 2011 19:24:04 +0200 Subject: [PATCH 0705/1071] AT91/input: atmel_tsadcc: rework irq infrastructure and parameters Signed-off-by: Nicolas Ferre --- drivers/input/touchscreen/atmel_tsadcc.c | 70 ++++++++++++++---------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 20154ba9aba920..397d17a87ec4eb 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -30,6 +30,7 @@ #define cpu_has_9x5_adc() (cpu_is_at91sam9x5()) #define ADC_DEFAULT_CLOCK 100000 +#define ZTHRESHOLD 3200 struct atmel_tsadcc { struct input_dev *input; @@ -39,7 +40,6 @@ struct atmel_tsadcc { unsigned int prev_absx; unsigned int prev_absy; unsigned int prev_absz; - unsigned char bufferedmeasure; }; static void __iomem *tsc_base; @@ -62,6 +62,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) { struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; struct input_dev *input_dev = ts_dev->input; + struct at91_tsadcc_data *pdata = input_dev->dev.parent->platform_data; unsigned int status; unsigned int reg; @@ -76,7 +77,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) /* Contact lost */ if (cpu_has_9x5_adc()) { /* 9X5 using TSMR to set PENDBC time */ - reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR) | ATMEL_TSADCC_PENDBC; + reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR) | ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC); atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg); } else { reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC; @@ -88,7 +89,6 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); input_report_key(input_dev, BTN_TOUCH, 0); - ts_dev->bufferedmeasure = 0; input_sync(input_dev); } else if (status & ATMEL_TSADCC_PENCNT) { @@ -118,27 +118,20 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) { /* Conversion finished */ - if (ts_dev->bufferedmeasure) { - /* Last measurement is always discarded, since it can - * be erroneous. - * Always report previous measurement */ - dev_dbg(&input_dev->dev, - "x = %d, y = %d, pressure = %d\n", - ts_dev->prev_absx, ts_dev->prev_absy, - ts_dev->prev_absz); - input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); - input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); - input_report_key(input_dev, BTN_TOUCH, 1); - if (cpu_has_9x5_adc()) - input_report_abs(input_dev, ABS_PRESSURE, ts_dev->prev_absz); - input_sync(input_dev); - } else - ts_dev->bufferedmeasure = 1; - - /* Now make new measurement */ + /* make new measurement */ if (cpu_has_9x5_adc()) { - ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR) & 0xffff; - ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR) & 0xffff; + unsigned int xscale, yscale; + + /* calculate position */ + reg = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR); + ts_dev->prev_absx = (reg & ATMEL_TSADCC_XPOS) << 10; + xscale = (reg & ATMEL_TSADCC_XSCALE) >> 16; + ts_dev->prev_absx /= xscale ? xscale: 1; + + reg = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR); + ts_dev->prev_absy = (reg & ATMEL_TSADCC_YPOS) << 10; + yscale = (reg & ATMEL_TSADCC_YSCALE) >> 16; + ts_dev->prev_absy /= yscale ? yscale: 1 << 10; /* calculate the pressure */ reg = atmel_tsadcc_read(ATMEL_TSADCC_PRESSR); @@ -157,6 +150,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); } + + /* report measurement to input layer */ + if (ts_dev->prev_absz < ZTHRESHOLD) { + dev_dbg(&input_dev->dev, + "x = %d, y = %d, pressure = %d\n", + ts_dev->prev_absx, ts_dev->prev_absy, + ts_dev->prev_absz); + input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); + input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); + if (cpu_has_9x5_adc()) + input_report_abs(input_dev, ABS_PRESSURE, ts_dev->prev_absz); + input_report_key(input_dev, BTN_TOUCH, 1); + input_sync(input_dev); + } else { + dev_dbg(&input_dev->dev, + "pressure too low: not reporting\n"); + } } return IRQ_HANDLED; @@ -233,7 +243,6 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) } ts_dev->input = input_dev; - ts_dev->bufferedmeasure = 0; snprintf(ts_dev->phys, sizeof(ts_dev->phys), "%s/input0", dev_name(&pdev->dev)); @@ -275,10 +284,10 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc); if (cpu_has_9x5_adc()) { - reg = ((0x01 << 5) & ATMEL_TSADCC_SLEEP) | /* Sleep Mode */ - ((0x01 << 6) & ATMEL_TSADCC_FWUP) | /* Fast Wake Up */ + reg = ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* no Sleep Mode */ + ((0x00 << 6) & ATMEL_TSADCC_FWUP) | /* no Fast Wake Up needed */ (prsc << 8) | - ((0x8 << 16) & ATMEL_TSADCC_STARTUP) | + ((0x4 << 16) & ATMEL_TSADCC_STARTUP) | ((pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TRACKTIM); } else { reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | @@ -296,10 +305,10 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) if (cpu_has_9x5_adc()) { atmel_tsadcc_write(ATMEL_TSADCC_TSMR, ATMEL_TSADCC_TSMODE_4WIRE_PRESS | - (pdata->filtering_average << 4) | /* Touchscreen average */ + ((pdata->filtering_average << 4) & ATMEL_TSADCC_TSAV) | /* Touchscreen average */ ATMEL_TSADCC_NOTSDMA | ATMEL_TSADCC_PENDET_ENA | - (pdata->pendet_debounce << 28) | + ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC) | (0x3 << 8)); /* Touchscreen freq */ } else { atmel_tsadcc_write(ATMEL_TSADCC_TSR, @@ -312,7 +321,8 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) * option only available on ES2 and higher */ if (cpu_has_9x5_adc()) { - atmel_tsadcc_write(ATMEL_TSADCC_ACR, pdata->pendet_sensitivity); + if (pdata->pendet_sensitivity <= ATMEL_TSADCC_PENDET_SENSITIVITY) + atmel_tsadcc_write(ATMEL_TSADCC_ACR, pdata->pendet_sensitivity); } atmel_tsadcc_read(ATMEL_TSADCC_SR); From 079654dbdf6ef40224a0b9db69f123aac8de88cb Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Thu, 7 Jun 2012 14:19:11 +0800 Subject: [PATCH 0706/1071] input: at91: add tsadcc_data for 9x5 Signed-off-by: Josh Wu --- arch/arm/mach-at91/include/mach/board.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 369afc2ffc5b97..726e5f3ad1ffc0 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -175,7 +175,9 @@ extern void __init at91_add_device_isi(struct isi_platform_data *data, /* Touchscreen Controller */ struct at91_tsadcc_data { unsigned int adc_clock; + u8 filtering_average; u8 pendet_debounce; + u8 pendet_sensitivity; u8 ts_sample_hold_time; }; extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data); From f7b5deca3e2b9c16c728c0868daa32ad544acb05 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Wed, 13 Jun 2012 17:28:40 +0800 Subject: [PATCH 0707/1071] input: at91: add dt support for atmel touch screen adc controller. Signed-off-by: Josh Wu --- drivers/input/touchscreen/atmel_tsadcc.c | 86 ++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 397d17a87ec4eb..021f87ec04957f 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -40,6 +40,8 @@ struct atmel_tsadcc { unsigned int prev_absx; unsigned int prev_absy; unsigned int prev_absz; + + struct at91_tsadcc_data board; }; static void __iomem *tsc_base; @@ -62,7 +64,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) { struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; struct input_dev *input_dev = ts_dev->input; - struct at91_tsadcc_data *pdata = input_dev->dev.parent->platform_data; + struct at91_tsadcc_data *pdata = &ts_dev->board; unsigned int status; unsigned int reg; @@ -172,6 +174,63 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) return IRQ_HANDLED; } +#if defined(CONFIG_OF) +static int __devinit atmel_of_init_tsadcc(struct device_node *np, + struct at91_tsadcc_data *pdata, + struct platform_device *pdev) +{ + u32 val; + + if (of_property_read_u32(np, "atmel,tsadcc_clock", &val) == 0) + pdata->adc_clock = val; + + if (of_property_read_u32(np, "atmel,filtering_average", &val) == 0) { + if (val > 0x03) { + dev_err(&pdev->dev, "invalid touch average setting, 0x%02x\n", + val); + return -EINVAL; + } + pdata->filtering_average = (u8)val; + } + + if (of_property_read_u32(np, "atmel,pendet_debounce", &val) == 0) { + if (val > 0x0f) { + dev_err(&pdev->dev, "invalid pen detect debounce, 0x%02x\n", + val); + return -EINVAL; + } + pdata->pendet_debounce = (u8)val; + } + + if (of_property_read_u32(np, "atmel,pendet_sensitivity", &val) == 0) { + if (val > 0x03) { + dev_err(&pdev->dev, "invalid pen detective sensitivity setting, 0x%02x\n", + val); + return -EINVAL; + } + pdata->pendet_sensitivity = (u8)val; + } + + if (of_property_read_u32(np, "atmel,ts_sample_hold_time", &val) == 0) { + if (val > 0x0f) { + dev_err(&pdev->dev, "invalid ts sample hold time, 0x%02x\n", + val); + return -EINVAL; + } + pdata->ts_sample_hold_time = (u8)val; + } + + return 0; +} +#else +static int __devinit atmel_of_init_tsadcc(struct device_node *np, + struct at91_tsadcc_data *pdata, + struct platform_device *pdev) +{ + return -EINVAL; +} +#endif + /* * The functions for inserting/removing us as a module. */ @@ -181,7 +240,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) struct atmel_tsadcc *ts_dev; struct input_dev *input_dev; struct resource *res; - struct at91_tsadcc_data *pdata = pdev->dev.platform_data; + struct at91_tsadcc_data *pdata; int err = 0; unsigned int prsc; unsigned int reg; @@ -199,6 +258,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) return -ENOMEM; } platform_set_drvdata(pdev, ts_dev); + pdata = &ts_dev->board; input_dev = input_allocate_device(); if (!input_dev) { @@ -264,8 +324,16 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) prsc = clk_get_rate(ts_dev->clk); dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); - if (!pdata) - goto err_fail; + if (pdev->dev.of_node) { + err = atmel_of_init_tsadcc(pdev->dev.of_node, pdata, pdev); + if (err) + goto err_fail; + } else { + if (!pdev->dev.platform_data) + goto err_fail; + else + memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); + } if (!pdata->adc_clock) pdata->adc_clock = ADC_DEFAULT_CLOCK; @@ -374,11 +442,21 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_tsaddcc_dt_ids[] = { + { .compatible = "atmel,at91sam9x5-tsadcc"}, + { /* sentinel */ } +} + +MODULE_DEVICE_TABLE(of, atmel_tsaddcc_dt_ids); +#endif + static struct platform_driver atmel_tsadcc_driver = { .probe = atmel_tsadcc_probe, .remove = __devexit_p(atmel_tsadcc_remove), .driver = { .name = "atmel_tsadcc", + .of_match_table = of_match_ptr(atmel_tsaddcc_dt_ids), }, }; module_platform_driver(atmel_tsadcc_driver); From 9d2964c914253b949f9f78359dfb844617657dab Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Mon, 1 Nov 2010 16:38:41 +0800 Subject: [PATCH 0708/1071] video/atmel_lcdfb: add support for AT91SAM9x5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Josh Wu Signed-off-by: Dan Liang Signed-off-by: Nicolas Ferre [ukleinek: forward-port to 2.6.39-rcish] Signed-off-by: Uwe Kleine-König Conflicts: drivers/video/atmel_lcdfb.c --- .../arm/mach-at91/include/mach/atmel_hlcdfb.h | 865 ++++++++++++++++++ drivers/video/atmel_lcdfb.c | 668 ++++++++++---- include/video/atmel_lcdc.h | 15 + 3 files changed, 1389 insertions(+), 159 deletions(-) create mode 100644 arch/arm/mach-at91/include/mach/atmel_hlcdfb.h diff --git a/arch/arm/mach-at91/include/mach/atmel_hlcdfb.h b/arch/arm/mach-at91/include/mach/atmel_hlcdfb.h new file mode 100644 index 00000000000000..a57b79b720c101 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/atmel_hlcdfb.h @@ -0,0 +1,865 @@ +/* + * Header file for AT91 High end LCD Controller + * + * Data structure and register user interface + * + * Copyright (C) 2010 Atmel Corporation + * + * 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 PUROFFSETE. 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 __ATMEL_HLCD_H__ +#define __ATMEL_HLCD_H__ + +/* Lcdc hardware registers */ +#define ATMEL_LCDC_LCDCFG0 0x0000 +#define LCDC_LCDCFG0_CLKPOL (0x1 << 0) +#define LCDC_LCDCFG0_CLKSEL (0x1 << 2) +#define LCDC_LCDCFG0_CLKPWMSEL (0x1 << 3) +#define LCDC_LCDCFG0_CGDISBASE (0x1 << 8) +#define LCDC_LCDCFG0_CGDISOVR1 (0x1 << 9) +#define LCDC_LCDCFG0_CGDISHEO (0x1 << 11) +#define LCDC_LCDCFG0_CGDISHCR (0x1 << 12) +#define LCDC_LCDCFG0_CLKDIV_OFFSET 16 +#define LCDC_LCDCFG0_CLKDIV (0xff << LCDC_LCDCFG0_CLKDIV_OFFSET) + +#define ATMEL_LCDC_LCDCFG1 0x0004 +#define LCDC_LCDCFG1_HSPW_OFFSET 0 +#define LCDC_LCDCFG1_HSPW (0x3f << LCDC_LCDCFG1_HSPW_OFFSET) +#define LCDC_LCDCFG1_VSPW_OFFSET 16 +#define LCDC_LCDCFG1_VSPW (0x3f << LCDC_LCDCFG1_VSPW_OFFSET) + +#define ATMEL_LCDC_LCDCFG2 0x0008 +#define LCDC_LCDCFG2_VFPW_OFFSET 0 +#define LCDC_LCDCFG2_VFPW (0x3f << LCDC_LCDCFG2_VFPW_OFFSET) +#define LCDC_LCDCFG2_VBPW_OFFSET 16 +#define LCDC_LCDCFG2_VBPW (0x3f << LCDC_LCDCFG2_VBPW_OFFSET) + +#define ATMEL_LCDC_LCDCFG3 0x000C +#define LCDC_LCDCFG3_HFPW_OFFSET 0 +#define LCDC_LCDCFG3_HFPW (0xff << LCDC_LCDCFG3_HFPW_OFFSET) +#define LCDC_LCDCFG3_HBPW_OFFSET 16 +#define LCDC_LCDCFG3_HBPW (0xff << LCDC_LCDCFG3_HBPW_OFFSET) + +#define ATMEL_LCDC_LCDCFG4 0x0010 +#define LCDC_LCDCFG4_PPL_OFFSET 0 +#define LCDC_LCDCFG4_PPL (0x7ff << LCDC_LCDCFG4_PPL_OFFSET) +#define LCDC_LCDCFG4_RPF_OFFSET 16 +#define LCDC_LCDCFG4_RPF (0x7ff << LCDC_LCDCFG4_RPF_OFFSET) + +#define ATMEL_LCDC_LCDCFG5 0x0014 +#define LCDC_LCDCFG5_HSPOL (0x1 << 0) +#define LCDC_LCDCFG5_VSPOL (0x1 << 1) +#define LCDC_LCDCFG5_VSPDLYS (0x1 << 2) +#define LCDC_LCDCFG5_VSPDLYE (0x1 << 3) +#define LCDC_LCDCFG5_DISPPOL (0x1 << 4) +#define LCDC_LCDCFG5_SERIAL (0x1 << 5) +#define LCDC_LCDCFG5_DITHER (0x1 << 6) +#define LCDC_LCDCFG5_DISPDLY (0x1 << 7) +#define LCDC_LCDCFG5_MODE_OFFSET 8 +#define LCDC_LCDCFG5_MODE (0x3 << LCDC_LCDCFG5_MODE_OFFSET) +#define LCDC_LCDCFG5_MODE_OUTPUT_12BPP (0x0 << 8) +#define LCDC_LCDCFG5_MODE_OUTPUT_16BPP (0x1 << 8) +#define LCDC_LCDCFG5_MODE_OUTPUT_18BPP (0x2 << 8) +#define LCDC_LCDCFG5_MODE_OUTPUT_24BPP (0x3 << 8) +#define LCDC_LCDCFG5_VSPSU (0x1 << 12) +#define LCDC_LCDCFG5_VSPHO (0x1 << 13) +#define LCDC_LCDCFG5_GUARDTIME_OFFSET 16 +#define LCDC_LCDCFG5_GUARDTIME (0x1f << LCDC_LCDCFG5_GUARDTIME_OFFSET) + +#define ATMEL_LCDC_LCDCFG6 0x0018 +#define LCDC_LCDCFG6_PWMPS_OFFSET 0 +#define LCDC_LCDCFG6_PWMPS (0x7 << LCDC_LCDCFG6_PWMPS_OFFSET) +#define LCDC_LCDCFG6_PWMPOL (0x1 << 4) +#define LCDC_LCDCFG6_PWMCVAL_OFFSET 8 +#define LCDC_LCDCFG6_PWMCVAL (0xff << LCDC_LCDCFG6_PWMCVAL_OFFSET) + +#define ATMEL_LCDC_LCDEN 0x0020 +#define LCDC_LCDEN_CLKEN (0x1 << 0) +#define LCDC_LCDEN_SYNCEN (0x1 << 1) +#define LCDC_LCDEN_DISPEN (0x1 << 2) +#define LCDC_LCDEN_PWMEN (0x1 << 3) + +#define ATMEL_LCDC_LCDDIS 0x0024 +#define LCDC_LCDDIS_CLKDIS (0x1 << 0) +#define LCDC_LCDDIS_SYNCDIS (0x1 << 1) +#define LCDC_LCDDIS_DISPDIS (0x1 << 2) +#define LCDC_LCDDIS_PWMDIS (0x1 << 3) +#define LCDC_LCDDIS_CLKRST (0x1 << 8) +#define LCDC_LCDDIS_SYNCRST (0x1 << 9) +#define LCDC_LCDDIS_DISPRST (0x1 << 10) +#define LCDC_LCDDIS_PWMRST (0x1 << 11) + +#define ATMEL_LCDC_LCDSR 0x0028 +#define LCDC_LCDSR_CLKSTS (0x1 << 0) +#define LCDC_LCDSR_LCDSTS (0x1 << 1) +#define LCDC_LCDSR_DISPSTS (0x1 << 2) +#define LCDC_LCDSR_PWMSTS (0x1 << 3) +#define LCDC_LCDSR_SIPSTS (0x1 << 4) + +#define ATMEL_LCDC_LCDIER 0x002C +#define LCDC_LCDIER_SOFIE (0x1 << 0) +#define LCDC_LCDIER_DISIE (0x1 << 1) +#define LCDC_LCDIER_DISPIE (0x1 << 2) +#define LCDC_LCDIER_FIFOERRIE (0x1 << 4) +#define LCDC_LCDIER_BASEIE (0x1 << 8) +#define LCDC_LCDIER_OVR1IE (0x1 << 9) +#define LCDC_LCDIER_HEOIE (0x1 << 11) +#define LCDC_LCDIER_HCRIE (0x1 << 12) + +#define ATMEL_LCDC_LCDIDR 0x0030 +#define LCDC_LCDIDR_SOFID (0x1 << 0) +#define LCDC_LCDIDR_DISID (0x1 << 1) +#define LCDC_LCDIDR_DISPID (0x1 << 2) +#define LCDC_LCDIDR_FIFOERRID (0x1 << 4) +#define LCDC_LCDIDR_BASEID (0x1 << 8) +#define LCDC_LCDIDR_OVR1ID (0x1 << 9) +#define LCDC_LCDIDR_HEOID (0x1 << 11) +#define LCDC_LCDIDR_HCRID (0x1 << 12) + +#define ATMEL_LCDC_LCDIMR 0x0034 +#define LCDC_LCDIMR_SOFIM (0x1 << 0) +#define LCDC_LCDIMR_DISIM (0x1 << 1) +#define LCDC_LCDIMR_DISPIM (0x1 << 2) +#define LCDC_LCDIMR_FIFOERRIM (0x1 << 4) +#define LCDC_LCDIMR_BASEIM (0x1 << 8) +#define LCDC_LCDIMR_OVR1IM (0x1 << 9) +#define LCDC_LCDIMR_HEOIM (0x1 << 11) +#define LCDC_LCDIMR_HCRIM (0x1 << 12) + +#define ATMEL_LCDC_LCDISR 0x0038 +#define LCDC_LCDISR_SOF (0x1 << 0) +#define LCDC_LCDISR_DIS (0x1 << 1) +#define LCDC_LCDISR_DISP (0x1 << 2) +#define LCDC_LCDISR_FIFOERR (0x1 << 4) +#define LCDC_LCDISR_BASE (0x1 << 8) +#define LCDC_LCDISR_OVR1 (0x1 << 9) +#define LCDC_LCDISR_HEO (0x1 << 11) +#define LCDC_LCDISR_HCR (0x1 << 12) + +#define ATMEL_LCDC_BASECHER 0x0040 +#define LCDC_BASECHER_CHEN (0x1 << 0) +#define LCDC_BASECHER_UPDATEEN (0x1 << 1) +#define LCDC_BASECHER_A2QEN (0x1 << 2) + +#define ATMEL_LCDC_BASECHDR 0x0044 +#define LCDC_BASECHDR_CHDIS (0x1 << 0) +#define LCDC_BASECHDR_CHRST (0x1 << 8) + +#define ATMEL_LCDC_BASECHSR 0x0048 +#define LCDC_BASECHSR_CHSR (0x1 << 0) +#define LCDC_BASECHSR_UPDATESR (0x1 << 1) +#define LCDC_BASECHSR_A2QSR (0x1 << 2) + +#define ATMEL_LCDC_BASEIER 0x004C +#define LCDC_BASEIER_DMA (0x1 << 2) +#define LCDC_BASEIER_DSCR (0x1 << 3) +#define LCDC_BASEIER_ADD (0x1 << 4) +#define LCDC_BASEIER_DONE (0x1 << 5) +#define LCDC_BASEIER_OVR (0x1 << 6) + +#define ATMEL_LCDC_BASEIDR 0x0050 +#define LCDC_BASEIDR_DMA (0x1 << 2) +#define LCDC_BASEIDR_DSCR (0x1 << 3) +#define LCDC_BASEIDR_ADD (0x1 << 4) +#define LCDC_BASEIDR_DONE (0x1 << 5) +#define LCDC_BASEIDR_OVR (0x1 << 6) + +#define ATMEL_LCDC_BASEIMR 0x0054 +#define LCDC_BASEIMR_DMA (0x1 << 2) +#define LCDC_BASEIMR_DSCR (0x1 << 3) +#define LCDC_BASEIMR_ADD (0x1 << 4) +#define LCDC_BASEIMR_DONE (0x1 << 5) +#define LCDC_BASEIMR_OVR (0x1 << 6) + +#define ATMEL_LCDC_BASEISR 0x0058 +#define LCDC_BASEISR_DMA (0x1 << 2) +#define LCDC_BASEISR_DSCR (0x1 << 3) +#define LCDC_BASEISR_ADD (0x1 << 4) +#define LCDC_BASEISR_DONE (0x1 << 5) +#define LCDC_BASEISR_OVR (0x1 << 6) + +#define ATMEL_LCDC_BASEHEAD 0x005C + +#define ATMEL_LCDC_BASEADDR 0x0060 + +#define ATMEL_LCDC_BASECTRL 0x0064 +#define LCDC_BASECTRL_DFETCH (0x1 << 0) +#define LCDC_BASECTRL_LFETCH (0x1 << 1) +#define LCDC_BASECTRL_DMAIEN (0x1 << 2) +#define LCDC_BASECTRL_DSCRIEN (0x1 << 3) +#define LCDC_BASECTRL_ADDIEN (0x1 << 4) +#define LCDC_BASECTRL_DONEIEN (0x1 << 5) + +#define ATMEL_LCDC_BASENEXT 0x0068 + +#define ATMEL_LCDC_BASECFG0 0x006C +#define LCDC_BASECFG0_BLEN_OFFSET 4 +#define LCDC_BASECFG0_BLEN (0x3 << LCDC_BASECFG0_BLEN_OFFSET) +#define LCDC_BASECFG0_BLEN_AHB_SINGLE (0x0 << 4) +#define LCDC_BASECFG0_BLEN_AHB_INCR4 (0x1 << 4) +#define LCDC_BASECFG0_BLEN_AHB_INCR8 (0x2 << 4) +#define LCDC_BASECFG0_BLEN_AHB_INCR16 (0x3 << 4) +#define LCDC_BASECFG0_DLBO (0x1 << 8) + +#define ATMEL_LCDC_BASECFG1 0x0070 +#define LCDC_BASECFG1_CLUTEN (0x1 << 0) +#define LCDC_BASECFG1_RGBMODE_OFFSET 4 +#define LCDC_BASECFG1_RGBMODE (0xf << LCDC_BASECFG1_RGBMODE_OFFSET) +#define LCDC_BASECFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4) +#define LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4) +#define LCDC_BASECFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4) +#define LCDC_BASECFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4) +#define LCDC_BASECFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4) +#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4) +#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4) +#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4) +#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4) +#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4) +#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4) +#define LCDC_BASECFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4) +#define LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4) +#define LCDC_BASECFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4) +#define LCDC_BASECFG1_CLUTMODE_OFFSET 8 +#define LCDC_BASECFG1_CLUTMODE (0x3 << LCDC_BASECFG1_CLUTMODE_OFFSET) +#define LCDC_BASECFG1_CLUTMODE_1BPP (0x0 << 8) +#define LCDC_BASECFG1_CLUTMODE_2BPP (0x1 << 8) +#define LCDC_BASECFG1_CLUTMODE_4BPP (0x2 << 8) +#define LCDC_BASECFG1_CLUTMODE_8BPP (0x3 << 8) + +#define ATMEL_LCDC_BASECFG2 0x0074 + +#define ATMEL_LCDC_BASECFG3 0x0078 +#define LCDC_BASECFG3_BDEF_OFFSET 0 +#define LCDC_BASECFG3_BDEF (0xff << LCDC_BASECFG3_BDEF_OFFSET) +#define LCDC_BASECFG3_GDEF_OFFSET 8 +#define LCDC_BASECFG3_GDEF (0xff << LCDC_BASECFG3_GDEF_OFFSET) +#define LCDC_BASECFG3_RDEF_OFFSET 16 +#define LCDC_BASECFG3_RDEF (0xff << LCDC_BASECFG3_RDEF_OFFSET) + +#define ATMEL_LCDC_BASECFG4 0x007C +#define LCDC_BASECFG4_DMA (0x1 << 8) +#define LCDC_BASECFG4_REP (0x1 << 9) + +#define ATMEL_LCDC_OVRCHER1 0x0100 +#define LCDC_OVRCHER1_CHEN (0x1 << 0) +#define LCDC_OVRCHER1_UPDATEEN (0x1 << 1) +#define LCDC_OVRCHER1_A2QEN (0x1 << 2) + +#define ATMEL_LCDC_OVRCHDR1 0x0104 +#define LCDC_OVRCHDR1_CHDIS (0x1 << 0) +#define LCDC_OVRCHDR1_CHRST (0x1 << 8) + +#define ATMEL_LCDC_OVRCHSR1 0x0108 +#define LCDC_OVRCHSR1_CHSR (0x1 << 0) +#define LCDC_OVRCHSR1_UPDATESR (0x1 << 1) +#define LCDC_OVRCHSR1_A2QSR (0x1 << 2) + +#define ATMEL_LCDC_OVRIER1 0x010C +#define LCDC_OVRIER1_DMA (0x1 << 2) +#define LCDC_OVRIER1_DSCR (0x1 << 3) +#define LCDC_OVRIER1_ADD (0x1 << 4) +#define LCDC_OVRIER1_DONE (0x1 << 5) +#define LCDC_OVRIER1_OVR (0x1 << 6) + +#define ATMEL_LCDC_OVRIDR1 0x0110 +#define LCDC_OVRIDR1_DMA (0x1 << 2) +#define LCDC_OVRIDR1_DSCR (0x1 << 3) +#define LCDC_OVRIDR1_ADD (0x1 << 4) +#define LCDC_OVRIDR1_DONE (0x1 << 5) +#define LCDC_OVRIDR1_OVR (0x1 << 6) + +#define ATMEL_LCDC_OVRIMR1 0x0114 +#define LCDC_OVRIMR1_DMA (0x1 << 2) +#define LCDC_OVRIMR1_DSCR (0x1 << 3) +#define LCDC_OVRIMR1_ADD (0x1 << 4) +#define LCDC_OVRIMR1_DONE (0x1 << 5) +#define LCDC_OVRIMR1_OVR (0x1 << 6) + +#define ATMEL_LCDC_OVRISR1 0x0118 +#define LCDC_OVRISR1_DMA (0x1 << 2) +#define LCDC_OVRISR1_DSCR (0x1 << 3) +#define LCDC_OVRISR1_ADD (0x1 << 4) +#define LCDC_OVRISR1_DONE (0x1 << 5) +#define LCDC_OVRISR1_OVR (0x1 << 6) + +#define ATMEL_LCDC_OVRHEAD1 0x011C + +#define ATMEL_LCDC_OVRADDR1 0x0120 + +#define ATMEL_LCDC_OVRCTRL1 0x0124 +#define LCDC_OVRCTRL1_DFETCH (0x1 << 0) +#define LCDC_OVRCTRL1_LFETCH (0x1 << 1) +#define LCDC_OVRCTRL1_DMAIEN (0x1 << 2) +#define LCDC_OVRCTRL1_DSCRIEN (0x1 << 3) +#define LCDC_OVRCTRL1_ADDIEN (0x1 << 4) +#define LCDC_OVRCTRL1_DONEIEN (0x1 << 5) + +#define ATMEL_LCDC_OVRNEXT1 0x0128 + +#define ATMEL_LCDC_OVR1CFG0 0x012C +#define LCDC_OVR1CFG0_BLEN_OFFSET 4 +#define LCDC_OVR1CFG0_BLEN (0x3 << LCDC_OVR1CFG0_BLEN_OFFSET) +#define LCDC_OVR1CFG0_BLEN_AHB_SINGLE (0x0 << 4) +#define LCDC_OVR1CFG0_BLEN_AHB_INCR4 (0x1 << 4) +#define LCDC_OVR1CFG0_BLEN_AHB_INCR8 (0x2 << 4) +#define LCDC_OVR1CFG0_BLEN_AHB_INCR16 (0x3 << 4) +#define LCDC_OVR1CFG0_DLBO (0x1 << 8) +#define LCDC_OVR1CFG0_ROTDIS (0x1 << 12) +#define LCDC_OVR1CFG0_LOCKDIS (0x1 << 13) + +#define ATMEL_LCDC_OVR1CFG1 0x0130 +#define LCDC_OVR1CFG1_CLUTEN (0x1 << 0) +#define LCDC_OVR1CFG1_RGBMODE_OFFSET 4 +#define LCDC_OVR1CFG1_RGBMODE (0xf << LCDC_OVR1CFG1_RGBMODE_OFFSET) +#define LCDC_OVR1CFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4) +#define LCDC_OVR1CFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4) +#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4) +#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4) +#define LCDC_OVR1CFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4) +#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4) +#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4) +#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4) +#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4) +#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4) +#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4) +#define LCDC_OVR1CFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4) +#define LCDC_OVR1CFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4) +#define LCDC_OVR1CFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4) +#define LCDC_OVR1CFG1_CLUTMODE_OFFSET 8 +#define LCDC_OVR1CFG1_CLUTMODE (0x3 << LCDC_OVR1CFG1_CLUTMODE_OFFSET) +#define LCDC_OVR1CFG1_CLUTMODE_1BPP (0x0 << 8) +#define LCDC_OVR1CFG1_CLUTMODE_2BPP (0x1 << 8) +#define LCDC_OVR1CFG1_CLUTMODE_4BPP (0x2 << 8) +#define LCDC_OVR1CFG1_CLUTMODE_8BPP (0x3 << 8) + +#define ATMEL_LCDC_OVR1CFG2 0x0134 +#define LCDC_OVR1CFG2_XOFFSET_OFFSET 0 +#define LCDC_OVR1CFG2_XOFFSET (0x7ff << LCDC_OVR1CFG2_XOFFSET_OFFSET) +#define LCDC_OVR1CFG2_YOFFSET_OFFSET 16 +#define LCDC_OVR1CFG2_YOFFSET (0x7ff << LCDC_OVR1CFG2_YOFFSET_OFFSET) + +#define ATMEL_LCDC_OVR1CFG3 0x0138 +#define LCDC_OVR1CFG3_XSIZE_OFFSET 0 +#define LCDC_OVR1CFG3_XSIZE (0x7ff << LCDC_OVR1CFG3_XSIZE_OFFSET) +#define LCDC_OVR1CFG3_YSIZE_OFFSET 16 +#define LCDC_OVR1CFG3_YSIZE (0x7ff << LCDC_OVR1CFG3_YSIZE_OFFSET) + +#define ATMEL_LCDC_OVR1CFG4 0x013C + +#define ATMEL_LCDC_OVR1CFG5 0x0140 + +#define ATMEL_LCDC_OVR1CFG6 0x0144 +#define LCDC_OVR1CFG6_BDEF_OFFSET 0 +#define LCDC_OVR1CFG6_BDEF (0xff << LCDC_OVR1CFG6_BDEF_OFFSET) +#define LCDC_OVR1CFG6_GDEF_OFFSET 8 +#define LCDC_OVR1CFG6_GDEF (0xff << LCDC_OVR1CFG6_GDEF_OFFSET) +#define LCDC_OVR1CFG6_RDEF_OFFSET 16 +#define LCDC_OVR1CFG6_RDEF (0xff << LCDC_OVR1CFG6_RDEF_OFFSET) + +#define ATMEL_LCDC_OVR1CFG7 0x0148 +#define LCDC_OVR1CFG7_BKEY_OFFSET 0 +#define LCDC_OVR1CFG7_BKEY (0xff << LCDC_OVR1CFG7_BKEY_OFFSET) +#define LCDC_OVR1CFG7_GKEY_OFFSET 8 +#define LCDC_OVR1CFG7_GKEY (0xff << LCDC_OVR1CFG7_GKEY_OFFST) +#define LCDC_OVR1CFG7_RKEY_OFFSET 16 +#define LCDC_OVR1CFG7_RKEY (0xff << LCDC_OVR1CFG7_RKEY_OFFSET) + +#define ATMEL_LCDC_OVR1CFG8 0x014C +#define LCDC_OVR1CFG8_BMASK_OFFSET 0 +#define LCDC_OVR1CFG8_BMASK (0xff << LCDC_OVR1CFG8_BMASK_OFFSET) +#define LCDC_OVR1CFG8_GMASK_OFFSET 8 +#define LCDC_OVR1CFG8_GMASK (0xff << LCDC_OVR1CFG8_GMASK_OFFSET) +#define LCDC_OVR1CFG8_RMASK_OFFSET 16 +#define LCDC_OVR1CFG8_RMASK (0xff << LCDC_OVR1CFG8_RMASK_OFFSET) + +#define ATMEL_LCDC_OVR1CFG9 0x0150 +#define LCDC_OVR1CFG9_CRKEY (0x1 << 0) +#define LCDC_OVR1CFG9_INV (0x1 << 1) +#define LCDC_OVR1CFG9_ITER2BL (0x1 << 2) +#define LCDC_OVR1CFG9_ITER (0x1 << 3) +#define LCDC_OVR1CFG9_REVALPHA (0x1 << 4) +#define LCDC_OVR1CFG9_GAEN (0x1 << 5) +#define LCDC_OVR1CFG9_LAEN (0x1 << 6) +#define LCDC_OVR1CFG9_OVR (0x1 << 7) +#define LCDC_OVR1CFG9_DMA (0x1 << 8) +#define LCDC_OVR1CFG9_REP (0x1 << 9) +#define LCDC_OVR1CFG9_DSTKEY (0x1 << 10) +#define LCDC_OVR1CFG9_GA_OFFSET 16 +#define LCDC_OVR1CFG9_GA (0xff << LCDC_OVR1CFG9_GA_OFFSET) + +#define ATMEL_LCDC_HEOCHER 0x0280 +#define LCDC_HEOCHER_CHEN (0x1 << 0) +#define LCDC_HEOCHER_UPDATEEN (0x1 << 1) +#define LCDC_HEOCHER_A2QEN (0x1 << 2) + +#define ATMEL_LCDC_HEOCHDR 0x0284 +#define LCDC_HEOCHDR_CHDIS (0x1 << 0) +#define LCDC_HEOCHDR_CHRST (0x1 << 8) + +#define ATMEL_LCDC_HEOCHSR 0x0288 +#define LCDC_HEOCHSR_CHSR (0x1 << 0) +#define LCDC_HEOCHSR_UPDATESR (0x1 << 1) +#define LCDC_HEOCHSR_A2QSR (0x1 << 2) + +#define ATMEL_LCDC_HEOIER 0x028C +#define LCDC_HEOIER_DMA (0x1 << 2) +#define LCDC_HEOIER_DSCR (0x1 << 3) +#define LCDC_HEOIER_ADD (0x1 << 4) +#define LCDC_HEOIER_DONE (0x1 << 5) +#define LCDC_HEOIER_OVR (0x1 << 6) +#define LCDC_HEOIER_UDMA (0x1 << 10) +#define LCDC_HEOIER_UDSCR (0x1 << 11) +#define LCDC_HEOIER_UADD (0x1 << 12) +#define LCDC_HEOIER_UDONE (0x1 << 13) +#define LCDC_HEOIER_UOVR (0x1 << 14) +#define LCDC_HEOIER_VDMA (0x1 << 18) +#define LCDC_HEOIER_VDSCR (0x1 << 19) +#define LCDC_HEOIER_VADD (0x1 << 20) +#define LCDC_HEOIER_VDONE (0x1 << 21) +#define LCDC_HEOIER_VOVR (0x1 << 22) + +#define ATMEL_LCDC_HEOIDR 0x0290 +#define LCDC_HEOIDR_DMA (0x1 << 2) +#define LCDC_HEOIDR_DSCR (0x1 << 3) +#define LCDC_HEOIDR_ADD (0x1 << 4) +#define LCDC_HEOIDR_DONE (0x1 << 5) +#define LCDC_HEOIDR_OVR (0x1 << 6) +#define LCDC_HEOIDR_UDMA (0x1 << 10) +#define LCDC_HEOIDR_UDSCR (0x1 << 11) +#define LCDC_HEOIDR_UADD (0x1 << 12) +#define LCDC_HEOIDR_UDONE (0x1 << 13) +#define LCDC_HEOIDR_UOVR (0x1 << 14) +#define LCDC_HEOIDR_VDMA (0x1 << 18) +#define LCDC_HEOIDR_VDSCR (0x1 << 19) +#define LCDC_HEOIDR_VADD (0x1 << 20) +#define LCDC_HEOIDR_VDONE (0x1 << 21) +#define LCDC_HEOIDR_VOVR (0x1 << 22) + +#define ATMEL_LCDC_HEOIMR 0x0294 +#define LCDC_HEOIMR_DMA (0x1 << 2) +#define LCDC_HEOIMR_DSCR (0x1 << 3) +#define LCDC_HEOIMR_ADD (0x1 << 4) +#define LCDC_HEOIMR_DONE (0x1 << 5) +#define LCDC_HEOIMR_OVR (0x1 << 6) +#define LCDC_HEOIMR_UDMA (0x1 << 10) +#define LCDC_HEOIMR_UDSCR (0x1 << 11) +#define LCDC_HEOIMR_UADD (0x1 << 12) +#define LCDC_HEOIMR_UDONE (0x1 << 13) +#define LCDC_HEOIMR_UOVR (0x1 << 14) +#define LCDC_HEOIMR_VDMA (0x1 << 18) +#define LCDC_HEOIMR_VDSCR (0x1 << 19) +#define LCDC_HEOIMR_VADD (0x1 << 20) +#define LCDC_HEOIMR_VDONE (0x1 << 21) +#define LCDC_HEOIMR_VOVR (0x1 << 22) + +#define ATMEL_LCDC_HEOISR 0x0298 +#define LCDC_HEOISR_DMA (0x1 << 2) +#define LCDC_HEOISR_DSCR (0x1 << 3) +#define LCDC_HEOISR_ADD (0x1 << 4) +#define LCDC_HEOISR_DONE (0x1 << 5) +#define LCDC_HEOISR_OVR (0x1 << 6) +#define LCDC_HEOISR_UDMA (0x1 << 10) +#define LCDC_HEOISR_UDSCR (0x1 << 11) +#define LCDC_HEOISR_UADD (0x1 << 12) +#define LCDC_HEOISR_UDONE (0x1 << 13) +#define LCDC_HEOISR_UOVR (0x1 << 14) +#define LCDC_HEOISR_VDMA (0x1 << 18) +#define LCDC_HEOISR_VDSCR (0x1 << 19) +#define LCDC_HEOISR_VADD (0x1 << 20) +#define LCDC_HEOISR_VDONE (0x1 << 21) +#define LCDC_HEOISR_VOVR (0x1 << 22) + +#define ATMEL_LCDC_HEOHEAD 0x029C + +#define ATMEL_LCDC_HEOADDR 0x02A0 + +#define ATMEL_LCDC_HEOCTRL 0x02A4 +#define LCDC_HEOCTRL_DFETCH (0x1 << 0) +#define LCDC_HEOCTRL_LFETCH (0x1 << 1) +#define LCDC_HEOCTRL_DMAIEN (0x1 << 2) +#define LCDC_HEOCTRL_DSCRIEN (0x1 << 3) +#define LCDC_HEOCTRL_ADDIEN (0x1 << 4) +#define LCDC_HEOCTRL_DONEIEN (0x1 << 5) + +#define ATMEL_LCDC_HEONEXT 0x02A8 + +#define ATMEL_LCDC_HEOUHEAD 0x02AC + +#define ATMEL_LCDC_HEOUADDR 0x02B0 + +#define ATMEL_LCDC_HEOUCTRL 0x02B4 +#define LCDC_HEOUCTRL_UDFETCH (0x1 << 0) +#define LCDC_HEOUCTRL_UDMAIEN (0x1 << 2) +#define LCDC_HEOUCTRL_UDSCRIEN (0x1 << 3) +#define LCDC_HEOUCTRL_UADDIEN (0x1 << 4) +#define LCDC_HEOUCTRL_UDONEIEN (0x1 << 5) + +#define ATMEL_LCDC_HEOUNEXT 0x02B8 + +#define ATMEL_LCDC_HEOVHEAD 0x02BC + +#define ATMEL_LCDC_HEOVADDR 0x02C0 + +#define ATMEL_LCDC_HEOVCTRL 0x02C4 +#define LCDC_HEOVCTRL_VDFETCH (0x1 << 0) +#define LCDC_HEOVCTRL_VDMAIEN (0x1 << 2) +#define LCDC_HEOVCTRL_VDSCRIEN (0x1 << 3) +#define LCDC_HEOVCTRL_VADDIEN (0x1 << 4) +#define LCDC_HEOVCTRL_VDONEIEN (0x1 << 5) + +#define ATMEL_LCDC_HEOVNEXT 0x02C8 + +#define ATMEL_LCDC_HEOCFG0 0x02CC +#define LCDC_HEOCFG0_BLEN_OFFSET 4 +#define LCDC_HEOCFG0_BLEN (0x3 << LCDC_HEOCFG0_BLEN_OFFSET) +#define LCDC_HEOCFG0_BLEN_AHB_SINGLE (0x0 << 4) +#define LCDC_HEOCFG0_BLEN_AHB_INCR4 (0x1 << 4) +#define LCDC_HEOCFG0_BLEN_AHB_INCR8 (0x2 << 4) +#define LCDC_HEOCFG0_BLEN_AHB_INCR16 (0x3 << 4) +#define LCDC_HEOCFG0_BLENUV_OFFSET 6 +#define LCDC_HEOCFG0_BLENUV (0x3 << LCDC_HEOCFG0_BLENUV_OFFSET) +#define LCDC_HEOCFG0_BLENUV_AHB_SINGLE (0x0 << 6) +#define LCDC_HEOCFG0_BLENUV_AHB_INCR4 (0x1 << 6) +#define LCDC_HEOCFG0_BLENUV_AHB_INCR8 (0x2 << 6) +#define LCDC_HEOCFG0_BLENUV_AHB_INCR16 (0x3 << 6) +#define LCDC_HEOCFG0_DLBO (0x1 << 8) +#define LCDC_HEOCFG0_ROTDIS (0x1 << 12) +#define LCDC_HEOCFG0_LOCKDIS (0x1 << 13) + +#define ATMEL_LCDC_HEOCFG1 0x02D0 +#define LCDC_HEOCFG1_CLUTEN (0x1 << 0) +#define LCDC_HEOCFG1_YUVEN (0x1 << 1) +#define LCDC_HEOCFG1_RGBMODE_OFFSET 4 +#define LCDC_HEOCFG1_RGBMODE (0xf << LCDC_HEOCFG1_RGBMODE_OFFSET) +#define LCDC_HEOCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4) +#define LCDC_HEOCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4) +#define LCDC_HEOCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4) +#define LCDC_HEOCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4) +#define LCDC_HEOCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4) +#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4) +#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4) +#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4) +#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4) +#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4) +#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4) +#define LCDC_HEOCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4) +#define LCDC_HEOCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4) +#define LCDC_HEOCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4) +#define LCDC_HEOCFG1_CLUTMODE_OFFSET 8 +#define LCDC_HEOCFG1_CLUTMODE (0x3 << LCDC_HEOCFG1_CLUTMODE_OFFSET) +#define LCDC_HEOCFG1_CLUTMODE_1BPP (0x0 << 8) +#define LCDC_HEOCFG1_CLUTMODE_2BPP (0x1 << 8) +#define LCDC_HEOCFG1_CLUTMODE_4BPP (0x2 << 8) +#define LCDC_HEOCFG1_CLUTMODE_8BPP (0x3 << 8) +#define LCDC_HEOCFG1_YUVMODE_OFFSET 12 +#define LCDC_HEOCFG1_YUVMODE (0xf << LCDC_HEOCFG1_YUVMODE_OFFSET) +#define LCDC_HEOCFG1_YUVMODE_32BPP_AYCBCR (0x0 << 12) +#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE0 (0x1 << 12) +#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE1 (0x2 << 12) +#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE2 (0x3 << 12) +#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE3 (0x4 << 12) +#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_SEMIPLANAR (0x5 << 12) +#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_PLANAR (0x6 << 12) +#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_SEMIPLANAR (0x7 << 12) +#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_PLANAR (0x8 << 12) +#define LCDC_HEOCFG1_YUV422ROT (0x1 << 16) +#define LCDC_HEOCFG1_YUV422SWP (0x1 << 17) + +#define ATMEL_LCDC_HEOCFG2 0x02D4 +#define LCDC_HEOCFG2_XOFFSET_OFFSET 0 +#define LCDC_HEOCFG2_XOFFSET (0x7ff << LCDC_HEOCFG2_XOFFSET_OFFSET) +#define LCDC_HEOCFG2_YOFFSET_OFFSET 16 +#define LCDC_HEOCFG2_YOFFSET (0x7ff << LCDC_HEOCFG2_YOFFSET_OFFSET) + +#define ATMEL_LCDC_HEOCFG3 0x02D8 +#define LCDC_HEOCFG3_XSIZE_OFFSET 0 +#define LCDC_HEOCFG3_XSIZE (0x7ff << LCDC_HEOCFG3_XSIZE_OFFSET) +#define LCDC_HEOCFG3_YSIZE_OFFSET 16 +#define LCDC_HEOCFG3_YSIZE (0x7ff << LCDC_HEOCFG3_YSIZE_OFFSET) + +#define ATMEL_LCDC_HEOCFG4 0x02DC +#define LCDC_HEOCFG4_XMEM_SIZE_OFFSET 0 +#define LCDC_HEOCFG4_XMEM_SIZE (0x7ff << LCDC_HEOCFG4_XMEM_SIZE_OFFSET) +#define LCDC_HEOCFG4_YMEM_SIZE_OFFSET 16 +#define LCDC_HEOCFG4_YMEM_SIZE (0x7ff << LCDC_HEOCFG4_YMEM_SIZE_OFFSET) + +#define ATMEL_LCDC_HEOCFG5 0x02E0 + +#define ATMEL_LCDC_HEOCFG6 0x02E4 + +#define ATMEL_LCDC_HEOCFG7 0x02E8 + +#define ATMEL_LCDC_HEOCFG8 0x02EC + +#define ATMEL_LCDC_HEOCFG9 0x02F0 +#define LCDC_HEOCFG9_BDEF_OFFSET 0 +#define LCDC_HEOCFG9_BDEF (0xff << LCDC_HEOCFG9_BDEF_OFFSET) +#define LCDC_HEOCFG9_GDEF_OFFSET 8 +#define LCDC_HEOCFG9_GDEF (0xff << LCDC_HEOCFG9_GDEF_OFFSET) +#define LCDC_HEOCFG9_RDEF_OFFSET 16 +#define LCDC_HEOCFG9_RDEF (0xff << LCDC_HEOCFG9_RDEF_OFFSET) + +#define ATMEL_LCDC_HEOCFG10 0x02F4 +#define LCDC_HEOCFG10_BKEY_OFFSET 0 +#define LCDC_HEOCFG10_BKEY (0xff << LCDC_HEOCFG10_BKEY_OFFSET) +#define LCDC_HEOCFG10_GKEY_OFFSET 8 +#define LCDC_HEOCFG10_GKEY (0xff << LCDC_HEOCFG10_GKEY_OFFSET) +#define LCDC_HEOCFG10_RKEY_OFFSET 16 +#define LCDC_HEOCFG10_RKEY (0xff << LCDC_HEOCFG10_RKEY_OFFSET) + +#define ATMEL_LCDC_HEOCFG11 0x02F8 +#define LCDC_HEOCFG11_BMASK_OFFSET 0 +#define LCDC_HEOCFG11_BMASK (0xff << LCDC_HEOCFG11_BMASK_OFFSET) +#define LCDC_HEOCFG11_GMASK_OFFSET 8 +#define LCDC_HEOCFG11_GMASK (0xff << LCDC_HEOCFG11_GMASK_OFFSET) +#define LCDC_HEOCFG11_RMASK_OFFSET 16 +#define LCDC_HEOCFG11_RMASK (0xff << LCDC_HEOCFG11_RMASK_OFFSET) + +#define ATMEL_LCDC_HEOCFG12 0x02FC +#define LCDC_HEOCFG12_CRKEY (0x1 << 0) +#define LCDC_HEOCFG12_INV (0x1 << 1) +#define LCDC_HEOCFG12_ITER2BL (0x1 << 2) +#define LCDC_HEOCFG12_ITER (0x1 << 3) +#define LCDC_HEOCFG12_REVALPHA (0x1 << 4) +#define LCDC_HEOCFG12_GAEN (0x1 << 5) +#define LCDC_HEOCFG12_LAEN (0x1 << 6) +#define LCDC_HEOCFG12_OVR (0x1 << 7) +#define LCDC_HEOCFG12_DMA (0x1 << 8) +#define LCDC_HEOCFG12_REP (0x1 << 9) +#define LCDC_HEOCFG12_DSTKEY (0x1 << 10) +#define LCDC_HEOCFG12_VIDPRI (0x1 << 12) +#define LCDC_HEOCFG12_GA_OFFSET 16 +#define LCDC_HEOCFG12_GA (0xff << LCDC_HEOCFG12_GA_OFFSET) + +#define ATMEL_LCDC_HEOCFG13 0x0300 +#define LCDC_HEOCFG13_XFACTOR_OFFSET 0 +#define LCDC_HEOCFG13_XFACTOR (0x1fff << LCDC_HEOCFG13_XFACTOR_OFFSET) +#define LCDC_HEOCFG13_YFACTOR_OFFSET 16 +#define LCDC_HEOCFG13_YFACTOR (0x1fff << LCDC_HEOCFG13_YFACTOR_OFFSET) +#define LCDC_HEOCFG13_SCALEN (0x1 << 31) + +#define ATMEL_LCDC_HEOCFG14 0x0304 +#define LCDC_HEOCFG14_CSCRY_OFFSET 0 +#define LCDC_HEOCFG14_CSCRY (0x3ff << LCDC_HEOCFG14_CSCRY_OFFSET) +#define LCDC_HEOCFG14_CSCRU_OFFSET 10 +#define LCDC_HEOCFG14_CSCRU (0x3ff << LCDC_HEOCFG14_CSCRU_OFFSET) +#define LCDC_HEOCFG14_CSCRV_OFFSET 20 +#define LCDC_HEOCFG14_CSCRV (0x3ff << LCDC_HEOCFG14_CSCRV_OFFSET) +#define LCDC_HEOCFG14_CSCYOFF (0x1 << 30) + +#define ATMEL_LCDC_HEOCFG15 0x0308 +#define LCDC_HEOCFG15_CSCGY_OFFSET 0 +#define LCDC_HEOCFG15_CSCGY (0x3ff << LCDC_HEOCFG15_CSCGY_OFFSET) +#define LCDC_HEOCFG15_CSCGU_OFFSET 10 +#define LCDC_HEOCFG15_CSCGU (0x3ff << LCDC_HEOCFG15_CSCGU_OFFSET) +#define LCDC_HEOCFG15_CSCGV_OFFSET 20 +#define LCDC_HEOCFG15_CSCGV (0x3ff << LCDC_HEOCFG15_CSCGV_OFFSET) +#define LCDC_HEOCFG15_CSCUOFF (0x1 << 30) + +#define ATMEL_LCDC_HEOCFG16 0x030C +#define LCDC_HEOCFG16_CSCBY_OFFSET 0 +#define LCDC_HEOCFG16_CSCBY (0x3ff << LCDC_HEOCFG16_CSCBY_OFFSET) +#define LCDC_HEOCFG16_CSCBU_OFFSET 10 +#define LCDC_HEOCFG16_CSCBU (0x3ff << LCDC_HEOCFG16_CSCBU_OFFSET) +#define LCDC_HEOCFG16_CSCBV_OFFSET 20 +#define LCDC_HEOCFG16_CSCBV (0x3ff << LCDC_HEOCFG16_CSCBV_OFFSET) +#define LCDC_HEOCFG16_CSCVOFF (0x1 << 30) + +#define ATMEL_LCDC_HCRCHER 0x0340 +#define LCDC_HCRCHER_CHEN (0x1 << 0) +#define LCDC_HCRCHER_UPDATEEN (0x1 << 1) +#define LCDC_HCRCHER_A2QEN (0x1 << 2) + +#define ATMEL_LCDC_HCRCHDR 0x0344 +#define LCDC_HCRCHDR_CHDIS (0x1 << 0) +#define LCDC_HCRCHDR_CHRST (0x1 << 8) + +#define ATMEL_LCDC_HCRCHSR 0x0348 +#define LCDC_HCRCHSR_CHSR (0x1 << 0) +#define LCDC_HCRCHSR_UPDATESR (0x1 << 1) +#define LCDC_HCRCHSR_A2QSR (0x1 << 2) + +#define ATMEL_LCDC_HCRIER 0x034C +#define LCDC_HCRIER_DMA (0x1 << 2) +#define LCDC_HCRIER_DSCR (0x1 << 3) +#define LCDC_HCRIER_ADD (0x1 << 4) +#define LCDC_HCRIER_DONE (0x1 << 5) +#define LCDC_HCRIER_OVR (0x1 << 6) + +#define ATMEL_LCDC_HCRIDR 0x0350 +#define LCDC_HCRIDR_DMA (0x1 << 2) +#define LCDC_HCRIDR_DSCR (0x1 << 3) +#define LCDC_HCRIDR_ADD (0x1 << 4) +#define LCDC_HCRIDR_DONE (0x1 << 5) +#define LCDC_HCRIDR_OVR (0x1 << 6) + +#define ATMEL_LCDC_HCRIMR 0x0354 +#define LCDC_HCRIMR_DMA (0x1 << 2) +#define LCDC_HCRIMR_DSCR (0x1 << 3) +#define LCDC_HCRIMR_ADD (0x1 << 4) +#define LCDC_HCRIMR_DONE (0x1 << 5) +#define LCDC_HCRIMR_OVR (0x1 << 6) + +#define ATMEL_LCDC_HCRISR 0x0358 +#define LCDC_HCRISR_DMA (0x1 << 2) +#define LCDC_HCRISR_DSCR (0x1 << 3) +#define LCDC_HCRISR_ADD (0x1 << 4) +#define LCDC_HCRISR_DONE (0x1 << 5) +#define LCDC_HCRISR_OVR (0x1 << 6) + +#define ATMEL_LCDC_HCRHEAD 0x035C + +#define ATMEL_LCDC_HCRADDR 0x0360 + +#define ATMEL_LCDC_HCRCTRL 0x0364 +#define LCDC_HCRCTRL_DFETCH (0x1 << 0) +#define LCDC_HCRCTRL_LFETCH (0x1 << 1) +#define LCDC_HCRCTRL_DMAIEN (0x1 << 2) +#define LCDC_HCRCTRL_DSCRIEN (0x1 << 3) +#define LCDC_HCRCTRL_ADDIEN (0x1 << 4) +#define LCDC_HCRCTRL_DONEIEN (0x1 << 5) + +#define ATMEL_LCDC_HCRNEXT 0x0368 + +#define ATMEL_LCDC_HCRCFG0 0x036C +#define LCDC_HCRCFG0_BLEN_OFFSET 4 +#define LCDC_HCRCFG0_BLEN (0x3 << LCDC_HCRCFG0_BLEN_OFFSET) +#define LCDC_HCRCFG0_BLEN_AHB_SINGLE (0x0 << 4) +#define LCDC_HCRCFG0_BLEN_AHB_INCR4 (0x1 << 4) +#define LCDC_HCRCFG0_BLEN_AHB_INCR8 (0x2 << 4) +#define LCDC_HCRCFG0_BLEN_AHB_INCR16 (0x3 << 4) +#define LCDC_HCRCFG0_DLBO (0x1 << 8) + +#define ATMEL_LCDC_HCRCFG1 0x0370 +#define LCDC_HCRCFG1_CLUTEN (0x1 << 0) +#define LCDC_HCRCFG1_RGBMODE_OFFSET 4 +#define LCDC_HCRCFG1_RGBMODE (0xf << LCDC_HCRCFG1_RGBMODE_OFFSET) +#define LCDC_HCRCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4) +#define LCDC_HCRCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4) +#define LCDC_HCRCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4) +#define LCDC_HCRCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4) +#define LCDC_HCRCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4) +#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4) +#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4) +#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4) +#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4) +#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4) +#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4) +#define LCDC_HCRCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4) +#define LCDC_HCRCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4) +#define LCDC_HCRCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4) +#define LCDC_HCRCFG1_CLUTMODE_OFFSET 8 +#define LCDC_HCRCFG1_CLUTMODE (0x3 << LCDC_HCRCFG1_CLUTMODE_OFFSET) +#define LCDC_HCRCFG1_CLUTMODE_1BPP (0x0 << 8) +#define LCDC_HCRCFG1_CLUTMODE_2BPP (0x1 << 8) +#define LCDC_HCRCFG1_CLUTMODE_4BPP (0x2 << 8) +#define LCDC_HCRCFG1_CLUTMODE_8BPP (0x3 << 8) + +#define ATMEL_LCDC_HCRCFG2 0x0374 +#define LCDC_HCRCFG2_XOFFSET_OFFSET 0 +#define LCDC_HCRCFG2_XOFFSET (0x7ff << LCDC_HCRCFG2_XOFFSET_OFFSET) +#define LCDC_HCRCFG2_YOFFSET_OFFSET 16 +#define LCDC_HCRCFG2_YOFFSET (0x7ff << LCDC_HCRCFG2_YOFFSET_OFFSET) + +#define ATMEL_LCDC_HCRCFG3 0x0378 +#define LCDC_HCRCFG3_XSIZE_OFFSET 0 +#define LCDC_HCRCFG3_XSIZE (0x7f << LCDC_HCRCFG3_XSIZE_OFFSET) +#define LCDC_HCRCFG3_YSIZE_OFFSET 16 +#define LCDC_HCRCFG3_YSIZE (0x7f << LCDC_HCRCFG3_YSIZE_OFFSET) + +#define ATMEL_LCDC_HCRCFG4 0x037C + +#define ATMEL_LCDC_HCRCFG6 0x0384 +#define LCDC_HCRCFG6_BDEF_OFFSET 0 +#define LCDC_HCRCFG6_BDEF (0xff << LCDC_HCRCFG6_BDEF_OFFSET) +#define LCDC_HCRCFG6_GDEF_OFFSET 8 +#define LCDC_HCRCFG6_GDEF (0xff << LCDC_HCRCFG6_GDEF_OFFSET) +#define LCDC_HCRCFG6_RDEF_OFFSET 16 +#define LCDC_HCRCFG6_RDEF (0xff << LCDC_HCRCFG6_RDEF_OFFSET) + +#define ATMEL_LCDC_HCRCFG7 0x0388 +#define LCDC_HCRCFG7_BKEY_OFFSET 0 +#define LCDC_HCRCFG7_BKEY (0xff << LCDC_HCRCFG7_BKEY_OFFSET) +#define LCDC_HCRCFG7_GKEY_OFFSET 8 +#define LCDC_HCRCFG7_GKEY (0xff << LCDC_HCRCFG7_GKEY_OFFSET) +#define LCDC_HCRCFG7_RKEY_OFFSET 16 +#define LCDC_HCRCFG7_RKEY (0xff << LCDC_HCRCFG7_RKEY_OFFSET) + +#define ATMEL_LCDC_HCRCFG8 0x038C +#define LCDC_HCRCFG8_BMASK_OFFSET 0 +#define LCDC_HCRCFG8_BMASK (0xff << LCDC_HCRCFG8_BMASK_OFFSET) +#define LCDC_HCRCFG8_GMASK_OFFSET 8 +#define LCDC_HCRCFG8_GMASK (0xff << LCDC_HCRCFG8_GMASK_OFFSET) +#define LCDC_HCRCFG8_RMASK_OFFSET 16 +#define LCDC_HCRCFG8_RMASK (0xff << LCDC_HCRCFG8_RMASK_OFFSET) + +#define ATMEL_LCDC_HCRCFG9 0x0390 +#define LCDC_HCRCFG9_CRKEY (0x1 << 0) +#define LCDC_HCRCFG9_INV (0x1 << 1) +#define LCDC_HCRCFG9_ITER2BL (0x1 << 2) +#define LCDC_HCRCFG9_ITER (0x1 << 3) +#define LCDC_HCRCFG9_REVALPHA (0x1 << 4) +#define LCDC_HCRCFG9_GAEN (0x1 << 5) +#define LCDC_HCRCFG9_LAEN (0x1 << 6) +#define LCDC_HCRCFG9_OVR (0x1 << 7) +#define LCDC_HCRCFG9_DMA (0x1 << 8) +#define LCDC_HCRCFG9_REP (0x1 << 9) +#define LCDC_HCRCFG9_DSTKEY (0x1 << 10) +#define LCDC_HCRCFG9_GA_OFFSET 16 +#define LCDC_HCRCFG9_GA_Msk (0xff << LCDC_HCRCFG9_GA_OFFSET) + +#define ATMEL_LCDC_BASECLUT 0x400 +#define LCDC_BASECLUT_BCLUT_OFFSET 0 +#define LCDC_BASECLUT_BCLUT (0xff << LCDC_BASECLUT_BCLUT_OFFSET) +#define LCDC_BASECLUT_GCLUT_OFFSET 8 +#define LCDC_BASECLUT_GCLUT (0xff << LCDC_BASECLUT_GCLUT_OFFSET) +#define LCDC_BASECLUT_RCLUT_OFFSET 16 +#define LCDC_BASECLUT_RCLUT (0xff << LCDC_BASECLUT_RCLUT_OFFSET) + +#define ATMEL_LCDC_OVR1CLUT 0x800 +#define LCDC_OVR1CLUT_BCLUT_OFFSET 0 +#define LCDC_OVR1CLUT_BCLUT (0xff << LCDC_OVR1CLUT_BCLUT_OFFSET) +#define LCDC_OVR1CLUT_GCLUT_OFFSET 8 +#define LCDC_OVR1CLUT_GCLUT (0xff << LCDC_OVR1CLUT_GCLUT_OFFSET) +#define LCDC_OVR1CLUT_RCLUT_OFFSET 16 +#define LCDC_OVR1CLUT_RCLUT (0xff << LCDC_OVR1CLUT_RCLUT_OFFSET) +#define LCDC_OVR1CLUT_ACLUT_OFFSET 24 +#define LCDC_OVR1CLUT_ACLUT (0xff << LCDC_OVR1CLUT_ACLUT_OFFSET) + +#define ATMEL_LCDC_HEOCLUT 0x1000 +#define LCDC_HEOCLUT_BCLUT_OFFSET 0 +#define LCDC_HEOCLUT_BCLUT (0xff << LCDC_HEOCLUT_BCLUT_OFFSET) +#define LCDC_HEOCLUT_GCLUT_OFFSET 8 +#define LCDC_HEOCLUT_GCLUT (0xff << LCDC_HEOCLUT_GCLUT_OFFSET) +#define LCDC_HEOCLUT_RCLUT_OFFSET 16 +#define LCDC_HEOCLUT_RCLUT (0xff << LCDC_HEOCLUT_RCLUT_OFFSET) +#define LCDC_HEOCLUT_ACLUT_OFFSET 24 +#define LCDC_HEOCLUT_ACLUT (0xff << LCDC_HEOCLUT_ACLUT_OFFSET) + +#define ATMEL_LCDC_HCRCLUT 0x1400 +#define LCDC_HCRCLUT_BCLUT_OFFSET 0 +#define LCDC_HCRCLUT_BCLUT (0xff << LCDC_HCRCLUT_BCLUT_OFFSET) +#define LCDC_HCRCLUT_GCLUT_OFFSET 8 +#define LCDC_HCRCLUT_GCLUT (0xff << LCDC_HCRCLUT_GCLUT_OFFSET) +#define LCDC_HCRCLUT_RCLUT_OFFSET 16 +#define LCDC_HCRCLUT_RCLUT (0xff << LCDC_HCRCLUT_RCLUT_OFFSET) +#define LCDC_HCRCLUT_ACLUT_OFFSET 24 +#define LCDC_HCRCLUT_ACLUT (0xff << LCDC_HCRCLUT_ACLUT_OFFSET) + +/* Base layer CLUT */ +#define ATMEL_LCDC_LUT(n) (0x0400 + ((n)*4)) + + +#endif /* __ATMEL_HLCDC4_H__ */ diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 15055395cd95a1..27eca1b2d043d5 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -1,7 +1,7 @@ /* * Driver for AT91/AT32 LCD Controller * - * Copyright (C) 2007 Atmel Corporation + * Copyright (C) 2007-2010 Atmel Corporation * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -25,6 +25,7 @@ #include #include