diff options
Diffstat (limited to 'drivers')
328 files changed, 2925 insertions, 1298 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9628652e080..e0596954290 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -237,6 +237,16 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state)  	} else if (result == ACPI_STATE_D3_HOT) {  		result = ACPI_STATE_D3;  	} + +	/* +	 * If we were unsure about the device parent's power state up to this +	 * point, the fact that the device is in D0 implies that the parent has +	 * to be in D0 too. +	 */ +	if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN +	    && result == ACPI_STATE_D0) +		device->parent->power.state = ACPI_STATE_D0; +  	*state = result;   out: diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fc180341462..40e38a06ba8 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -107,6 +107,7 @@ struct acpi_power_resource {  	/* List of devices relying on this power resource */  	struct acpi_power_resource_device *devices; +	struct mutex devices_lock;  };  static struct list_head acpi_power_resource_list; @@ -225,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device)  static int __acpi_power_on(struct acpi_power_resource *resource)  { -	struct acpi_power_resource_device *device_list = resource->devices;  	acpi_status status = AE_OK;  	status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); @@ -238,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource)  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",  			  resource->name)); -	while (device_list) { -		acpi_power_on_device(device_list->device); - -		device_list = device_list->next; -	} -  	return 0;  }  static int acpi_power_on(acpi_handle handle)  {  	int result = 0; +	bool resume_device = false;  	struct acpi_power_resource *resource = NULL; +	struct acpi_power_resource_device *device_list;  	result = acpi_power_get_context(handle, &resource);  	if (result) @@ -266,10 +262,25 @@ static int acpi_power_on(acpi_handle handle)  		result = __acpi_power_on(resource);  		if (result)  			resource->ref_count--; +		else +			resume_device = true;  	}  	mutex_unlock(&resource->resource_lock); +	if (!resume_device) +		return result; + +	mutex_lock(&resource->devices_lock); + +	device_list = resource->devices; +	while (device_list) { +		acpi_power_on_device(device_list->device); +		device_list = device_list->next; +	} + +	mutex_unlock(&resource->devices_lock); +  	return result;  } @@ -355,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,  	if (acpi_power_get_context(res_handle, &resource))  		return; -	mutex_lock(&resource->resource_lock); +	mutex_lock(&resource->devices_lock);  	prev = NULL;  	curr = resource->devices;  	while (curr) { @@ -372,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,  		prev = curr;  		curr = curr->next;  	} -	mutex_unlock(&resource->resource_lock); +	mutex_unlock(&resource->devices_lock);  }  /* Unlink dev from all power resources in _PR0 */ @@ -414,10 +425,10 @@ static int __acpi_power_resource_register_device(  	power_resource_device->device = powered_device; -	mutex_lock(&resource->resource_lock); +	mutex_lock(&resource->devices_lock);  	power_resource_device->next = resource->devices;  	resource->devices = power_resource_device; -	mutex_unlock(&resource->resource_lock); +	mutex_unlock(&resource->devices_lock);  	return 0;  } @@ -462,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)  	return ret;  no_power_resource: -	printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); +	printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!");  	return -ENODEV;  }  EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); @@ -721,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device)  	resource->device = device;  	mutex_init(&resource->resource_lock); +	mutex_init(&resource->devices_lock);  	strcpy(resource->name, device->pnp.bus_id);  	strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);  	strcpy(acpi_device_class(device), ACPI_POWER_CLASS); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 50d5dea0ff5..7862d17976b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -268,6 +268,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {  	/* JMicron 360/1/3/5/6, match class to avoid IDE function */  	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,  	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, +	/* JMicron 362B and 362C have an AHCI function with IDE class code */ +	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, +	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },  	/* ATI */  	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ @@ -393,6 +396,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {  	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */  	{ PCI_DEVICE(0x1b4b, 0x917a),  	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */ +	{ PCI_DEVICE(0x1b4b, 0x9192), +	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */  	{ PCI_DEVICE(0x1b4b, 0x91a3),  	  .driver_data = board_ahci_yes_fbs }, @@ -400,7 +405,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {  	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */  	/* Asmedia */ -	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1061 */ +	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */ +	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */ +	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */ +	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */  	/* Generic, PCI class code for AHCI */  	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index de0435e63b0..887f68f6d79 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -35,6 +35,7 @@ new_skb(ulong len)  		skb_reset_mac_header(skb);  		skb_reset_network_header(skb);  		skb->protocol = __constant_htons(ETH_P_AOE); +		skb_checksum_none_assert(skb);  	}  	return skb;  } diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 38aa6dda6b8..da3311129a0 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -795,6 +795,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,  				}  			break;  			case CMD_PROTOCOL_ERR: +				cmd->result = DID_ERROR << 16;  				dev_warn(&h->pdev->dev,  					"%p has protocol error\n", c);                          break; diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index a8fddeb3d63..f946d31d691 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -1148,11 +1148,15 @@ static bool mtip_pause_ncq(struct mtip_port *port,  	reply = port->rxfis + RX_FIS_D2H_REG;  	task_file_data = readl(port->mmio+PORT_TFDATA); -	if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT)) +	if (fis->command == ATA_CMD_SEC_ERASE_UNIT) +		clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); + +	if ((task_file_data & 1))  		return false;  	if (fis->command == ATA_CMD_SEC_ERASE_PREP) {  		set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); +		set_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);  		port->ic_pause_timer = jiffies;  		return true;  	} else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) && @@ -1900,7 +1904,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,  	int rv = 0, xfer_sz = command[3];  	if (xfer_sz) { -		if (user_buffer) +		if (!user_buffer)  			return -EFAULT;  		buf = dmam_alloc_coherent(&port->dd->pdev->dev, @@ -2043,7 +2047,7 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)  		*timeout = 240000; /* 4 minutes */  		break;  	case ATA_CMD_STANDBYNOW1: -		*timeout = 10000;  /* 10 seconds */ +		*timeout = 120000;  /* 2 minutes */  		break;  	case 0xF7:  	case 0xFA: @@ -2588,9 +2592,6 @@ static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,  	if (!len || size)  		return 0; -	if (size < 0) -		return -EINVAL; -  	size += sprintf(&buf[size], "H/ S ACTive      : [ 0x");  	for (n = dd->slot_groups-1; n >= 0; n--) @@ -2660,9 +2661,6 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,  	if (!len || size)  		return 0; -	if (size < 0) -		return -EINVAL; -  	size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n",  							dd->port->flags);  	size += sprintf(&buf[size], "Flag-dd   : [ %08lX ]\n", @@ -3214,8 +3212,8 @@ static int mtip_hw_init(struct driver_data *dd)  				"Unable to check write protect progress\n");  	else  		dev_info(&dd->pdev->dev, -				"Write protect progress: %d%% (%d blocks)\n", -				attr242.cur, attr242.data); +				"Write protect progress: %u%% (%u blocks)\n", +				attr242.cur, le32_to_cpu(attr242.data));  	return rv;  out3: @@ -3619,6 +3617,10 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)  			bio_endio(bio, -ENODATA);  			return;  		} +		if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) { +			bio_endio(bio, -ENODATA); +			return; +		}  	}  	if (unlikely(!bio_has_data(bio))) { @@ -4168,7 +4170,13 @@ static void mtip_pci_shutdown(struct pci_dev *pdev)  /* Table of device ids supported by this driver. */  static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = { -	{  PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P325M_DEVICE_ID) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420H_DEVICE_ID) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420M_DEVICE_ID) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P425M_DEVICE_ID) },  	{ 0 }  }; @@ -4199,12 +4207,12 @@ static int __init mtip_init(void)  {  	int error; -	printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n"); +	pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");  	/* Allocate a major block device number to use with this driver. */  	error = register_blkdev(0, MTIP_DRV_NAME);  	if (error <= 0) { -		printk(KERN_ERR "Unable to register block device (%d)\n", +		pr_err("Unable to register block device (%d)\n",  		error);  		return -EBUSY;  	} @@ -4213,7 +4221,7 @@ static int __init mtip_init(void)  	if (!dfs_parent) {  		dfs_parent = debugfs_create_dir("rssd", NULL);  		if (IS_ERR_OR_NULL(dfs_parent)) { -			printk(KERN_WARNING "Error creating debugfs parent\n"); +			pr_warn("Error creating debugfs parent\n");  			dfs_parent = NULL;  		}  	} diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index f51fc23d17b..18627a1d04c 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -76,7 +76,13 @@  /* Micron Vendor ID & P320x SSD Device ID */  #define PCI_VENDOR_ID_MICRON    0x1344 -#define P320_DEVICE_ID		0x5150 +#define P320H_DEVICE_ID		0x5150 +#define P320M_DEVICE_ID		0x5151 +#define P320S_DEVICE_ID		0x5152 +#define P325M_DEVICE_ID		0x5153 +#define P420H_DEVICE_ID		0x5160 +#define P420M_DEVICE_ID		0x5161 +#define P425M_DEVICE_ID		0x5163  /* Driver name and version strings */  #define MTIP_DRV_NAME		"mtip32xx" @@ -131,10 +137,12 @@ enum {  	MTIP_PF_SVC_THD_STOP_BIT    = 8,  	/* below are bit numbers in 'dd_flag' defined in driver_data */ +	MTIP_DDF_SEC_LOCK_BIT	    = 0,  	MTIP_DDF_REMOVE_PENDING_BIT = 1,  	MTIP_DDF_OVER_TEMP_BIT      = 2,  	MTIP_DDF_WRITE_PROTECT_BIT  = 3,  	MTIP_DDF_STOP_IO      = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \ +				(1 << MTIP_DDF_SEC_LOCK_BIT) | \  				(1 << MTIP_DDF_OVER_TEMP_BIT) | \  				(1 << MTIP_DDF_WRITE_PROTECT_BIT)), diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index d07c9f7fded..0c03411c59e 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -449,6 +449,14 @@ static void nbd_clear_que(struct nbd_device *nbd)  		req->errors++;  		nbd_end_request(req);  	} + +	while (!list_empty(&nbd->waiting_queue)) { +		req = list_entry(nbd->waiting_queue.next, struct request, +				 queuelist); +		list_del_init(&req->queuelist); +		req->errors++; +		nbd_end_request(req); +	}  } @@ -598,6 +606,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,  		nbd->file = NULL;  		nbd_clear_que(nbd);  		BUG_ON(!list_empty(&nbd->queue_head)); +		BUG_ON(!list_empty(&nbd->waiting_queue));  		if (file)  			fput(file);  		return 0; diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 9917943a357..54a55f03115 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -246,13 +246,12 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)  {  	struct rbd_device *rbd_dev = bdev->bd_disk->private_data; -	rbd_get_dev(rbd_dev); - -	set_device_ro(bdev, rbd_dev->read_only); -  	if ((mode & FMODE_WRITE) && rbd_dev->read_only)  		return -EROFS; +	rbd_get_dev(rbd_dev); +	set_device_ro(bdev, rbd_dev->read_only); +  	return 0;  } diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 73f196ca713..c6decb901e5 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req)  		invcount++;  	} -	ret = gnttab_unmap_refs(unmap, pages, invcount, false); +	ret = gnttab_unmap_refs(unmap, NULL, pages, invcount);  	BUG_ON(ret);  } diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 11f36e50213..fc2de5528dc 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -86,6 +86,7 @@ static struct usb_device_id ath3k_table[] = {  	/* Atheros AR5BBU22 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xE03C) }, +	{ USB_DEVICE(0x0489, 0xE036) },  	{ }	/* Terminating entry */  }; @@ -109,6 +110,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {  	/* Atheros AR5BBU22 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },  	{ }	/* Terminating entry */  }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index cef3bac1a54..654e248763e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -52,6 +52,9 @@ static struct usb_device_id btusb_table[] = {  	/* Generic Bluetooth USB device */  	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, +	/* Apple-specific (Broadcom) devices */ +	{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, +  	/* Broadcom SoftSailing reporting vendor specific */  	{ USB_DEVICE(0x0a5c, 0x21e1) }, @@ -94,16 +97,14 @@ static struct usb_device_id btusb_table[] = {  	/* Broadcom BCM20702A0 */  	{ USB_DEVICE(0x0489, 0xe042) }, -	{ USB_DEVICE(0x0a5c, 0x21e3) }, -	{ USB_DEVICE(0x0a5c, 0x21e6) }, -	{ USB_DEVICE(0x0a5c, 0x21e8) }, -	{ USB_DEVICE(0x0a5c, 0x21f3) }, -	{ USB_DEVICE(0x0a5c, 0x21f4) },  	{ USB_DEVICE(0x413c, 0x8197) },  	/* Foxconn - Hon Hai */  	{ USB_DEVICE(0x0489, 0xe033) }, +	/*Broadcom devices with vendor specific id */ +	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, +  	{ }	/* Terminating entry */  }; @@ -141,6 +142,7 @@ static struct usb_device_id blacklist_table[] = {  	/* Atheros AR5BBU12 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },  	/* Broadcom BCM2035 */  	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5869ea38705..72ce247a0e8 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,4 +1,5 @@  # common clock types +obj-$(CONFIG_HAVE_CLK)		+= clk-devres.o  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o  obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \  				   clk-mux.o clk-divider.o clk-fixed-factor.o diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c new file mode 100644 index 00000000000..8f571548870 --- /dev/null +++ b/drivers/clk/clk-devres.c @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/export.h> +#include <linux/gfp.h> + +static void devm_clk_release(struct device *dev, void *res) +{ +	clk_put(*(struct clk **)res); +} + +struct clk *devm_clk_get(struct device *dev, const char *id) +{ +	struct clk **ptr, *clk; + +	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); +	if (!ptr) +		return ERR_PTR(-ENOMEM); + +	clk = clk_get(dev, id); +	if (!IS_ERR(clk)) { +		*ptr = clk; +		devres_add(dev, ptr); +	} else { +		devres_free(ptr); +	} + +	return clk; +} +EXPORT_SYMBOL(devm_clk_get); + +static int devm_clk_match(struct device *dev, void *res, void *data) +{ +	struct clk **c = res; +	if (!c || !*c) { +		WARN_ON(!c || !*c); +		return 0; +	} +	return *c == data; +} + +void devm_clk_put(struct device *dev, struct clk *clk) +{ +	int ret; + +	ret = devres_release(dev, devm_clk_release, devm_clk_match, clk); + +	WARN_ON(ret); +} +EXPORT_SYMBOL(devm_clk_put); diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index d423c9bdd71..442a3136387 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -171,51 +171,6 @@ void clk_put(struct clk *clk)  }  EXPORT_SYMBOL(clk_put); -static void devm_clk_release(struct device *dev, void *res) -{ -	clk_put(*(struct clk **)res); -} - -struct clk *devm_clk_get(struct device *dev, const char *id) -{ -	struct clk **ptr, *clk; - -	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); -	if (!ptr) -		return ERR_PTR(-ENOMEM); - -	clk = clk_get(dev, id); -	if (!IS_ERR(clk)) { -		*ptr = clk; -		devres_add(dev, ptr); -	} else { -		devres_free(ptr); -	} - -	return clk; -} -EXPORT_SYMBOL(devm_clk_get); - -static int devm_clk_match(struct device *dev, void *res, void *data) -{ -	struct clk **c = res; -	if (!c || !*c) { -		WARN_ON(!c || !*c); -		return 0; -	} -	return *c == data; -} - -void devm_clk_put(struct device *dev, struct clk *clk) -{ -	int ret; - -	ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk); - -	WARN_ON(ret); -} -EXPORT_SYMBOL(devm_clk_put); -  void clkdev_add(struct clk_lookup *cl)  {  	mutex_lock(&clocks_mutex); diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index c0e816468e3..1a40935c85f 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -35,7 +35,6 @@  #include <linux/slab.h>  #include <linux/string.h>  #include <linux/cpumask.h> -#include <linux/sched.h>	/* for current / set_cpus_allowed() */  #include <linux/io.h>  #include <linux/delay.h> @@ -1139,16 +1138,23 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,  	return res;  } -/* Driver entry point to switch to the target frequency */ -static int powernowk8_target(struct cpufreq_policy *pol, -		unsigned targfreq, unsigned relation) +struct powernowk8_target_arg { +	struct cpufreq_policy		*pol; +	unsigned			targfreq; +	unsigned			relation; +}; + +static long powernowk8_target_fn(void *arg)  { -	cpumask_var_t oldmask; +	struct powernowk8_target_arg *pta = arg; +	struct cpufreq_policy *pol = pta->pol; +	unsigned targfreq = pta->targfreq; +	unsigned relation = pta->relation;  	struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);  	u32 checkfid;  	u32 checkvid;  	unsigned int newstate; -	int ret = -EIO; +	int ret;  	if (!data)  		return -EINVAL; @@ -1156,29 +1162,16 @@ static int powernowk8_target(struct cpufreq_policy *pol,  	checkfid = data->currfid;  	checkvid = data->currvid; -	/* only run on specific CPU from here on. */ -	/* This is poor form: use a workqueue or smp_call_function_single */ -	if (!alloc_cpumask_var(&oldmask, GFP_KERNEL)) -		return -ENOMEM; - -	cpumask_copy(oldmask, tsk_cpus_allowed(current)); -	set_cpus_allowed_ptr(current, cpumask_of(pol->cpu)); - -	if (smp_processor_id() != pol->cpu) { -		printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); -		goto err_out; -	} -  	if (pending_bit_stuck()) {  		printk(KERN_ERR PFX "failing targ, change pending bit set\n"); -		goto err_out; +		return -EIO;  	}  	pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",  		pol->cpu, targfreq, pol->min, pol->max, relation);  	if (query_current_values_with_pending_wait(data)) -		goto err_out; +		return -EIO;  	if (cpu_family != CPU_HW_PSTATE) {  		pr_debug("targ: curr fid 0x%x, vid 0x%x\n", @@ -1196,7 +1189,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,  	if (cpufreq_frequency_table_target(pol, data->powernow_table,  				targfreq, relation, &newstate)) -		goto err_out; +		return -EIO;  	mutex_lock(&fidvid_mutex); @@ -1209,9 +1202,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,  		ret = transition_frequency_fidvid(data, newstate);  	if (ret) {  		printk(KERN_ERR PFX "transition frequency failed\n"); -		ret = 1;  		mutex_unlock(&fidvid_mutex); -		goto err_out; +		return 1;  	}  	mutex_unlock(&fidvid_mutex); @@ -1220,12 +1212,25 @@ static int powernowk8_target(struct cpufreq_policy *pol,  				data->powernow_table[newstate].index);  	else  		pol->cur = find_khz_freq_from_fid(data->currfid); -	ret = 0; -err_out: -	set_cpus_allowed_ptr(current, oldmask); -	free_cpumask_var(oldmask); -	return ret; +	return 0; +} + +/* Driver entry point to switch to the target frequency */ +static int powernowk8_target(struct cpufreq_policy *pol, +		unsigned targfreq, unsigned relation) +{ +	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);  }  /* Driver entry point to verify the policy and range of frequencies */ diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c index 002888185f1..d216cd3cc56 100644 --- a/drivers/crypto/caam/key_gen.c +++ b/drivers/crypto/caam/key_gen.c @@ -120,3 +120,4 @@ u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,  	return ret;  } +EXPORT_SYMBOL(gen_split_key); diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3934fcc4e00..7ab6e26664a 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -661,7 +661,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,  			flags);  	if (unlikely(!atslave || !sg_len)) { -		dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); +		dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n");  		return NULL;  	} @@ -689,6 +689,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,  			mem = sg_dma_address(sg);  			len = sg_dma_len(sg); +			if (unlikely(!len)) { +				dev_dbg(chan2dev(chan), +					"prep_slave_sg: sg(%d) data length is zero\n", i); +				goto err; +			}  			mem_width = 2;  			if (unlikely(mem & 3 || len & 3))  				mem_width = 0; @@ -724,6 +729,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,  			mem = sg_dma_address(sg);  			len = sg_dma_len(sg); +			if (unlikely(!len)) { +				dev_dbg(chan2dev(chan), +					"prep_slave_sg: sg(%d) data length is zero\n", i); +				goto err; +			}  			mem_width = 2;  			if (unlikely(mem & 3 || len & 3))  				mem_width = 0; @@ -757,6 +767,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,  err_desc_get:  	dev_err(chan2dev(chan), "not enough descriptors available\n"); +err:  	atc_desc_put(atchan, first);  	return NULL;  } diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index e4feba6b03c..f5843bc80ba 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1567,17 +1567,19 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r)  		goto xfer_exit;  	} -	/* Prefer Secure Channel */ -	if (!_manager_ns(thrd)) -		r->cfg->nonsecure = 0; -	else -		r->cfg->nonsecure = 1;  	/* Use last settings, if not provided */ -	if (r->cfg) +	if (r->cfg) { +		/* Prefer Secure Channel */ +		if (!_manager_ns(thrd)) +			r->cfg->nonsecure = 0; +		else +			r->cfg->nonsecure = 1; +  		ccr = _prepare_ccr(r->cfg); -	else +	} else {  		ccr = readl(regs + CC(thrd->id)); +	}  	/* If this req doesn't have valid xfer settings */  	if (!_is_valid(ccr)) { @@ -2928,6 +2930,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)  		num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);  	pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); +	if (!pdmac->peripherals) { +		ret = -ENOMEM; +		dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n"); +		goto probe_err5; +	}  	for (i = 0; i < num_chan; i++) {  		pch = &pdmac->peripherals[i]; diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 616d90bcb3a..d5dc9da7f99 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -199,6 +199,36 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems)  	return (void *)(((unsigned long)ptr) + align - r);  } +static void _edac_mc_free(struct mem_ctl_info *mci) +{ +	int i, chn, row; +	struct csrow_info *csr; +	const unsigned int tot_dimms = mci->tot_dimms; +	const unsigned int tot_channels = mci->num_cschannel; +	const unsigned int tot_csrows = mci->nr_csrows; + +	if (mci->dimms) { +		for (i = 0; i < tot_dimms; i++) +			kfree(mci->dimms[i]); +		kfree(mci->dimms); +	} +	if (mci->csrows) { +		for (row = 0; row < tot_csrows; row++) { +			csr = mci->csrows[row]; +			if (csr) { +				if (csr->channels) { +					for (chn = 0; chn < tot_channels; chn++) +						kfree(csr->channels[chn]); +					kfree(csr->channels); +				} +				kfree(csr); +			} +		} +		kfree(mci->csrows); +	} +	kfree(mci); +} +  /**   * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure   * @mc_num:		Memory controller number @@ -413,24 +443,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,  	return mci;  error: -	if (mci->dimms) { -		for (i = 0; i < tot_dimms; i++) -			kfree(mci->dimms[i]); -		kfree(mci->dimms); -	} -	if (mci->csrows) { -		for (chn = 0; chn < tot_channels; chn++) { -			csr = mci->csrows[chn]; -			if (csr) { -				for (chn = 0; chn < tot_channels; chn++) -					kfree(csr->channels[chn]); -				kfree(csr); -			} -			kfree(mci->csrows[i]); -		} -		kfree(mci->csrows); -	} -	kfree(mci); +	_edac_mc_free(mci);  	return NULL;  } @@ -445,6 +458,14 @@ void edac_mc_free(struct mem_ctl_info *mci)  {  	edac_dbg(1, "\n"); +	/* If we're not yet registered with sysfs free only what was allocated +	 * in edac_mc_alloc(). +	 */ +	if (!device_is_registered(&mci->dev)) { +		_edac_mc_free(mci); +		return; +	} +  	/* the mci instance is freed here, when the sysfs object is dropped */  	edac_unregister_sysfs(mci);  } diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 47180a08eda..b6653a6fc5d 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -391,7 +391,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)  		for (j = 0; j < nr_channels; j++) {  			struct dimm_info *dimm = csrow->channels[j]->dimm; -			dimm->nr_pages = nr_pages / nr_channels; +			dimm->nr_pages = nr_pages;  			dimm->grain = nr_pages << PAGE_SHIFT;  			dimm->mtype = MEM_DDR2;  			dimm->dtype = DEV_UNKNOWN; diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 39c63757c2a..6a49dd00b81 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1012,6 +1012,10 @@ static void handle_channel(struct i5000_pvt *pvt, int slot, int channel,  			/* add the number of COLUMN bits */  			addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); +			/* Dual-rank memories have twice the size */ +			if (dinfo->dual_rank) +				addrBits++; +  			addrBits += 6;	/* add 64 bits per DIMM */  			addrBits -= 20;	/* divide by 2^^20 */  			addrBits -= 3;	/* 8 bits per bytes */ diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index f3b1f9fafa4..5715b7c2c51 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -513,7 +513,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)  {  	struct sbridge_pvt *pvt = mci->pvt_info;  	struct dimm_info *dimm; -	int i, j, banks, ranks, rows, cols, size, npages; +	unsigned i, j, banks, ranks, rows, cols, npages; +	u64 size;  	u32 reg;  	enum edac_type mode;  	enum mem_type mtype; @@ -585,10 +586,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)  				cols = numcol(mtr);  				/* DDR3 has 8 I/O banks */ -				size = (rows * cols * banks * ranks) >> (20 - 3); +				size = ((u64)rows * cols * banks * ranks) >> (20 - 3);  				npages = MiB_TO_PAGES(size); -				edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", +				edac_dbg(0, "mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",  					 pvt->sbridge_dev->mc, i, j,  					 size, npages,  					 banks, ranks, rows, cols); diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 920a609b2c3..38f9e52f358 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -669,13 +669,18 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)  	}  	info->dev = &pdev->dev;  	info->max77693 = max77693; -	info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic, -					 &max77693_muic_regmap_config); -	if (IS_ERR(info->max77693->regmap_muic)) { -		ret = PTR_ERR(info->max77693->regmap_muic); -		dev_err(max77693->dev, -			"failed to allocate register map: %d\n", ret); -		goto err_regmap; +	if (info->max77693->regmap_muic) +		dev_dbg(&pdev->dev, "allocate register map\n"); +	else { +		info->max77693->regmap_muic = devm_regmap_init_i2c( +						info->max77693->muic, +						&max77693_muic_regmap_config); +		if (IS_ERR(info->max77693->regmap_muic)) { +			ret = PTR_ERR(info->max77693->regmap_muic); +			dev_err(max77693->dev, +				"failed to allocate register map: %d\n", ret); +			goto err_regmap; +		}  	}  	platform_set_drvdata(pdev, info);  	mutex_init(&info->mutex); diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 8a420f13905..ed94b4ea72e 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -308,6 +308,7 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,  {  	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); +	__set_gpio_level_p012(group, pin, value);  	__set_gpio_dir_p012(group, pin, 0);  	return 0; @@ -318,6 +319,7 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,  {  	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); +	__set_gpio_level_p3(group, pin, value);  	__set_gpio_dir_p3(group, pin, 0);  	return 0; @@ -326,6 +328,9 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,  static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,  	int value)  { +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + +	__set_gpo_level_p3(group, pin, value);  	return 0;  } diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index d0c4574ef49..36164806b9d 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -193,6 +193,9 @@ static const struct file_operations ast_fops = {  	.mmap = ast_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.read = drm_read,  }; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 7282c081fb5..a712cafcfa1 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -841,7 +841,7 @@ int ast_cursor_init(struct drm_device *dev)  	ast->cursor_cache = obj;  	ast->cursor_cache_gpu_addr = gpu_addr; -	DRM_ERROR("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); +	DRM_DEBUG_KMS("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr);  	return 0;  fail:  	return ret; diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 7053140c659..b83a2d7ddd1 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -74,6 +74,9 @@ static const struct file_operations cirrus_driver_fops = {  	.unlocked_ioctl = drm_ioctl,  	.mmap = cirrus_mmap,  	.poll = drm_poll, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.fasync = drm_fasync,  };  static struct drm_driver driver = { diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 7f5096763b7..59a26e577b5 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -36,6 +36,6 @@ config DRM_EXYNOS_VIDI  config DRM_EXYNOS_G2D  	bool "Exynos DRM G2D" -	depends on DRM_EXYNOS +	depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D  	help  	  Choose this option if you want to use Exynos G2D for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 613bf8a5d9b..ae13febe0ea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -163,6 +163,12 @@ static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,  	/* TODO */  } +static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, +	struct vm_area_struct *vma) +{ +	return -ENOTTY; +} +  static struct dma_buf_ops exynos_dmabuf_ops = {  	.map_dma_buf		= exynos_gem_map_dma_buf,  	.unmap_dma_buf		= exynos_gem_unmap_dma_buf, @@ -170,6 +176,7 @@ static struct dma_buf_ops exynos_dmabuf_ops = {  	.kmap_atomic		= exynos_gem_dmabuf_kmap_atomic,  	.kunmap			= exynos_gem_dmabuf_kunmap,  	.kunmap_atomic		= exynos_gem_dmabuf_kunmap_atomic, +	.mmap			= exynos_gem_dmabuf_mmap,  	.release		= exynos_dmabuf_release,  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index ebacec6f1e4..d0707193745 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -160,7 +160,6 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)  	if (!file_priv)  		return -ENOMEM; -	drm_prime_init_file_private(&file->prime);  	file->driver_priv = file_priv;  	return exynos_drm_subdrv_open(dev, file); @@ -184,7 +183,6 @@ static void exynos_drm_preclose(struct drm_device *dev,  			e->base.destroy(&e->base);  		}  	} -	drm_prime_destroy_file_private(&file->prime);  	spin_unlock_irqrestore(&dev->event_lock, flags);  	exynos_drm_subdrv_close(dev, file); @@ -241,6 +239,9 @@ static const struct file_operations exynos_drm_driver_fops = {  	.poll		= drm_poll,  	.read		= drm_read,  	.unlocked_ioctl	= drm_ioctl, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.release	= drm_release,  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a68d2b313f0..b19cd93e704 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -831,11 +831,6 @@ static int __devinit fimd_probe(struct platform_device *pdev)  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "failed to find registers\n"); -		ret = -ENOENT; -		goto err_clk; -	}  	ctx->regs = devm_request_and_ioremap(&pdev->dev, res);  	if (!ctx->regs) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index d2d88f22a03..1065e90d091 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -129,7 +129,6 @@ struct g2d_runqueue_node {  struct g2d_data {  	struct device			*dev;  	struct clk			*gate_clk; -	struct resource			*regs_res;  	void __iomem			*regs;  	int				irq;  	struct workqueue_struct		*g2d_workq; @@ -751,7 +750,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	struct exynos_drm_subdrv *subdrv;  	int ret; -	g2d = kzalloc(sizeof(*g2d), GFP_KERNEL); +	g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL);  	if (!g2d) {  		dev_err(dev, "failed to allocate driver data\n");  		return -ENOMEM; @@ -759,10 +758,8 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",  			sizeof(struct g2d_runqueue_node), 0, 0, NULL); -	if (!g2d->runqueue_slab) { -		ret = -ENOMEM; -		goto err_free_mem; -	} +	if (!g2d->runqueue_slab) +		return -ENOMEM;  	g2d->dev = dev; @@ -794,38 +791,26 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	pm_runtime_enable(dev);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "failed to get I/O memory\n"); -		ret = -ENOENT; -		goto err_put_clk; -	} -	g2d->regs_res = request_mem_region(res->start, resource_size(res), -					   dev_name(dev)); -	if (!g2d->regs_res) { -		dev_err(dev, "failed to request I/O memory\n"); -		ret = -ENOENT; -		goto err_put_clk; -	} - -	g2d->regs = ioremap(res->start, resource_size(res)); +	g2d->regs = devm_request_and_ioremap(&pdev->dev, res);  	if (!g2d->regs) {  		dev_err(dev, "failed to remap I/O memory\n");  		ret = -ENXIO; -		goto err_release_res; +		goto err_put_clk;  	}  	g2d->irq = platform_get_irq(pdev, 0);  	if (g2d->irq < 0) {  		dev_err(dev, "failed to get irq\n");  		ret = g2d->irq; -		goto err_unmap_base; +		goto err_put_clk;  	} -	ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d); +	ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0, +								"drm_g2d", g2d);  	if (ret < 0) {  		dev_err(dev, "irq request failed\n"); -		goto err_unmap_base; +		goto err_put_clk;  	}  	platform_set_drvdata(pdev, g2d); @@ -838,7 +823,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	ret = exynos_drm_subdrv_register(subdrv);  	if (ret < 0) {  		dev_err(dev, "failed to register drm g2d device\n"); -		goto err_free_irq; +		goto err_put_clk;  	}  	dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n", @@ -846,13 +831,6 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	return 0; -err_free_irq: -	free_irq(g2d->irq, g2d); -err_unmap_base: -	iounmap(g2d->regs); -err_release_res: -	release_resource(g2d->regs_res); -	kfree(g2d->regs_res);  err_put_clk:  	pm_runtime_disable(dev);  	clk_put(g2d->gate_clk); @@ -862,8 +840,6 @@ err_destroy_workqueue:  	destroy_workqueue(g2d->g2d_workq);  err_destroy_slab:  	kmem_cache_destroy(g2d->runqueue_slab); -err_free_mem: -	kfree(g2d);  	return ret;  } @@ -873,24 +849,18 @@ static int __devexit g2d_remove(struct platform_device *pdev)  	cancel_work_sync(&g2d->runqueue_work);  	exynos_drm_subdrv_unregister(&g2d->subdrv); -	free_irq(g2d->irq, g2d);  	while (g2d->runqueue_node) {  		g2d_free_runqueue_node(g2d, g2d->runqueue_node);  		g2d->runqueue_node = g2d_get_runqueue_node(g2d);  	} -	iounmap(g2d->regs); -	release_resource(g2d->regs_res); -	kfree(g2d->regs_res); -  	pm_runtime_disable(&pdev->dev);  	clk_put(g2d->gate_clk);  	g2d_fini_cmdlist(g2d);  	destroy_workqueue(g2d->g2d_workq);  	kmem_cache_destroy(g2d->runqueue_slab); -	kfree(g2d);  	return 0;  } @@ -924,7 +894,7 @@ static int g2d_resume(struct device *dev)  }  #endif -SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); +static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);  struct platform_driver g2d_driver = {  	.probe		= g2d_probe, diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index f9efde40c09..a38051c95ec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -122,7 +122,7 @@ fail:  		__free_page(pages[i]);  	drm_free_large(pages); -	return ERR_PTR(PTR_ERR(p)); +	return ERR_CAST(p);  }  static void exynos_gem_put_pages(struct drm_gem_object *obj, @@ -662,7 +662,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,  	 */  	args->pitch = args->width * ((args->bpp + 7) / 8); -	args->size = PAGE_ALIGN(args->pitch * args->height); +	args->size = args->pitch * args->height;  	exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);  	if (IS_ERR(exynos_gem_obj)) diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 8ffcdf8b9e2..3fdf0b65f47 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -345,7 +345,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);  	if (!ctx) {  		DRM_LOG_KMS("failed to alloc common hdmi context.\n");  		return -ENOMEM; @@ -371,7 +371,6 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)  	DRM_DEBUG_KMS("%s\n", __FILE__);  	exynos_drm_subdrv_unregister(&ctx->subdrv); -	kfree(ctx);  	return 0;  } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index b89829e5043..e1f94b746bd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -29,7 +29,6 @@ static const uint32_t formats[] = {  	DRM_FORMAT_XRGB8888,  	DRM_FORMAT_ARGB8888,  	DRM_FORMAT_NV12, -	DRM_FORMAT_NV12M,  	DRM_FORMAT_NV12MT,  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index bb1550c4dd5..537027a74fd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -633,7 +633,7 @@ static int __devinit vidi_probe(struct platform_device *pdev)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);  	if (!ctx)  		return -ENOMEM; @@ -673,8 +673,6 @@ static int __devexit vidi_remove(struct platform_device *pdev)  		ctx->raw_edid = NULL;  	} -	kfree(ctx); -  	return 0;  } diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 409e2ec1207..a6aea6f3ea1 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2172,7 +2172,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)  	DRM_DEBUG_KMS("HDMI resource init\n"); -	memset(res, 0, sizeof *res); +	memset(res, 0, sizeof(*res));  	/* get clocks, power */  	res->hdmi = clk_get(dev, "hdmi"); @@ -2204,7 +2204,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)  	clk_set_parent(res->sclk_hdmi, res->sclk_pixel);  	res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * -		sizeof res->regul_bulk[0], GFP_KERNEL); +		sizeof(res->regul_bulk[0]), GFP_KERNEL);  	if (!res->regul_bulk) {  		DRM_ERROR("failed to get memory for regulators\n");  		goto fail; @@ -2243,7 +2243,7 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata)  		clk_put(res->sclk_hdmi);  	if (!IS_ERR_OR_NULL(res->hdmi))  		clk_put(res->hdmi); -	memset(res, 0, sizeof *res); +	memset(res, 0, sizeof(*res));  	return 0;  } @@ -2312,11 +2312,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev)  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		DRM_ERROR("failed to find registers\n"); -		ret = -ENOENT; -		goto err_resource; -	}  	hdata->regs = devm_request_and_ioremap(&pdev->dev, res);  	if (!hdata->regs) { diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 30fcc12f81d..25b97d5e5fc 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -236,11 +236,11 @@ static inline void vp_filter_set(struct mixer_resources *res,  static void vp_default_filter(struct mixer_resources *res)  {  	vp_filter_set(res, VP_POLY8_Y0_LL, -		filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); +		filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));  	vp_filter_set(res, VP_POLY4_Y0_LL, -		filter_y_vert_tap4, sizeof filter_y_vert_tap4); +		filter_y_vert_tap4, sizeof(filter_y_vert_tap4));  	vp_filter_set(res, VP_POLY4_C0_LL, -		filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); +		filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));  }  static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 0f9b7db80f6..cf49ba5a54b 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -476,6 +476,7 @@ static const struct psb_offset oaktrail_regmap[2] = {  		.pos = DSPAPOS,  		.surf = DSPASURF,  		.addr = MRST_DSPABASE, +		.base = MRST_DSPABASE,  		.status = PIPEASTAT,  		.linoff = DSPALINOFF,  		.tileoff = DSPATILEOFF, @@ -499,6 +500,7 @@ static const struct psb_offset oaktrail_regmap[2] = {  		.pos = DSPBPOS,  		.surf = DSPBSURF,  		.addr = DSPBBASE, +		.base = DSPBBASE,  		.status = PIPEBSTAT,  		.linoff = DSPBLINOFF,  		.tileoff = DSPBTILEOFF, diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 57d892eaaa6..463ec6871fe 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -115,6 +115,9 @@ static const struct file_operations i810_buffer_fops = {  	.unlocked_ioctl = drm_ioctl,  	.mmap = i810_mmap_buffers,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index f9924ad04d0..48cfcca2b35 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -51,6 +51,9 @@ static const struct file_operations i810_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9cf7dfe022b..914c0dfabe6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1587,6 +1587,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	spin_lock_init(&dev_priv->irq_lock);  	spin_lock_init(&dev_priv->error_lock);  	spin_lock_init(&dev_priv->rps_lock); +	spin_lock_init(&dev_priv->dpio_lock);  	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))  		dev_priv->num_pipe = 3; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 489e2b162b2..274d25de521 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3242,7 +3242,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,  {  	int ret; -	BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); +	if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) +		return -EBUSY;  	if (obj->gtt_space != NULL) {  		if ((alignment && obj->gtt_offset & (alignment - 1)) || diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8a3828528b9..5249640cce1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2700,9 +2700,6 @@ void intel_irq_init(struct drm_device *dev)  			dev->driver->irq_handler = i8xx_irq_handler;  			dev->driver->irq_uninstall = i8xx_irq_uninstall;  		} else if (INTEL_INFO(dev)->gen == 3) { -			/* IIR "flip pending" means done if this bit is set */ -			I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); -  			dev->driver->irq_preinstall = i915_irq_preinstall;  			dev->driver->irq_postinstall = i915_irq_postinstall;  			dev->driver->irq_uninstall = i915_irq_uninstall; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2dfa6cf4886..c040aee1341 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1376,7 +1376,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,  	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",  	     reg, pipe_name(pipe)); -	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), +	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 +	     && (val & DP_PIPEB_SELECT),  	     "IBX PCH dp port still using transcoder B\n");  } @@ -1388,7 +1389,8 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,  	     "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",  	     reg, pipe_name(pipe)); -	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), +	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0 +	     && (val & SDVO_PIPE_B_SELECT),  	     "IBX PCH hdmi port still using transcoder B\n");  } @@ -4189,12 +4191,6 @@ static void i8xx_update_pll(struct drm_crtc *crtc,  	POSTING_READ(DPLL(pipe));  	udelay(150); -	I915_WRITE(DPLL(pipe), dpll); - -	/* Wait for the clocks to stabilize. */ -	POSTING_READ(DPLL(pipe)); -	udelay(150); -  	/* The LVDS pin pair needs to be on before the DPLLs are enabled.  	 * This is an exception to the general rule that mode_set doesn't turn  	 * things on. @@ -4202,6 +4198,12 @@ static void i8xx_update_pll(struct drm_crtc *crtc,  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))  		intel_update_lvds(crtc, clock, adjusted_mode); +	I915_WRITE(DPLL(pipe), dpll); + +	/* Wait for the clocks to stabilize. */ +	POSTING_READ(DPLL(pipe)); +	udelay(150); +  	/* The pixel multiplier can only be updated once the  	 * DPLL is enabled and the clocks are stable.  	 * diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a6c426afaa7..ace757af913 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2533,14 +2533,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)  			break;  	} -	intel_dp_i2c_init(intel_dp, intel_connector, name); -  	/* Cache some DPCD data in the eDP case */  	if (is_edp(intel_dp)) { -		bool ret;  		struct edp_power_seq	cur, vbt;  		u32 pp_on, pp_off, pp_div; -		struct edid *edid;  		pp_on = I915_READ(PCH_PP_ON_DELAYS);  		pp_off = I915_READ(PCH_PP_OFF_DELAYS); @@ -2591,6 +2587,13 @@ intel_dp_init(struct drm_device *dev, int output_reg)  		DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",  			      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); +	} + +	intel_dp_i2c_init(intel_dp, intel_connector, name); + +	if (is_edp(intel_dp)) { +		bool ret; +		struct edid *edid;  		ironlake_edp_panel_vdd_on(intel_dp);  		ret = intel_dp_get_dpcd(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 98f602427eb..12dc3308ab8 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -609,7 +609,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)  	u32 temp;  	u32 enable_bits = SDVO_ENABLE; -	if (intel_hdmi->has_audio) +	if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON)  		enable_bits |= SDVO_AUDIO_ENABLE;  	temp = I915_READ(intel_hdmi->sdvox_reg); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 3df4f5fa892..e019b236986 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -162,19 +162,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)  	return val;  } -u32 intel_panel_get_max_backlight(struct drm_device *dev) +static u32 _intel_panel_get_max_backlight(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 max;  	max = i915_read_blc_pwm_ctl(dev_priv); -	if (max == 0) { -		/* XXX add code here to query mode clock or hardware clock -		 * and program max PWM appropriately. -		 */ -		pr_warn_once("fixme: max PWM is zero\n"); -		return 1; -	}  	if (HAS_PCH_SPLIT(dev)) {  		max >>= 16; @@ -188,6 +181,22 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)  			max *= 0xff;  	} +	return max; +} + +u32 intel_panel_get_max_backlight(struct drm_device *dev) +{ +	u32 max; + +	max = _intel_panel_get_max_backlight(dev); +	if (max == 0) { +		/* XXX add code here to query mode clock or hardware clock +		 * and program max PWM appropriately. +		 */ +		pr_warn_once("fixme: max PWM is zero\n"); +		return 1; +	} +  	DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);  	return max;  } @@ -424,7 +433,11 @@ int intel_panel_setup_backlight(struct drm_device *dev)  	memset(&props, 0, sizeof(props));  	props.type = BACKLIGHT_RAW; -	props.max_brightness = intel_panel_get_max_backlight(dev); +	props.max_brightness = _intel_panel_get_max_backlight(dev); +	if (props.max_brightness == 0) { +		DRM_ERROR("Failed to get maximum backlight value\n"); +		return -ENODEV; +	}  	dev_priv->backlight =  		backlight_device_register("intel_backlight",  					  &connector->kdev, dev, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1881c8c83f0..ba8a27b1757 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3672,6 +3672,9 @@ static void gen3_init_clock_gating(struct drm_device *dev)  	if (IS_PINEVIEW(dev))  		I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); + +	/* IIR "flip pending" means done if this bit is set */ +	I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));  }  static void i85x_init_clock_gating(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d81bb0bf288..123afd35761 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2573,7 +2573,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  		hotplug_mask = intel_sdvo->is_sdvob ?  			SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;  	} -	dev_priv->hotplug_supported_mask |= hotplug_mask;  	drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); @@ -2581,14 +2580,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))  		goto err; -	/* Set up hotplug command - note paranoia about contents of reply. -	 * We assume that the hardware is in a sane state, and only touch -	 * the bits we think we understand. -	 */ -	intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, -			     &intel_sdvo->hotplug_active, 2); -	intel_sdvo->hotplug_active[0] &= ~0x3; -  	if (intel_sdvo_output_setup(intel_sdvo,  				    intel_sdvo->caps.output_flags) != true) {  		DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", @@ -2596,6 +2587,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  		goto err;  	} +	/* Only enable the hotplug irq if we need it, to work around noisy +	 * hotplug lines. +	 */ +	if (intel_sdvo->hotplug_active[0]) +		dev_priv->hotplug_supported_mask |= hotplug_mask; +  	intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);  	/* Set the input timing to the screen. Assume always input 0. */ diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index ea1024d7997..e5f145d2cb3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -84,6 +84,9 @@ static const struct file_operations mgag200_driver_fops = {  	.mmap = mgag200_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.read = drm_read,  }; diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index ff23d88880e..3ca240b4413 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -179,7 +179,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)  			return 0;  	} else  	if (init->class == 0x906e) { -		NV_ERROR(dev, "906e not supported yet\n"); +		NV_DEBUG(dev, "906e not supported yet\n");  		return -EINVAL;  	} diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 69688ef5cf4..7e16dc5e646 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -598,7 +598,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,  	args->size = args->pitch * args->height;  	args->size = roundup(args->size, PAGE_SIZE); -	ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); +	ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);  	if (ret)  		return ret; diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index f429e6a8ca7..c399d510b27 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -22,6 +22,7 @@   * Authors: Ben Skeggs   */ +#include <linux/dmi.h>  #include "drmP.h"  #include "nouveau_drv.h"  #include "nouveau_hw.h" @@ -110,11 +111,26 @@ nv50_gpio_isr(struct drm_device *dev)  		nv_wr32(dev, 0xe074, intr1);  } +static struct dmi_system_id gpio_reset_ids[] = { +	{ +		.ident = "Apple Macbook 10,1", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), +		} +	}, +	{ } +}; +  int  nv50_gpio_init(struct drm_device *dev)  {  	struct drm_nouveau_private *dev_priv = dev->dev_private; +	/* initialise gpios and routing to vbios defaults */ +	if (dmi_check_system(gpio_reset_ids)) +		nouveau_gpio_reset(dev); +  	/* disable, and ack any pending gpio interrupts */  	nv_wr32(dev, 0xe050, 0x00000000);  	nv_wr32(dev, 0xe054, 0xffffffff); diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c index f704e942372..f376c39310d 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fb.c +++ b/drivers/gpu/drm/nouveau/nvc0_fb.c @@ -124,6 +124,7 @@ nvc0_fb_init(struct drm_device *dev)  	priv = dev_priv->engine.fb.priv;  	nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); +	nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c index 7d85553d518..cd39eb99f5b 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fifo.c +++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c @@ -373,7 +373,8 @@ nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)  static void  nvc0_fifo_isr(struct drm_device *dev)  { -	u32 stat = nv_rd32(dev, 0x002100); +	u32 mask = nv_rd32(dev, 0x002140); +	u32 stat = nv_rd32(dev, 0x002100) & mask;  	if (stat & 0x00000100) {  		NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index dac525b2994..8a2fc89b776 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1510,10 +1510,10 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,  	case OUTPUT_DP:  		if (nv_connector->base.display_info.bpc == 6) {  			nv_encoder->dp.datarate = mode->clock * 18 / 8; -			syncs |= 0x00000140; +			syncs |= 0x00000002 << 6;  		} else {  			nv_encoder->dp.datarate = mode->clock * 24 / 8; -			syncs |= 0x00000180; +			syncs |= 0x00000005 << 6;  		}  		if (nv_encoder->dcb->sorconf.link & 1) diff --git a/drivers/gpu/drm/nouveau/nve0_fifo.c b/drivers/gpu/drm/nouveau/nve0_fifo.c index e98d144e6eb..281bece751b 100644 --- a/drivers/gpu/drm/nouveau/nve0_fifo.c +++ b/drivers/gpu/drm/nouveau/nve0_fifo.c @@ -345,7 +345,8 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)  static void  nve0_fifo_isr(struct drm_device *dev)  { -	u32 stat = nv_rd32(dev, 0x002100); +	u32 mask = nv_rd32(dev, 0x002140); +	u32 stat = nv_rd32(dev, 0x002100) & mask;  	if (stat & 0x00000100) {  		NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 8acb34fd3fd..8d7e33a0b24 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1182,7 +1182,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)  	ring->ready = true;  	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); -	if (radeon_ring_supports_scratch_reg(rdev, ring)) { +	if (!ring->rptr_save_reg /* not resuming from suspend */ +	    && radeon_ring_supports_scratch_reg(rdev, ring)) {  		r = radeon_scratch_get(rdev, &ring->rptr_save_reg);  		if (r) {  			DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 7b737b9339a..2a59375dbe5 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -131,7 +131,7 @@ int radeon_fence_emit(struct radeon_device *rdev,   */  void radeon_fence_process(struct radeon_device *rdev, int ring)  { -	uint64_t seq, last_seq; +	uint64_t seq, last_seq, last_emitted;  	unsigned count_loop = 0;  	bool wake = false; @@ -158,13 +158,15 @@ void radeon_fence_process(struct radeon_device *rdev, int ring)  	 */  	last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);  	do { +		last_emitted = rdev->fence_drv[ring].sync_seq[ring];  		seq = radeon_fence_read(rdev, ring);  		seq |= last_seq & 0xffffffff00000000LL;  		if (seq < last_seq) { -			seq += 0x100000000LL; +			seq &= 0xffffffff; +			seq |= last_emitted & 0xffffffff00000000LL;  		} -		if (seq == last_seq) { +		if (seq <= last_seq || seq > last_emitted) {  			break;  		}  		/* If we loop over we don't want to return without diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index d31d4cca9a4..c5a164337bd 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -43,6 +43,9 @@ static const struct file_operations savage_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 7f119870147..867dc03000e 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -74,6 +74,9 @@ static const struct file_operations sis_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 90f6b13acfa..a7f4d6bd133 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -49,6 +49,9 @@ static const struct file_operations tdfx_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index ba055e9ca00..8d9dc44f1f9 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -69,6 +69,13 @@ static int udl_get_modes(struct drm_connector *connector)  static int udl_mode_valid(struct drm_connector *connector,  			  struct drm_display_mode *mode)  { +	struct udl_device *udl = connector->dev->dev_private; +	if (!udl->sku_pixel_limit) +		return 0; + +	if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) +		return MODE_VIRTUAL_Y; +  	return 0;  } diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 6e52069894b..9f84128505b 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -66,6 +66,9 @@ static const struct file_operations udl_driver_fops = {  	.unlocked_ioctl	= drm_ioctl,  	.release = drm_release,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index e927b4c052f..af1b914b17e 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -65,6 +65,9 @@ static const struct file_operations via_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig index 794ff67c570..b71bcd0bfbb 100644 --- a/drivers/gpu/drm/vmwgfx/Kconfig +++ b/drivers/gpu/drm/vmwgfx/Kconfig @@ -12,3 +12,11 @@ config DRM_VMWGFX  	  This is a KMS enabled DRM driver for the VMware SVGA2  	  virtual hardware.  	  The compiled module will be called "vmwgfx.ko". + +config DRM_VMWGFX_FBCON +	depends on DRM_VMWGFX +	bool "Enable framebuffer console under vmwgfx by default" +	help +	   Choose this option if you are shipping a new vmwgfx +	   userspace driver that supports using the kernel driver. + diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4d9edead01a..ba2c35dbf10 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -182,8 +182,9 @@ static struct pci_device_id vmw_pci_id_list[] = {  	{0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII},  	{0, 0, 0}  }; +MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); -static int enable_fbdev; +static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);  static int vmw_probe(struct pci_dev *, const struct pci_device_id *);  static void vmw_master_init(struct vmw_master *); @@ -1154,6 +1155,11 @@ static struct drm_driver driver = {  	.open = vmw_driver_open,  	.preclose = vmw_preclose,  	.postclose = vmw_postclose, + +	.dumb_create = vmw_dumb_create, +	.dumb_map_offset = vmw_dumb_map_offset, +	.dumb_destroy = vmw_dumb_destroy, +  	.fops = &vmwgfx_driver_fops,  	.name = VMWGFX_DRIVER_NAME,  	.desc = VMWGFX_DRIVER_DESC, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d0f2c079ee2..29c984ff7f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv,  int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,  				struct drm_file *file_priv); +int vmw_dumb_create(struct drm_file *file_priv, +		    struct drm_device *dev, +		    struct drm_mode_create_dumb *args); + +int vmw_dumb_map_offset(struct drm_file *file_priv, +			struct drm_device *dev, uint32_t handle, +			uint64_t *offset); +int vmw_dumb_destroy(struct drm_file *file_priv, +		     struct drm_device *dev, +		     uint32_t handle);  /**   * Overlay control - vmwgfx_overlay.c   */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index f2fb8f15e2f..7e0743358df 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv,  	} -	event = kzalloc(sizeof(event->event), GFP_KERNEL); +	event = kzalloc(sizeof(*event), GFP_KERNEL);  	if (unlikely(event == NULL)) {  		DRM_ERROR("Failed to allocate an event.\n");  		ret = -ENOMEM; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 22bf9a21ec7..2c6ffe0e2c0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1917,3 +1917,76 @@ err_ref:  	vmw_resource_unreference(&res);  	return ret;  } + + +int vmw_dumb_create(struct drm_file *file_priv, +		    struct drm_device *dev, +		    struct drm_mode_create_dumb *args) +{ +	struct vmw_private *dev_priv = vmw_priv(dev); +	struct vmw_master *vmaster = vmw_master(file_priv->master); +	struct vmw_user_dma_buffer *vmw_user_bo; +	struct ttm_buffer_object *tmp; +	int ret; + +	args->pitch = args->width * ((args->bpp + 7) / 8); +	args->size = args->pitch * args->height; + +	vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); +	if (vmw_user_bo == NULL) +		return -ENOMEM; + +	ret = ttm_read_lock(&vmaster->lock, true); +	if (ret != 0) { +		kfree(vmw_user_bo); +		return ret; +	} + +	ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, +			      &vmw_vram_sys_placement, true, +			      &vmw_user_dmabuf_destroy); +	if (ret != 0) +		goto out_no_dmabuf; + +	tmp = ttm_bo_reference(&vmw_user_bo->dma.base); +	ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, +				   &vmw_user_bo->base, +				   false, +				   ttm_buffer_type, +				   &vmw_user_dmabuf_release, NULL); +	if (unlikely(ret != 0)) +		goto out_no_base_object; + +	args->handle = vmw_user_bo->base.hash.key; + +out_no_base_object: +	ttm_bo_unref(&tmp); +out_no_dmabuf: +	ttm_read_unlock(&vmaster->lock); +	return ret; +} + +int vmw_dumb_map_offset(struct drm_file *file_priv, +			struct drm_device *dev, uint32_t handle, +			uint64_t *offset) +{ +	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; +	struct vmw_dma_buffer *out_buf; +	int ret; + +	ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); +	if (ret != 0) +		return -EINVAL; + +	*offset = out_buf->base.addr_space_offset; +	vmw_dmabuf_unreference(&out_buf); +	return 0; +} + +int vmw_dumb_destroy(struct drm_file *file_priv, +		     struct drm_device *dev, +		     uint32_t handle) +{ +	return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, +					 handle, TTM_REF_USAGE); +} diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 77d2df04c97..60c4e1e8591 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -519,6 +519,8 @@ static void tpkbd_remove_tp(struct hid_device *hdev)  	led_classdev_unregister(&data_pointer->led_mute);  	hid_set_drvdata(hdev, NULL); +	kfree(data_pointer->led_micmute.name); +	kfree(data_pointer->led_mute.name);  	kfree(data_pointer);  } diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 4d524b5f52f..9500f2f3f8f 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -193,6 +193,7 @@ static struct hid_ll_driver logi_dj_ll_driver;  static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,  					size_t count,  					unsigned char report_type); +static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);  static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,  						struct dj_report *dj_report) @@ -233,6 +234,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,  	if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &  	    SPFUNCTION_DEVICE_LIST_EMPTY) {  		dbg_hid("%s: device list is empty\n", __func__); +		djrcv_dev->querying_devices = false;  		return;  	} @@ -243,6 +245,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,  		return;  	} +	if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { +		/* The device is already known. No need to reallocate it. */ +		dbg_hid("%s: device is already known\n", __func__); +		return; +	} +  	dj_hiddev = hid_allocate_device();  	if (IS_ERR(dj_hiddev)) {  		dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", @@ -306,6 +314,7 @@ static void delayedwork_callback(struct work_struct *work)  	struct dj_report dj_report;  	unsigned long flags;  	int count; +	int retval;  	dbg_hid("%s\n", __func__); @@ -338,6 +347,25 @@ static void delayedwork_callback(struct work_struct *work)  		logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);  		break;  	default: +	/* A normal report (i. e. not belonging to a pair/unpair notification) +	 * arriving here, means that the report arrived but we did not have a +	 * paired dj_device associated to the report's device_index, this +	 * means that the original "device paired" notification corresponding +	 * to this dj_device never arrived to this driver. The reason is that +	 * hid-core discards all packets coming from a device while probe() is +	 * executing. */ +	if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { +		/* ok, we don't know the device, just re-ask the +		 * receiver for the list of connected devices. */ +		retval = logi_dj_recv_query_paired_devices(djrcv_dev); +		if (!retval) { +			/* everything went fine, so just leave */ +			break; +		} +		dev_err(&djrcv_dev->hdev->dev, +			"%s:logi_dj_recv_query_paired_devices " +			"error:%d\n", __func__, retval); +		}  		dbg_hid("%s: unexpected report type\n", __func__);  	}  } @@ -368,6 +396,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,  	if (!djdev) {  		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"  			" is NULL, index %d\n", dj_report->device_index); +		kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); + +		if (schedule_work(&djrcv_dev->work) == 0) { +			dbg_hid("%s: did not schedule the work item, was already " +			"queued\n", __func__); +		}  		return;  	} @@ -398,6 +432,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,  	if (dj_device == NULL) {  		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"  			" is NULL, index %d\n", dj_report->device_index); +		kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); + +		if (schedule_work(&djrcv_dev->work) == 0) { +			dbg_hid("%s: did not schedule the work item, was already " +			"queued\n", __func__); +		}  		return;  	} @@ -439,6 +479,10 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)  	struct dj_report *dj_report;  	int retval; +	/* no need to protect djrcv_dev->querying_devices */ +	if (djrcv_dev->querying_devices) +		return 0; +  	dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);  	if (!dj_report)  		return -ENOMEM; @@ -450,6 +494,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)  	return retval;  } +  static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,  					  unsigned timeout)  { diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h index fd28a5e0ca3..4a4000340ce 100644 --- a/drivers/hid/hid-logitech-dj.h +++ b/drivers/hid/hid-logitech-dj.h @@ -101,6 +101,7 @@ struct dj_receiver_dev {  	struct work_struct work;  	struct kfifo notif_fifo;  	spinlock_t lock; +	bool querying_devices;  };  struct dj_device { diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index cfec802cf9c..f915eb1c29f 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c @@ -87,10 +87,18 @@ static ssize_t ad7314_show_temperature(struct device *dev,  	}  } +static ssize_t ad7314_show_name(struct device *dev, +				struct device_attribute *devattr, char *buf) +{ +	return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); +} + +static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL);  static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,  			  ad7314_show_temperature, NULL, 0);  static struct attribute *ad7314_attributes[] = { +	&dev_attr_name.attr,  	&sensor_dev_attr_temp1_input.dev_attr.attr,  	NULL,  }; diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index e65c6e45d36..7bf4ce3d405 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -139,6 +139,12 @@ static ssize_t show_voltage(struct device *dev,  	}  } +static ssize_t ads7871_show_name(struct device *dev, +				 struct device_attribute *devattr, char *buf) +{ +	return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); +} +  static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0);  static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1);  static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); @@ -148,6 +154,8 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5);  static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6);  static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); +static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL); +  static struct attribute *ads7871_attributes[] = {  	&sensor_dev_attr_in0_input.dev_attr.attr,  	&sensor_dev_attr_in1_input.dev_attr.attr, @@ -157,6 +165,7 @@ static struct attribute *ads7871_attributes[] = {  	&sensor_dev_attr_in5_input.dev_attr.attr,  	&sensor_dev_attr_in6_input.dev_attr.attr,  	&sensor_dev_attr_in7_input.dev_attr.attr, +	&dev_attr_name.attr,  	NULL  }; diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 28270886051..8f3f6f2c45f 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -53,10 +53,10 @@  #define APPLESMC_MAX_DATA_LENGTH 32 -/* wait up to 32 ms for a status change. */ +/* wait up to 128 ms for a status change. */  #define APPLESMC_MIN_WAIT	0x0010  #define APPLESMC_RETRY_WAIT	0x0100 -#define APPLESMC_MAX_WAIT	0x8000 +#define APPLESMC_MAX_WAIT	0x20000  #define APPLESMC_READ_CMD	0x10  #define APPLESMC_WRITE_CMD	0x11 diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 0fa356fe82c..984a3f13923 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -815,17 +815,20 @@ static int __init coretemp_init(void)  	if (err)  		goto exit; +	get_online_cpus();  	for_each_online_cpu(i)  		get_core_online(i);  #ifndef CONFIG_HOTPLUG_CPU  	if (list_empty(&pdev_list)) { +		put_online_cpus();  		err = -ENODEV;  		goto exit_driver_unreg;  	}  #endif  	register_hotcpu_notifier(&coretemp_cpu_notifier); +	put_online_cpus();  	return 0;  #ifndef CONFIG_HOTPLUG_CPU @@ -840,6 +843,7 @@ static void __exit coretemp_exit(void)  {  	struct pdev_entry *p, *n; +	get_online_cpus();  	unregister_hotcpu_notifier(&coretemp_cpu_notifier);  	mutex_lock(&pdev_list_mutex);  	list_for_each_entry_safe(p, n, &pdev_list, list) { @@ -848,6 +852,7 @@ static void __exit coretemp_exit(void)  		kfree(p);  	}  	mutex_unlock(&pdev_list_mutex); +	put_online_cpus();  	platform_driver_unregister(&coretemp_driver);  } diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 2764b78a784..af69073b3fe 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -129,12 +129,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)   * counter saturations resulting in bogus power readings.   * We correct this value ourselves to cope with older BIOSes.   */ -static DEFINE_PCI_DEVICE_TABLE(affected_device) = { +static const struct pci_device_id affected_device[] = {  	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },  	{ 0 }  }; -static void __devinit tweak_runavg_range(struct pci_dev *pdev) +static void tweak_runavg_range(struct pci_dev *pdev)  {  	u32 val; @@ -158,6 +158,16 @@ static void __devinit tweak_runavg_range(struct pci_dev *pdev)  		REG_TDP_RUNNING_AVERAGE, val);  } +#ifdef CONFIG_PM +static int fam15h_power_resume(struct pci_dev *pdev) +{ +	tweak_runavg_range(pdev); +	return 0; +} +#else +#define fam15h_power_resume NULL +#endif +  static void __devinit fam15h_power_init_data(struct pci_dev *f4,  					     struct fam15h_power_data *data)  { @@ -256,6 +266,7 @@ static struct pci_driver fam15h_power_driver = {  	.id_table = fam15h_power_id_table,  	.probe = fam15h_power_probe,  	.remove = __devexit_p(fam15h_power_remove), +	.resume = fam15h_power_resume,  };  module_pci_driver(fam15h_power_driver); diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index 7f3f4a38572..602148299f6 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -69,22 +69,6 @@ struct ina2xx_data {  	u16 regs[INA2XX_MAX_REGISTERS];  }; -int ina2xx_read_word(struct i2c_client *client, int reg) -{ -	int val = i2c_smbus_read_word_data(client, reg); -	if (unlikely(val < 0)) { -		dev_dbg(&client->dev, -			"Failed to read register: %d\n", reg); -		return val; -	} -	return be16_to_cpu(val); -} - -void ina2xx_write_word(struct i2c_client *client, int reg, int data) -{ -	i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); -} -  static struct ina2xx_data *ina2xx_update_device(struct device *dev)  {  	struct i2c_client *client = to_i2c_client(dev); @@ -102,7 +86,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev)  		/* Read all registers */  		for (i = 0; i < data->registers; i++) { -			int rv = ina2xx_read_word(client, i); +			int rv = i2c_smbus_read_word_swapped(client, i);  			if (rv < 0) {  				ret = ERR_PTR(rv);  				goto abort; @@ -279,22 +263,26 @@ static int ina2xx_probe(struct i2c_client *client,  	switch (data->kind) {  	case ina219:  		/* device configuration */ -		ina2xx_write_word(client, INA2XX_CONFIG, INA219_CONFIG_DEFAULT); +		i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, +					     INA219_CONFIG_DEFAULT);  		/* set current LSB to 1mA, shunt is in uOhms */  		/* (equation 13 in datasheet) */ -		ina2xx_write_word(client, INA2XX_CALIBRATION, 40960000 / shunt); +		i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, +					     40960000 / shunt);  		dev_info(&client->dev,  			 "power monitor INA219 (Rshunt = %li uOhm)\n", shunt);  		data->registers = INA219_REGISTERS;  		break;  	case ina226:  		/* device configuration */ -		ina2xx_write_word(client, INA2XX_CONFIG, INA226_CONFIG_DEFAULT); +		i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, +					     INA226_CONFIG_DEFAULT);  		/* set current LSB to 1mA, shunt is in uOhms */  		/* (equation 1 in datasheet)*/ -		ina2xx_write_word(client, INA2XX_CALIBRATION, 5120000 / shunt); +		i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, +					     5120000 / shunt);  		dev_info(&client->dev,  			 "power monitor INA226 (Rshunt = %li uOhm)\n", shunt);  		data->registers = INA226_REGISTERS; diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 0018c7dd009..1a174f0a3cd 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev,  			 struct device_attribute *devattr, char *buf)  {  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -	struct twl4030_madc_request req; +	struct twl4030_madc_request req = { +		.channels = 1 << attr->index, +		.method = TWL4030_MADC_SW2, +		.type = TWL4030_MADC_WAIT, +	};  	long val; -	req.channels = (1 << attr->index); -	req.method = TWL4030_MADC_SW2; -	req.func_cb = NULL;  	val = twl4030_madc_conversion(&req);  	if (val < 0)  		return val; diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index ee4ebc198a9..2e56c6ce9fb 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -328,6 +328,7 @@ static int __init via_cputemp_init(void)  	if (err)  		goto exit; +	get_online_cpus();  	for_each_online_cpu(i) {  		struct cpuinfo_x86 *c = &cpu_data(i); @@ -347,12 +348,14 @@ static int __init via_cputemp_init(void)  #ifndef CONFIG_HOTPLUG_CPU  	if (list_empty(&pdev_list)) { +		put_online_cpus();  		err = -ENODEV;  		goto exit_driver_unreg;  	}  #endif  	register_hotcpu_notifier(&via_cputemp_cpu_notifier); +	put_online_cpus();  	return 0;  #ifndef CONFIG_HOTPLUG_CPU @@ -367,6 +370,7 @@ static void __exit via_cputemp_exit(void)  {  	struct pdev_entry *p, *n; +	get_online_cpus();  	unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);  	mutex_lock(&pdev_list_mutex);  	list_for_each_entry_safe(p, n, &pdev_list, list) { @@ -375,6 +379,7 @@ static void __exit via_cputemp_exit(void)  		kfree(p);  	}  	mutex_unlock(&pdev_list_mutex); +	put_online_cpus();  	platform_driver_unregister(&via_cputemp_driver);  } diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index 1201a15784c..db713c0dfba 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -552,7 +552,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);   */  int hwspin_lock_free(struct hwspinlock *hwlock)  { -	struct device *dev = hwlock->bank->dev; +	struct device *dev;  	struct hwspinlock *tmp;  	int ret; @@ -561,6 +561,7 @@ int hwspin_lock_free(struct hwspinlock *hwlock)  		return -EINVAL;  	} +	dev = hwlock->bank->dev;  	mutex_lock(&hwspinlock_tree_lock);  	/* make sure the hwspinlock is used */ diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 73133b1063f..6f5f98d69af 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -476,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap)  		/* To avoid integer overflow, use clock/100 for calculations */  		clock = pca_clock(pca_data) / 100; -		if (pca_data->i2c_clock > 10000) { +		if (pca_data->i2c_clock > 1000000) {  			mode = I2C_PCA_MODE_TURBO;  			min_tlow = 14;  			min_thi  = 5;  			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ -		} else if (pca_data->i2c_clock > 4000) { +		} else if (pca_data->i2c_clock > 400000) {  			mode = I2C_PCA_MODE_FASTP;  			min_tlow = 17;  			min_thi  = 9;  			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ -		} else if (pca_data->i2c_clock > 1000) { +		} else if (pca_data->i2c_clock > 100000) {  			mode = I2C_PCA_MODE_FAST;  			min_tlow = 44;  			min_thi  = 20; diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b4aaa1bd672..970a1612e79 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -104,6 +104,7 @@ config I2C_I801  	    DH89xxCC (PCH)  	    Panther Point (PCH)  	    Lynx Point (PCH) +	    Lynx Point-LP (PCH)  	  This driver can also be built as a module.  If so, the module  	  will be called i2c-i801. @@ -354,9 +355,13 @@ config I2C_DAVINCI  	  devices such as DaVinci NIC.  	  For details please see http://www.ti.com/davinci +config I2C_DESIGNWARE_CORE +	tristate +  config I2C_DESIGNWARE_PLATFORM  	tristate "Synopsys DesignWare Platform"  	depends on HAVE_CLK +	select I2C_DESIGNWARE_CORE  	help  	  If you say yes to this option, support will be included for the  	  Synopsys DesignWare I2C adapter. Only master mode is supported. @@ -367,6 +372,7 @@ config I2C_DESIGNWARE_PLATFORM  config I2C_DESIGNWARE_PCI  	tristate "Synopsys DesignWare PCI"  	depends on PCI +	select I2C_DESIGNWARE_CORE  	help  	  If you say yes to this option, support will be included for the  	  Synopsys DesignWare I2C adapter. Only master mode is supported. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ce3c2be7fb4..37c4182cc98 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o  obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o  obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o  obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o +obj-$(CONFIG_I2C_DESIGNWARE_CORE)	+= i2c-designware-core.o  obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o +i2c-designware-platform-objs := i2c-designware-platdrv.o  obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o +i2c-designware-pci-objs := i2c-designware-pcidrv.o  obj-$(CONFIG_I2C_EG20T)		+= i2c-eg20t.o  obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o  obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 1e48bec80ed..7b8ebbefb58 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -25,6 +25,7 @@   * ----------------------------------------------------------------------------   *   */ +#include <linux/export.h>  #include <linux/clk.h>  #include <linux/errno.h>  #include <linux/err.h> @@ -316,6 +317,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)  	dw_writel(dev, dev->master_cfg , DW_IC_CON);  	return 0;  } +EXPORT_SYMBOL_GPL(i2c_dw_init);  /*   * Waiting for bus not busy @@ -568,12 +570,14 @@ done:  	return ret;  } +EXPORT_SYMBOL_GPL(i2c_dw_xfer);  u32 i2c_dw_func(struct i2c_adapter *adap)  {  	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);  	return dev->functionality;  } +EXPORT_SYMBOL_GPL(i2c_dw_func);  static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)  { @@ -678,17 +682,20 @@ tx_aborted:  	return IRQ_HANDLED;  } +EXPORT_SYMBOL_GPL(i2c_dw_isr);  void i2c_dw_enable(struct dw_i2c_dev *dev)  {         /* Enable the adapter */  	dw_writel(dev, 1, DW_IC_ENABLE);  } +EXPORT_SYMBOL_GPL(i2c_dw_enable);  u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)  {  	return dw_readl(dev, DW_IC_ENABLE);  } +EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);  void i2c_dw_disable(struct dw_i2c_dev *dev)  { @@ -699,18 +706,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)  	dw_writel(dev, 0, DW_IC_INTR_MASK);  	dw_readl(dev, DW_IC_CLR_INTR);  } +EXPORT_SYMBOL_GPL(i2c_dw_disable);  void i2c_dw_clear_int(struct dw_i2c_dev *dev)  {  	dw_readl(dev, DW_IC_CLR_INTR);  } +EXPORT_SYMBOL_GPL(i2c_dw_clear_int);  void i2c_dw_disable_int(struct dw_i2c_dev *dev)  {  	dw_writel(dev, 0, DW_IC_INTR_MASK);  } +EXPORT_SYMBOL_GPL(i2c_dw_disable_int);  u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)  {  	return dw_readl(dev, DW_IC_COMP_PARAM_1);  } +EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 898dcf9c7ad..33e9b0c09af 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -52,6 +52,7 @@    DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes    Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes    Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes +  Lynx Point-LP (PCH)   0x9c22     32     hard     yes     yes     yes    Features supported by this driver:    Software PEC                     no @@ -155,6 +156,7 @@  #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS	0x2330  #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS	0x3b30  #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS	0x8c22 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS	0x9c22  struct i801_priv {  	struct i2c_adapter adapter; @@ -771,6 +773,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) },  	{ 0, }  }; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 088c5c1ed17..51f05b8520e 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -365,10 +365,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)  	struct device_node *node = dev->of_node;  	int ret; -	if (!node) -		return -EINVAL; - -	i2c->speed = &mxs_i2c_95kHz_config;  	ret = of_property_read_u32(node, "clock-frequency", &speed);  	if (ret)  		dev_warn(dev, "No I2C speed selected, using 100kHz\n"); @@ -419,10 +415,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)  		return err;  	i2c->dev = dev; +	i2c->speed = &mxs_i2c_95kHz_config; -	err = mxs_i2c_get_ofdata(i2c); -	if (err) -		return err; +	if (dev->of_node) { +		err = mxs_i2c_get_ofdata(i2c); +		if (err) +			return err; +	}  	platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d54416770b..8488bddfe46 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -48,8 +48,9 @@ enum {  	mcntrl_afie = 0x00000002,  	mcntrl_naie = 0x00000004,  	mcntrl_drmie = 0x00000008, -	mcntrl_daie = 0x00000020, -	mcntrl_rffie = 0x00000040, +	mcntrl_drsie = 0x00000010, +	mcntrl_rffie = 0x00000020, +	mcntrl_daie = 0x00000040,  	mcntrl_tffie = 0x00000080,  	mcntrl_reset = 0x00000100,  	mcntrl_cdbmode = 0x00000400, @@ -290,31 +291,37 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)  	 * or we didn't 'ask' for it yet.  	 */  	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { -		dev_dbg(&alg_data->adapter.dev, -			"%s(): Write dummy data to fill Rx-fifo...\n", -			__func__); +		/* 'Asking' is done asynchronously, e.g. dummy TX of several +		 * bytes is done before the first actual RX arrives in FIFO. +		 * Therefore, ordered bytes (via TX) are counted separately. +		 */ +		if (alg_data->mif.order) { +			dev_dbg(&alg_data->adapter.dev, +				"%s(): Write dummy data to fill Rx-fifo...\n", +				__func__); -		if (alg_data->mif.len == 1) { -			/* Last byte, do not acknowledge next rcv. */ -			val |= stop_bit; +			if (alg_data->mif.order == 1) { +				/* Last byte, do not acknowledge next rcv. */ +				val |= stop_bit; + +				/* +				 * Enable interrupt RFDAIE (data in Rx fifo), +				 * and disable DRMIE (need data for Tx) +				 */ +				ctl = ioread32(I2C_REG_CTL(alg_data)); +				ctl |= mcntrl_rffie | mcntrl_daie; +				ctl &= ~mcntrl_drmie; +				iowrite32(ctl, I2C_REG_CTL(alg_data)); +			}  			/* -			 * Enable interrupt RFDAIE (data in Rx fifo), -			 * and disable DRMIE (need data for Tx) +			 * Now we'll 'ask' for data: +			 * For each byte we want to receive, we must +			 * write a (dummy) byte to the Tx-FIFO.  			 */ -			ctl = ioread32(I2C_REG_CTL(alg_data)); -			ctl |= mcntrl_rffie | mcntrl_daie; -			ctl &= ~mcntrl_drmie; -			iowrite32(ctl, I2C_REG_CTL(alg_data)); +			iowrite32(val, I2C_REG_TX(alg_data)); +			alg_data->mif.order--;  		} - -		/* -		 * Now we'll 'ask' for data: -		 * For each byte we want to receive, we must -		 * write a (dummy) byte to the Tx-FIFO. -		 */ -		iowrite32(val, I2C_REG_TX(alg_data)); -  		return 0;  	} @@ -514,6 +521,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  		alg_data->mif.buf = pmsg->buf;  		alg_data->mif.len = pmsg->len; +		alg_data->mif.order = pmsg->len;  		alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?  			I2C_SMBUS_READ : I2C_SMBUS_WRITE;  		alg_data->mif.ret = 0; @@ -566,6 +574,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  	/* Cleanup to be sure... */  	alg_data->mif.buf = NULL;  	alg_data->mif.len = 0; +	alg_data->mif.order = 0;  	dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",  		__func__, ioread32(I2C_REG_STS(alg_data))); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2efa56c5ff2..2091ae8f539 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -637,6 +637,22 @@ static void i2c_adapter_dev_release(struct device *dev)  }  /* + * This function is only needed for mutex_lock_nested, so it is never + * called unless locking correctness checking is enabled. Thus we + * make it inline to avoid a compiler warning. That's what gcc ends up + * doing anyway. + */ +static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) +{ +	unsigned int depth = 0; + +	while ((adapter = i2c_parent_is_i2c_adapter(adapter))) +		depth++; + +	return depth; +} + +/*   * Let users instantiate I2C devices through sysfs. This can be used when   * platform initialization code doesn't contain the proper data for   * whatever reason. Also useful for drivers that do device detection and @@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,  	/* Make sure the device was added through sysfs */  	res = -ENOENT; -	mutex_lock(&adap->userspace_clients_lock); +	mutex_lock_nested(&adap->userspace_clients_lock, +			  i2c_adapter_depth(adap));  	list_for_each_entry_safe(client, next, &adap->userspace_clients,  				 detected) {  		if (client->addr == addr) { @@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)  		return res;  	/* Remove devices instantiated from sysfs */ -	mutex_lock(&adap->userspace_clients_lock); +	mutex_lock_nested(&adap->userspace_clients_lock, +			  i2c_adapter_depth(adap));  	list_for_each_entry_safe(client, next, &adap->userspace_clients,  				 detected) {  		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index f61780a0237..3bd5540238a 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -617,7 +617,7 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)  	st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");  	if (IS_ERR(st->adc_clk)) {  		dev_err(&pdev->dev, "Failed to get the ADC clock.\n"); -		ret = PTR_ERR(st->clk); +		ret = PTR_ERR(st->adc_clk);  		goto error_disable_clk;  	} diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 51f42061dae..6cfd4d8fd0b 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1361,11 +1361,11 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)  	struct tid_info *t = dev->rdev.lldi.tids;  	ep = lookup_tid(t, tid); -	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);  	if (!ep) {  		printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n");  		return 0;  	} +	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);  	mutex_lock(&ep->com.mutex);  	switch (ep->com.state) {  	case ABORTING: diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index cb5b7f7d4d3..b29a4246ef4 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -2219,7 +2219,6 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp,  	u32 wqe_idx;  	if (!qp->wqe_wr_id_tbl[tail].signaled) { -		expand = true;	/* CQE cannot be consumed yet */  		*polled = false;    /* WC cannot be consumed yet */  	} else {  		ibwc->status = IB_WC_SUCCESS; @@ -2227,10 +2226,11 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp,  		ibwc->qp = &qp->ibqp;  		ocrdma_update_wc(qp, ibwc, tail);  		*polled = true; -		wqe_idx = le32_to_cpu(cqe->wq.wqeidx) &	OCRDMA_CQE_WQEIDX_MASK; -		if (tail != wqe_idx) -			expand = true; /* Coalesced CQE can't be consumed yet */  	} +	wqe_idx = le32_to_cpu(cqe->wq.wqeidx) &	OCRDMA_CQE_WQEIDX_MASK; +	if (tail != wqe_idx) +		expand = true; /* Coalesced CQE can't be consumed yet */ +  	ocrdma_hwq_inc_tail(&qp->sq);  	return expand;  } diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index 19f1e6c45fb..ccb119143d2 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c @@ -471,9 +471,10 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev,  		if (port_num != port) {  			ibp = to_iport(ibdev, port_num);  			ret = check_mkey(ibp, smp, 0); -			if (ret) +			if (ret) {  				ret = IB_MAD_RESULT_FAILURE;  				goto bail; +			}  		}  	} diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index ca43901ed86..0af216d21f8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -262,7 +262,10 @@ struct ipoib_ethtool_st {  	u16     max_coalesced_frames;  }; +struct ipoib_neigh_table; +  struct ipoib_neigh_hash { +	struct ipoib_neigh_table       *ntbl;  	struct ipoib_neigh __rcu      **buckets;  	struct rcu_head			rcu;  	u32				mask; @@ -271,9 +274,9 @@ struct ipoib_neigh_hash {  struct ipoib_neigh_table {  	struct ipoib_neigh_hash __rcu  *htbl; -	rwlock_t			rwlock;  	atomic_t			entries;  	struct completion		flushed; +	struct completion		deleted;  };  /* diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3e2085a3ee4..1e19b5ae7c4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -546,15 +546,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,  	struct ipoib_neigh *neigh;  	unsigned long flags; +	spin_lock_irqsave(&priv->lock, flags);  	neigh = ipoib_neigh_alloc(daddr, dev);  	if (!neigh) { +		spin_unlock_irqrestore(&priv->lock, flags);  		++dev->stats.tx_dropped;  		dev_kfree_skb_any(skb);  		return;  	} -	spin_lock_irqsave(&priv->lock, flags); -  	path = __path_find(dev, daddr + 4);  	if (!path) {  		path = path_rec_create(dev, daddr + 4); @@ -863,10 +863,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)  	if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))  		return; -	write_lock_bh(&ntbl->rwlock); +	spin_lock_irqsave(&priv->lock, flags);  	htbl = rcu_dereference_protected(ntbl->htbl, -					 lockdep_is_held(&ntbl->rwlock)); +					 lockdep_is_held(&priv->lock));  	if (!htbl)  		goto out_unlock; @@ -883,16 +883,14 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)  		struct ipoib_neigh __rcu **np = &htbl->buckets[i];  		while ((neigh = rcu_dereference_protected(*np, -							  lockdep_is_held(&ntbl->rwlock))) != NULL) { +							  lockdep_is_held(&priv->lock))) != NULL) {  			/* was the neigh idle for two GC periods */  			if (time_after(neigh_obsolete, neigh->alive)) {  				rcu_assign_pointer(*np,  						   rcu_dereference_protected(neigh->hnext, -									     lockdep_is_held(&ntbl->rwlock))); +									     lockdep_is_held(&priv->lock)));  				/* remove from path/mc list */ -				spin_lock_irqsave(&priv->lock, flags);  				list_del(&neigh->list); -				spin_unlock_irqrestore(&priv->lock, flags);  				call_rcu(&neigh->rcu, ipoib_neigh_reclaim);  			} else {  				np = &neigh->hnext; @@ -902,7 +900,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)  	}  out_unlock: -	write_unlock_bh(&ntbl->rwlock); +	spin_unlock_irqrestore(&priv->lock, flags);  }  static void ipoib_reap_neigh(struct work_struct *work) @@ -947,10 +945,8 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,  	struct ipoib_neigh *neigh;  	u32 hash_val; -	write_lock_bh(&ntbl->rwlock); -  	htbl = rcu_dereference_protected(ntbl->htbl, -					 lockdep_is_held(&ntbl->rwlock)); +					 lockdep_is_held(&priv->lock));  	if (!htbl) {  		neigh = NULL;  		goto out_unlock; @@ -961,10 +957,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,  	 */  	hash_val = ipoib_addr_hash(htbl, daddr);  	for (neigh = rcu_dereference_protected(htbl->buckets[hash_val], -					       lockdep_is_held(&ntbl->rwlock)); +					       lockdep_is_held(&priv->lock));  	     neigh != NULL;  	     neigh = rcu_dereference_protected(neigh->hnext, -					       lockdep_is_held(&ntbl->rwlock))) { +					       lockdep_is_held(&priv->lock))) {  		if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {  			/* found, take one ref on behalf of the caller */  			if (!atomic_inc_not_zero(&neigh->refcnt)) { @@ -987,12 +983,11 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,  	/* put in hash */  	rcu_assign_pointer(neigh->hnext,  			   rcu_dereference_protected(htbl->buckets[hash_val], -						     lockdep_is_held(&ntbl->rwlock))); +						     lockdep_is_held(&priv->lock)));  	rcu_assign_pointer(htbl->buckets[hash_val], neigh);  	atomic_inc(&ntbl->entries);  out_unlock: -	write_unlock_bh(&ntbl->rwlock);  	return neigh;  } @@ -1040,35 +1035,29 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh)  	struct ipoib_neigh *n;  	u32 hash_val; -	write_lock_bh(&ntbl->rwlock); -  	htbl = rcu_dereference_protected(ntbl->htbl, -					lockdep_is_held(&ntbl->rwlock)); +					lockdep_is_held(&priv->lock));  	if (!htbl) -		goto out_unlock; +		return;  	hash_val = ipoib_addr_hash(htbl, neigh->daddr);  	np = &htbl->buckets[hash_val];  	for (n = rcu_dereference_protected(*np, -					    lockdep_is_held(&ntbl->rwlock)); +					    lockdep_is_held(&priv->lock));  	     n != NULL;  	     n = rcu_dereference_protected(*np, -					lockdep_is_held(&ntbl->rwlock))) { +					lockdep_is_held(&priv->lock))) {  		if (n == neigh) {  			/* found */  			rcu_assign_pointer(*np,  					   rcu_dereference_protected(neigh->hnext, -								     lockdep_is_held(&ntbl->rwlock))); +								     lockdep_is_held(&priv->lock)));  			call_rcu(&neigh->rcu, ipoib_neigh_reclaim); -			goto out_unlock; +			return;  		} else {  			np = &n->hnext;  		}  	} - -out_unlock: -	write_unlock_bh(&ntbl->rwlock); -  }  static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) @@ -1080,7 +1069,6 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)  	clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);  	ntbl->htbl = NULL; -	rwlock_init(&ntbl->rwlock);  	htbl = kzalloc(sizeof(*htbl), GFP_KERNEL);  	if (!htbl)  		return -ENOMEM; @@ -1095,6 +1083,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)  	htbl->mask = (size - 1);  	htbl->buckets = buckets;  	ntbl->htbl = htbl; +	htbl->ntbl = ntbl;  	atomic_set(&ntbl->entries, 0);  	/* start garbage collection */ @@ -1111,9 +1100,11 @@ static void neigh_hash_free_rcu(struct rcu_head *head)  						    struct ipoib_neigh_hash,  						    rcu);  	struct ipoib_neigh __rcu **buckets = htbl->buckets; +	struct ipoib_neigh_table *ntbl = htbl->ntbl;  	kfree(buckets);  	kfree(htbl); +	complete(&ntbl->deleted);  }  void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) @@ -1125,10 +1116,10 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)  	int i;  	/* remove all neigh connected to a given path or mcast */ -	write_lock_bh(&ntbl->rwlock); +	spin_lock_irqsave(&priv->lock, flags);  	htbl = rcu_dereference_protected(ntbl->htbl, -					 lockdep_is_held(&ntbl->rwlock)); +					 lockdep_is_held(&priv->lock));  	if (!htbl)  		goto out_unlock; @@ -1138,16 +1129,14 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)  		struct ipoib_neigh __rcu **np = &htbl->buckets[i];  		while ((neigh = rcu_dereference_protected(*np, -							  lockdep_is_held(&ntbl->rwlock))) != NULL) { +							  lockdep_is_held(&priv->lock))) != NULL) {  			/* delete neighs belong to this parent */  			if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) {  				rcu_assign_pointer(*np,  						   rcu_dereference_protected(neigh->hnext, -									     lockdep_is_held(&ntbl->rwlock))); +									     lockdep_is_held(&priv->lock)));  				/* remove from parent list */ -				spin_lock_irqsave(&priv->lock, flags);  				list_del(&neigh->list); -				spin_unlock_irqrestore(&priv->lock, flags);  				call_rcu(&neigh->rcu, ipoib_neigh_reclaim);  			} else {  				np = &neigh->hnext; @@ -1156,7 +1145,7 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)  		}  	}  out_unlock: -	write_unlock_bh(&ntbl->rwlock); +	spin_unlock_irqrestore(&priv->lock, flags);  }  static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) @@ -1164,37 +1153,44 @@ static void ipoib_flush_neighs(struct ipoib_dev_priv *priv)  	struct ipoib_neigh_table *ntbl = &priv->ntbl;  	struct ipoib_neigh_hash *htbl;  	unsigned long flags; -	int i; +	int i, wait_flushed = 0; -	write_lock_bh(&ntbl->rwlock); +	init_completion(&priv->ntbl.flushed); + +	spin_lock_irqsave(&priv->lock, flags);  	htbl = rcu_dereference_protected(ntbl->htbl, -					lockdep_is_held(&ntbl->rwlock)); +					lockdep_is_held(&priv->lock));  	if (!htbl)  		goto out_unlock; +	wait_flushed = atomic_read(&priv->ntbl.entries); +	if (!wait_flushed) +		goto free_htbl; +  	for (i = 0; i < htbl->size; i++) {  		struct ipoib_neigh *neigh;  		struct ipoib_neigh __rcu **np = &htbl->buckets[i];  		while ((neigh = rcu_dereference_protected(*np, -							  lockdep_is_held(&ntbl->rwlock))) != NULL) { +				       lockdep_is_held(&priv->lock))) != NULL) {  			rcu_assign_pointer(*np,  					   rcu_dereference_protected(neigh->hnext, -								     lockdep_is_held(&ntbl->rwlock))); +								     lockdep_is_held(&priv->lock)));  			/* remove from path/mc list */ -			spin_lock_irqsave(&priv->lock, flags);  			list_del(&neigh->list); -			spin_unlock_irqrestore(&priv->lock, flags);  			call_rcu(&neigh->rcu, ipoib_neigh_reclaim);  		}  	} +free_htbl:  	rcu_assign_pointer(ntbl->htbl, NULL);  	call_rcu(&htbl->rcu, neigh_hash_free_rcu);  out_unlock: -	write_unlock_bh(&ntbl->rwlock); +	spin_unlock_irqrestore(&priv->lock, flags); +	if (wait_flushed) +		wait_for_completion(&priv->ntbl.flushed);  }  static void ipoib_neigh_hash_uninit(struct net_device *dev) @@ -1203,7 +1199,7 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)  	int stopped;  	ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n"); -	init_completion(&priv->ntbl.flushed); +	init_completion(&priv->ntbl.deleted);  	set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);  	/* Stop GC if called at init fail need to cancel work */ @@ -1211,10 +1207,9 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)  	if (!stopped)  		cancel_delayed_work(&priv->neigh_reap_task); -	if (atomic_read(&priv->ntbl.entries)) { -		ipoib_flush_neighs(priv); -		wait_for_completion(&priv->ntbl.flushed); -	} +	ipoib_flush_neighs(priv); + +	wait_for_completion(&priv->ntbl.deleted);  } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 13f4aa7593c..75367249f44 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -707,9 +707,7 @@ out:  		neigh = ipoib_neigh_get(dev, daddr);  		spin_lock_irqsave(&priv->lock, flags);  		if (!neigh) { -			spin_unlock_irqrestore(&priv->lock, flags);  			neigh = ipoib_neigh_alloc(daddr, dev); -			spin_lock_irqsave(&priv->lock, flags);  			if (neigh) {  				kref_get(&mcast->ah->ref);  				neigh->ah	= mcast->ah; diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index ce68e361558..cdc252612c0 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -516,9 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)  	input_set_drvdata(input_dev, keypad);  	/* Ensure that the keypad will stay dormant until opened */ -	clk_enable(keypad->clk); +	clk_prepare_enable(keypad->clk);  	imx_keypad_inhibit(keypad); -	clk_disable(keypad->clk); +	clk_disable_unprepare(keypad->clk);  	error = request_irq(irq, imx_keypad_irq_handler, 0,  			    pdev->name, keypad); diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index f06231b7cab..84ec691c05a 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c @@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)  	ponkey->idev = input;  	ponkey->ab8500 = ab8500; -	ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf); -	ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr); +	ponkey->irq_dbf = irq_dbf; +	ponkey->irq_dbr = irq_dbr;  	input->name = "AB8500 POn(PowerOn) Key";  	input->dev.parent = &pdev->dev; diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 3f5649f1908..a261d857691 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -721,6 +721,17 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)  	switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {  	case FSP_PKT_TYPE_ABS: + +		if ((packet[0] == 0x48 || packet[0] == 0x49) && +		    packet[1] == 0 && packet[2] == 0) { +			/* +			 * Ignore coordinate noise when finger leaving the +			 * surface, otherwise cursor may jump to upper-left +			 * corner. +			 */ +			packet[3] &= 0xf0; +		} +  		abs_x = GET_ABS_X(packet);  		abs_y = GET_ABS_Y(packet); diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 2ffd110bd5b..2e77246c2e5 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -72,7 +72,7 @@ static int amba_kmi_open(struct serio *io)  	unsigned int divisor;  	int ret; -	ret = clk_enable(kmi->clk); +	ret = clk_prepare_enable(kmi->clk);  	if (ret)  		goto out; @@ -92,7 +92,7 @@ static int amba_kmi_open(struct serio *io)  	return 0;   clk_disable: -	clk_disable(kmi->clk); +	clk_disable_unprepare(kmi->clk);   out:  	return ret;  } @@ -104,7 +104,7 @@ static void amba_kmi_close(struct serio *io)  	writeb(0, KMICR);  	free_irq(kmi->irq, kmi); -	clk_disable(kmi->clk); +	clk_disable_unprepare(kmi->clk);  }  static int __devinit amba_kmi_probe(struct amba_device *dev, diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 6918773ce02..d6cc77a53c7 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -335,6 +335,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {  	},  	{  		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), +			DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"), +		}, +	}, +	{ +		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),  			DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),  		}, diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index b06a5e3a665..64957770b52 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -566,9 +566,12 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,  	}  	read = min_t(size_t, count, tsdata->raw_bufsize - *off); -	error = copy_to_user(buf, tsdata->raw_buffer + *off, read); -	if (!error) -		*off += read; +	if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) { +		error = -EFAULT; +		goto out; +	} + +	*off += read;  out:  	mutex_unlock(&tsdata->mutex);  	return error ?: read; diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index e32709e0dd6..721fdb3597c 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -304,6 +304,45 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt)  #define EGALAX_PKT_TYPE_REPT		0x80  #define EGALAX_PKT_TYPE_DIAG		0x0A +static int egalax_init(struct usbtouch_usb *usbtouch) +{ +	int ret, i; +	unsigned char *buf; +	struct usb_device *udev = interface_to_usbdev(usbtouch->interface); + +	/* +	 * An eGalax diagnostic packet kicks the device into using the right +	 * protocol.  We send a "check active" packet.  The response will be +	 * read later and ignored. +	 */ + +	buf = kmalloc(3, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	buf[0] = EGALAX_PKT_TYPE_DIAG; +	buf[1] = 1;	/* length */ +	buf[2] = 'A';	/* command - check active */ + +	for (i = 0; i < 3; i++) { +		ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), +				      0, +				      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +				      0, 0, buf, 3, +				      USB_CTRL_SET_TIMEOUT); +		if (ret >= 0) { +			ret = 0; +			break; +		} +		if (ret != -EPIPE) +			break; +	} + +	kfree(buf); + +	return ret; +} +  static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)  {  	if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) @@ -1056,6 +1095,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {  		.process_pkt	= usbtouch_process_multi,  		.get_pkt_len	= egalax_get_pkt_len,  		.read_data	= egalax_read_data, +		.init		= egalax_init,  	},  #endif diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index fa6ca473372..dceaec821b0 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)  	switch (cmd) {  	case CLOSE_CHANNEL:  		test_and_clear_bit(FLG_OPEN, &bch->Flags); +		cancel_work_sync(&bch->workq);  		spin_lock_irqsave(&fc->lock, flags); -		mISDN_freebchannel(bch); +		mISDN_clear_bchannel(bch);  		modehdlc(bch, ISDN_P_NONE);  		spin_unlock_irqrestore(&fc->lock, flags);  		ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 5e402cf2e79..f02794203bb 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -5059,6 +5059,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,  				printk(KERN_INFO  				       "HFC-E1 #%d has overlapping B-channels on fragment #%d\n",  				       E1_cnt + 1, pt); +				kfree(hc);  				return -EINVAL;  			}  			maskcheck |= hc->bmask[pt]; @@ -5086,6 +5087,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,  	if ((poll >> 1) > sizeof(hc->silence_data)) {  		printk(KERN_ERR "HFCMULTI error: silence_data too small, "  		       "please fix\n"); +		kfree(hc);  		return -EINVAL;  	}  	for (i = 0; i < (poll >> 1); i++) diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 752e0825591..ccd7d851be2 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)  	switch (cmd) {  	case CLOSE_CHANNEL:  		test_and_clear_bit(FLG_OPEN, &bch->Flags); +		cancel_work_sync(&bch->workq);  		spin_lock_irqsave(hx->ip->hwlock, flags); -		mISDN_freebchannel(bch); +		mISDN_clear_bchannel(bch);  		hscx_mode(hx, ISDN_P_NONE);  		spin_unlock_irqrestore(hx->ip->hwlock, flags);  		ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index be5973ded6d..182ecf0626c 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)  	switch (cmd) {  	case CLOSE_CHANNEL:  		test_and_clear_bit(FLG_OPEN, &bch->Flags); +		cancel_work_sync(&bch->workq);  		spin_lock_irqsave(ich->is->hwlock, flags); -		mISDN_freebchannel(bch); +		mISDN_clear_bchannel(bch);  		modeisar(ich, ISDN_P_NONE);  		spin_unlock_irqrestore(ich->is->hwlock, flags);  		ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index c3e3e768627..9bcade59eb7 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)  	switch (cmd) {  	case CLOSE_CHANNEL:  		test_and_clear_bit(FLG_OPEN, &bch->Flags); +		cancel_work_sync(&bch->workq);  		spin_lock_irqsave(&card->lock, flags); -		mISDN_freebchannel(bch); +		mISDN_clear_bchannel(bch);  		mode_tiger(bc, ISDN_P_NONE);  		spin_unlock_irqrestore(&card->lock, flags);  		ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 26a86b84609..335fe645500 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)  	switch (cmd) {  	case CLOSE_CHANNEL:  		test_and_clear_bit(FLG_OPEN, &bch->Flags); +		cancel_work_sync(&bch->workq);  		spin_lock_irqsave(&card->lock, flags); -		mISDN_freebchannel(bch); +		mISDN_clear_bchannel(bch);  		w6692_mode(bc, ISDN_P_NONE);  		spin_unlock_irqrestore(&card->lock, flags);  		ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index ef34fd40867..2602be23f34 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c @@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch)  	ch->next_minlen = ch->init_minlen;  	ch->maxlen = ch->init_maxlen;  	ch->next_maxlen = ch->init_maxlen; +	skb_queue_purge(&ch->rqueue); +	ch->rcount = 0;  }  EXPORT_SYMBOL(mISDN_clear_bchannel); -int +void  mISDN_freebchannel(struct bchannel *ch)  { +	cancel_work_sync(&ch->workq);  	mISDN_clear_bchannel(ch); -	skb_queue_purge(&ch->rqueue); -	ch->rcount = 0; -	flush_work_sync(&ch->workq); -	return 0;  }  EXPORT_SYMBOL(mISDN_freebchannel); diff --git a/drivers/md/md.c b/drivers/md/md.c index 3f6203a4c7e..308e87b417e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7619,6 +7619,8 @@ static int remove_and_add_spares(struct mddev *mddev)  			}  		}  	} +	if (removed) +		set_bit(MD_CHANGE_DEVS, &mddev->flags);  	return spares;  } @@ -7632,9 +7634,11 @@ static void reap_sync_thread(struct mddev *mddev)  	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {  		/* success...*/  		/* activate any spares */ -		if (mddev->pers->spare_active(mddev)) +		if (mddev->pers->spare_active(mddev)) {  			sysfs_notify(&mddev->kobj, NULL,  				     "degraded"); +			set_bit(MD_CHANGE_DEVS, &mddev->flags); +		}  	}  	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&  	    mddev->pers->finish_reshape) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1c2eb38f3c5..0138a727c1f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1512,14 +1512,16 @@ static int _enough(struct r10conf *conf, struct geom *geo, int ignore)  	do {  		int n = conf->copies;  		int cnt = 0; +		int this = first;  		while (n--) { -			if (conf->mirrors[first].rdev && -			    first != ignore) +			if (conf->mirrors[this].rdev && +			    this != ignore)  				cnt++; -			first = (first+1) % geo->raid_disks; +			this = (this+1) % geo->raid_disks;  		}  		if (cnt == 0)  			return 0; +		first = (first + geo->near_copies) % geo->raid_disks;  	} while (first != 0);  	return 1;  } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index adda94df5eb..0689173fd9f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -393,6 +393,8 @@ static int calc_degraded(struct r5conf *conf)  	degraded = 0;  	for (i = 0; i < conf->previous_raid_disks; i++) {  		struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); +		if (rdev && test_bit(Faulty, &rdev->flags)) +			rdev = rcu_dereference(conf->disks[i].replacement);  		if (!rdev || test_bit(Faulty, &rdev->flags))  			degraded++;  		else if (test_bit(In_sync, &rdev->flags)) @@ -417,6 +419,8 @@ static int calc_degraded(struct r5conf *conf)  	degraded2 = 0;  	for (i = 0; i < conf->raid_disks; i++) {  		struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); +		if (rdev && test_bit(Faulty, &rdev->flags)) +			rdev = rcu_dereference(conf->disks[i].replacement);  		if (!rdev || test_bit(Faulty, &rdev->flags))  			degraded2++;  		else if (test_bit(In_sync, &rdev->flags)) @@ -1587,6 +1591,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)  		#ifdef CONFIG_MULTICORE_RAID456  		init_waitqueue_head(&nsh->ops.wait_for_ops);  		#endif +		spin_lock_init(&nsh->stripe_lock);  		list_add(&nsh->lru, &newstripes);  	} @@ -4192,7 +4197,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)  			finish_wait(&conf->wait_for_overlap, &w);  			set_bit(STRIPE_HANDLE, &sh->state);  			clear_bit(STRIPE_DELAYED, &sh->state); -			if ((bi->bi_rw & REQ_NOIDLE) && +			if ((bi->bi_rw & REQ_SYNC) &&  			    !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))  				atomic_inc(&conf->preread_active_stripes);  			release_stripe_plug(mddev, sh); diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index b67a3018b13..ce229ea933d 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -470,7 +470,8 @@ static int __devinit device_800_init(struct pm80x_chip *chip,  	ret =  	    mfd_add_devices(chip->dev, 0, &onkey_devs[0], -			    ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0); +			    ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, +			    NULL);  	if (ret < 0) {  		dev_err(chip->dev, "Failed to add onkey subdev\n");  		goto out_dev; @@ -481,7 +482,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip,  		rtc_devs[0].platform_data = pdata->rtc;  		rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);  		ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], -				      ARRAY_SIZE(rtc_devs), NULL, 0); +				      ARRAY_SIZE(rtc_devs), NULL, 0, NULL);  		if (ret < 0) {  			dev_err(chip->dev, "Failed to add rtc subdev\n");  			goto out_dev; diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 6146583589f..c20a31136f0 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -216,7 +216,8 @@ static int __devinit device_805_init(struct pm80x_chip *chip)  	}  	ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], -			      ARRAY_SIZE(codec_devs), &codec_resources[0], 0); +			      ARRAY_SIZE(codec_devs), &codec_resources[0], 0, +			      NULL);  	if (ret < 0) {  		dev_err(chip->dev, "Failed to add codec subdev\n");  		goto out_codec; diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index d09918cf1b1..b73f033b2c6 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -637,7 +637,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,  			bk_devs[i].resources = &bk_resources[j];  			ret = mfd_add_devices(chip->dev, 0,  					      &bk_devs[i], 1, -					      &bk_resources[j], 0); +					      &bk_resources[j], 0, NULL);  			if (ret < 0) {  				dev_err(chip->dev, "Failed to add "  					"backlight subdev\n"); @@ -672,7 +672,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip,  			led_devs[i].resources = &led_resources[j],  			ret = mfd_add_devices(chip->dev, 0,  					      &led_devs[i], 1, -					      &led_resources[j], 0); +					      &led_resources[j], 0, NULL);  			if (ret < 0) {  				dev_err(chip->dev, "Failed to add "  					"led subdev\n"); @@ -709,7 +709,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,  		regulator_devs[i].resources = ®ulator_resources[seq];  		ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, -				      ®ulator_resources[seq], 0); +				      ®ulator_resources[seq], 0, NULL);  		if (ret < 0) {  			dev_err(chip->dev, "Failed to add regulator subdev\n");  			goto out; @@ -733,7 +733,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip,  	rtc_devs[0].resources = &rtc_resources[0];  	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],  			      ARRAY_SIZE(rtc_devs), &rtc_resources[0], -			      chip->irq_base); +			      chip->irq_base, NULL);  	if (ret < 0)  		dev_err(chip->dev, "Failed to add rtc subdev\n");  } @@ -752,7 +752,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip,  	touch_devs[0].resources = &touch_resources[0];  	ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],  			      ARRAY_SIZE(touch_devs), &touch_resources[0], -			      chip->irq_base); +			      chip->irq_base, NULL);  	if (ret < 0)  		dev_err(chip->dev, "Failed to add touch subdev\n");  } @@ -770,7 +770,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,  	power_devs[0].num_resources = ARRAY_SIZE(battery_resources);  	power_devs[0].resources = &battery_resources[0],  	ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, -			      &battery_resources[0], chip->irq_base); +			      &battery_resources[0], chip->irq_base, NULL);  	if (ret < 0)  		dev_err(chip->dev, "Failed to add battery subdev\n"); @@ -779,7 +779,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,  	power_devs[1].num_resources = ARRAY_SIZE(charger_resources);  	power_devs[1].resources = &charger_resources[0],  	ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, -			      &charger_resources[0], chip->irq_base); +			      &charger_resources[0], chip->irq_base, NULL);  	if (ret < 0)  		dev_err(chip->dev, "Failed to add charger subdev\n"); @@ -788,7 +788,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,  	power_devs[2].num_resources = ARRAY_SIZE(preg_resources);  	power_devs[2].resources = &preg_resources[0],  	ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, -			      &preg_resources[0], chip->irq_base); +			      &preg_resources[0], chip->irq_base, NULL);  	if (ret < 0)  		dev_err(chip->dev, "Failed to add preg subdev\n");  } @@ -802,7 +802,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip,  	onkey_devs[0].resources = &onkey_resources[0],  	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],  			      ARRAY_SIZE(onkey_devs), &onkey_resources[0], -			      chip->irq_base); +			      chip->irq_base, NULL);  	if (ret < 0)  		dev_err(chip->dev, "Failed to add onkey subdev\n");  } @@ -815,7 +815,8 @@ static void __devinit device_codec_init(struct pm860x_chip *chip,  	codec_devs[0].num_resources = ARRAY_SIZE(codec_resources);  	codec_devs[0].resources = &codec_resources[0],  	ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], -			      ARRAY_SIZE(codec_devs), &codec_resources[0], 0); +			      ARRAY_SIZE(codec_devs), &codec_resources[0], 0, +			      NULL);  	if (ret < 0)  		dev_err(chip->dev, "Failed to add codec subdev\n");  } diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 44a3fdbadef..f1beb4971f8 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -424,7 +424,7 @@ static int aat2870_i2c_probe(struct i2c_client *client,  	}  	ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs, -			      ARRAY_SIZE(aat2870_devs), NULL, 0); +			      ARRAY_SIZE(aat2870_devs), NULL, 0, NULL);  	if (ret != 0) {  		dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret);  		goto out_disable; diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 78fca2902c8..01781ae5d0d 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -946,7 +946,7 @@ static int __devinit ab3100_probe(struct i2c_client *client,  	}  	err = mfd_add_devices(&client->dev, 0, ab3100_devs, -		ARRAY_SIZE(ab3100_devs), NULL, 0); +			      ARRAY_SIZE(ab3100_devs), NULL, 0, NULL);  	ab3100_setup_debugfs(ab3100); diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 626b4ecaf64..47adf800024 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1418,25 +1418,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev)  	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,  			ARRAY_SIZE(abx500_common_devs), NULL, -			ab8500->irq_base); +			ab8500->irq_base, ab8500->domain);  	if (ret)  		goto out_freeirq;  	if (is_ab9540(ab8500))  		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,  				ARRAY_SIZE(ab9540_devs), NULL, -				ab8500->irq_base); +				ab8500->irq_base, ab8500->domain);  	else  		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,  				ARRAY_SIZE(ab8500_devs), NULL, -				ab8500->irq_base); +				ab8500->irq_base, ab8500->domain);  	if (ret)  		goto out_freeirq;  	if (is_ab9540(ab8500) || is_ab8505(ab8500))  		ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,  				ARRAY_SIZE(ab9540_ab8505_devs), NULL, -				ab8500->irq_base); +				ab8500->irq_base, ab8500->domain);  	if (ret)  		goto out_freeirq; @@ -1444,7 +1444,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)  		/* Add battery management devices */  		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,  				      ARRAY_SIZE(ab8500_bm_devs), NULL, -				      ab8500->irq_base); +				      ab8500->irq_base, ab8500->domain);  		if (ret)  			dev_err(ab8500->dev, "error adding bm devices\n");  	} diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index c7983e86254..1b48f209480 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -316,7 +316,7 @@ int __devinit arizona_dev_init(struct arizona *arizona)  	}  	ret = mfd_add_devices(arizona->dev, -1, early_devs, -			      ARRAY_SIZE(early_devs), NULL, 0); +			      ARRAY_SIZE(early_devs), NULL, 0, NULL);  	if (ret != 0) {  		dev_err(dev, "Failed to add early children: %d\n", ret);  		return ret; @@ -516,11 +516,11 @@ int __devinit arizona_dev_init(struct arizona *arizona)  	switch (arizona->type) {  	case WM5102:  		ret = mfd_add_devices(arizona->dev, -1, wm5102_devs, -				      ARRAY_SIZE(wm5102_devs), NULL, 0); +				      ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);  		break;  	case WM5110:  		ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, -				      ARRAY_SIZE(wm5102_devs), NULL, 0); +				      ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);  		break;  	} diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 683e18a2332..62f0883a763 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -913,14 +913,14 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,  	if (pdata->clock_rate) {  		ds1wm_pdata.clock_rate = pdata->clock_rate;  		ret = mfd_add_devices(&pdev->dev, pdev->id, -			&asic3_cell_ds1wm, 1, mem, asic->irq_base); +			&asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL);  		if (ret < 0)  			goto out;  	}  	if (mem_sdio && (irq >= 0)) {  		ret = mfd_add_devices(&pdev->dev, pdev->id, -			&asic3_cell_mmc, 1, mem_sdio, irq); +			&asic3_cell_mmc, 1, mem_sdio, irq, NULL);  		if (ret < 0)  			goto out;  	} @@ -934,7 +934,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,  			asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]);  		}  		ret = mfd_add_devices(&pdev->dev, 0, -			asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0); +			asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL);  	}   out: diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index 3419e726de4..2b282133c72 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c @@ -149,7 +149,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,  	}  	err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, -			ARRAY_SIZE(cs5535_mfd_cells), NULL, 0); +			      ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL);  	if (err) {  		dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);  		goto err_disable; diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 2544910e1fd..a0a62b24621 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -803,7 +803,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)  		dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret);  	ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, -			      ARRAY_SIZE(da9052_subdev_info), NULL, 0); +			      ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL);  	if (ret)  		goto err; diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 4e2af2cb2d2..45e83a68641 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -129,7 +129,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev)  	cell->pdata_size = sizeof(*davinci_vc);  	ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, -			      DAVINCI_VC_CELLS, NULL, 0); +			      DAVINCI_VC_CELLS, NULL, 0, NULL);  	if (ret != 0) {  		dev_err(&pdev->dev, "fail to register client devices\n");  		goto fail4; diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 7040a008113..0e63cdd9b52 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3010,7 +3010,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)  		prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);  	err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, -			ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); +			      ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL);  	if (err) {  		pr_err("prcmu: Failed to add subdevices\n");  		return err; diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 04c7093d649..9e5453d21a6 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -168,7 +168,7 @@ static int __init pasic3_probe(struct platform_device *pdev)  		/* the first 5 PASIC3 registers control the DS1WM */  		ds1wm_resources[0].end = (5 << asic->bus_shift) - 1;  		ret = mfd_add_devices(&pdev->dev, pdev->id, -				&ds1wm_cell, 1, r, irq); +				      &ds1wm_cell, 1, r, irq, NULL);  		if (ret < 0)  			dev_warn(dev, "failed to register DS1WM\n");  	} @@ -176,7 +176,8 @@ static int __init pasic3_probe(struct platform_device *pdev)  	if (pdata && pdata->led_pdata) {  		led_cell.platform_data = pdata->led_pdata;  		led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); -		ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); +		ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, +				      0, NULL);  		if (ret < 0)  			dev_warn(dev, "failed to register LED device\n");  	} diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index 59df5584cb5..266bdc5bd96 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -344,13 +344,13 @@ static int __devinit intel_msic_init_devices(struct intel_msic *msic)  			continue;  		ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL, -				      pdata->irq[i]); +				      pdata->irq[i], NULL);  		if (ret)  			goto fail;  	}  	ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs, -			      ARRAY_SIZE(msic_other_devs), NULL, 0); +			      ARRAY_SIZE(msic_other_devs), NULL, 0, NULL);  	if (ret)  		goto fail; diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 2ea99989551..965c4801df8 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -147,7 +147,7 @@ static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)  	}  	return mfd_add_devices(&pdev->dev, 0, priv->cells, -			       num_probed, NULL, pdev->irq); +			       num_probed, NULL, pdev->irq, NULL);  }  /* diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 87662a17dec..c6b6d7dda51 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -287,7 +287,8 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)  	writeb(0xff, adc->base + JZ_REG_ADC_CTRL);  	ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, -		ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base); +			      ARRAY_SIZE(jz4740_adc_cells), mem_base, +			      irq_base, NULL);  	if (ret < 0)  		goto err_clk_put; diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c index 0b2879b87fd..24212f45b20 100644 --- a/drivers/mfd/lm3533-core.c +++ b/drivers/mfd/lm3533-core.c @@ -393,7 +393,8 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)  	lm3533_als_devs[0].platform_data = pdata->als;  	lm3533_als_devs[0].pdata_size = sizeof(*pdata->als); -	ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0); +	ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, +			      0, NULL);  	if (ret) {  		dev_err(lm3533->dev, "failed to add ALS device\n");  		return ret; @@ -422,7 +423,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)  	}  	ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs, -					pdata->num_backlights, NULL, 0); +			      pdata->num_backlights, NULL, 0, NULL);  	if (ret) {  		dev_err(lm3533->dev, "failed to add backlight devices\n");  		return ret; @@ -451,7 +452,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)  	}  	ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs, -						pdata->num_leds, NULL, 0); +			      pdata->num_leds, NULL, 0, NULL);  	if (ret) {  		dev_err(lm3533->dev, "failed to add LED devices\n");  		return ret; diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 027cc8f8613..092ad4b44b6 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -750,7 +750,7 @@ gpe0_done:  	lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);  	ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], -				1, NULL, 0); +			      1, NULL, 0, NULL);  gpio_done:  	if (acpi_conflict) @@ -765,7 +765,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,  	u32 base_addr_cfg;  	u32 base_addr;  	int ret; -	bool acpi_conflict = false;  	struct resource *res;  	/* Setup power management base register */ @@ -780,20 +779,11 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,  	res = wdt_io_res(ICH_RES_IO_TCO);  	res->start = base_addr + ACPIBASE_TCO_OFF;  	res->end = base_addr + ACPIBASE_TCO_END; -	ret = acpi_check_resource_conflict(res); -	if (ret) { -		acpi_conflict = true; -		goto wdt_done; -	}  	res = wdt_io_res(ICH_RES_IO_SMI);  	res->start = base_addr + ACPIBASE_SMI_OFF;  	res->end = base_addr + ACPIBASE_SMI_END; -	ret = acpi_check_resource_conflict(res); -	if (ret) { -		acpi_conflict = true; -		goto wdt_done; -	} +  	lpc_ich_enable_acpi_space(dev);  	/* @@ -813,21 +803,13 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,  		res = wdt_mem_res(ICH_RES_MEM_GCS);  		res->start = base_addr + ACPIBASE_GCS_OFF;  		res->end = base_addr + ACPIBASE_GCS_END; -		ret = acpi_check_resource_conflict(res); -		if (ret) { -			acpi_conflict = true; -			goto wdt_done; -		}  	}  	lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id);  	ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], -				1, NULL, 0); +			      1, NULL, 0, NULL);  wdt_done: -	if (acpi_conflict) -		pr_warn("Resource conflict(s) found affecting %s\n", -				lpc_ich_cells[LPC_WDT].name);  	return ret;  } diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index 9f20abc5e39..f6b9c5c96b2 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c @@ -127,7 +127,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,  		lpc_sch_cells[i].id = id->device;  	ret = mfd_add_devices(&dev->dev, 0, -			lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); +			      lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, +			      0, NULL);  	if (ret)  		goto out_dev; @@ -153,7 +154,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,  			tunnelcreek_cells[i].id = id->device;  		ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, -			ARRAY_SIZE(tunnelcreek_cells), NULL, 0); +				      ARRAY_SIZE(tunnelcreek_cells), NULL, +				      0, NULL);  	}  	return ret; diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index c03e12b5192..d9e24c849a0 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -126,7 +126,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,  	max77686_irq_init(max77686);  	ret = mfd_add_devices(max77686->dev, -1, max77686_devs, -			      ARRAY_SIZE(max77686_devs), NULL, 0); +			      ARRAY_SIZE(max77686_devs), NULL, 0, NULL);  	if (ret < 0)  		goto err_mfd; diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c index 2b403569e0a..1029d018c73 100644 --- a/drivers/mfd/max77693-irq.c +++ b/drivers/mfd/max77693-irq.c @@ -137,6 +137,9 @@ static void max77693_irq_mask(struct irq_data *data)  	const struct max77693_irq_data *irq_data =  				irq_to_max77693_irq(max77693, data->irq); +	if (irq_data->group >= MAX77693_IRQ_GROUP_NR) +		return; +  	if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)  		max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;  	else @@ -149,6 +152,9 @@ static void max77693_irq_unmask(struct irq_data *data)  	const struct max77693_irq_data *irq_data =  	    irq_to_max77693_irq(max77693, data->irq); +	if (irq_data->group >= MAX77693_IRQ_GROUP_NR) +		return; +  	if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)  		max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;  	else @@ -200,7 +206,7 @@ static irqreturn_t max77693_irq_thread(int irq, void *data)  	if (irq_src & MAX77693_IRQSRC_MUIC)  		/* MUIC INT1 ~ INT3 */ -		max77693_bulk_read(max77693->regmap, MAX77693_MUIC_REG_INT1, +		max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1,  			MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]);  	/* Apply masking */ @@ -255,7 +261,8 @@ int max77693_irq_init(struct max77693_dev *max77693)  {  	struct irq_domain *domain;  	int i; -	int ret; +	int ret = 0; +	u8 intsrc_mask;  	mutex_init(&max77693->irqlock); @@ -287,19 +294,38 @@ int max77693_irq_init(struct max77693_dev *max77693)  					&max77693_irq_domain_ops, max77693);  	if (!domain) {  		dev_err(max77693->dev, "could not create irq domain\n"); -		return -ENODEV; +		ret = -ENODEV; +		goto err_irq;  	}  	max77693->irq_domain = domain; +	/* Unmask max77693 interrupt */ +	ret = max77693_read_reg(max77693->regmap, +			MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask); +	if (ret < 0) { +		dev_err(max77693->dev, "fail to read PMIC register\n"); +		goto err_irq; +	} + +	intsrc_mask &= ~(MAX77693_IRQSRC_CHG); +	intsrc_mask &= ~(MAX77693_IRQSRC_FLASH); +	intsrc_mask &= ~(MAX77693_IRQSRC_MUIC); +	ret = max77693_write_reg(max77693->regmap, +			MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask); +	if (ret < 0) { +		dev_err(max77693->dev, "fail to write PMIC register\n"); +		goto err_irq; +	} +  	ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread,  				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,  				   "max77693-irq", max77693); -  	if (ret)  		dev_err(max77693->dev, "Failed to request IRQ %d: %d\n",  			max77693->irq, ret); -	return 0; +err_irq: +	return ret;  }  void max77693_irq_exit(struct max77693_dev *max77693) diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index a1811cb50ec..cc5155e2049 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -152,6 +152,20 @@ static int max77693_i2c_probe(struct i2c_client *i2c,  	max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);  	i2c_set_clientdata(max77693->haptic, max77693); +	/* +	 * Initialize register map for MUIC device because use regmap-muic +	 * instance of MUIC device when irq of max77693 is initialized +	 * before call max77693-muic probe() function. +	 */ +	max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic, +					 &max77693_regmap_config); +	if (IS_ERR(max77693->regmap_muic)) { +		ret = PTR_ERR(max77693->regmap_muic); +		dev_err(max77693->dev, +			"failed to allocate register map: %d\n", ret); +		goto err_regmap; +	} +  	ret = max77693_irq_init(max77693);  	if (ret < 0)  		goto err_irq; @@ -159,7 +173,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,  	pm_runtime_set_active(max77693->dev);  	ret = mfd_add_devices(max77693->dev, -1, max77693_devs, -			ARRAY_SIZE(max77693_devs), NULL, 0); +			      ARRAY_SIZE(max77693_devs), NULL, 0, NULL);  	if (ret < 0)  		goto err_mfd; diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 825a7f06d9b..ee53757beca 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,  	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],  			      ARRAY_SIZE(rtc_devs), -			      &rtc_resources[0], chip->irq_base); +			      &rtc_resources[0], chip->irq_base, NULL);  	if (ret < 0) {  		dev_err(chip->dev, "Failed to add rtc subdev\n");  		goto out; @@ -606,7 +606,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,  	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],  			      ARRAY_SIZE(onkey_devs), -			      &onkey_resources[0], 0); +			      &onkey_resources[0], 0, NULL);  	if (ret < 0) {  		dev_err(chip->dev, "Failed to add onkey subdev\n");  		goto out_dev; @@ -615,7 +615,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,  	if (pdata) {  		ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0],  				      ARRAY_SIZE(regulator_devs), -				      ®ulator_resources[0], 0); +				      ®ulator_resources[0], 0, NULL);  		if (ret < 0) {  			dev_err(chip->dev, "Failed to add regulator subdev\n");  			goto out_dev; @@ -625,7 +625,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,  	if (pdata && pdata->backlight) {  		ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],  				      ARRAY_SIZE(backlight_devs), -				      &backlight_resources[0], 0); +				      &backlight_resources[0], 0, NULL);  		if (ret < 0) {  			dev_err(chip->dev, "Failed to add backlight subdev\n");  			goto out_dev; @@ -635,7 +635,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,  	if (pdata && pdata->power) {  		ret = mfd_add_devices(chip->dev, 0, &power_devs[0],  					ARRAY_SIZE(power_devs), -					&power_supply_resources[0], 0); +				      &power_supply_resources[0], 0, NULL);  		if (ret < 0) {  			dev_err(chip->dev, "Failed to add power supply "  				"subdev\n"); @@ -646,7 +646,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,  	if (pdata && pdata->touch) {  		ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],  				      ARRAY_SIZE(touch_devs), -				      &touch_resources[0], 0); +				      &touch_resources[0], 0, NULL);  		if (ret < 0) {  			dev_err(chip->dev, "Failed to add touch subdev\n");  			goto out_dev; diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 10b629c245b..f123517065e 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -160,7 +160,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,  	mfd_add_devices(max8997->dev, -1, max8997_devs,  			ARRAY_SIZE(max8997_devs), -			NULL, 0); +			NULL, 0, NULL);  	/*  	 * TODO: enable others (flash, muic, rtc, battery, ...) and diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 6ef56d28c05..d7218cc9094 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -161,13 +161,13 @@ static int max8998_i2c_probe(struct i2c_client *i2c,  	switch (id->driver_data) {  	case TYPE_LP3974:  		ret = mfd_add_devices(max8998->dev, -1, -				lp3974_devs, ARRAY_SIZE(lp3974_devs), -				NULL, 0); +				      lp3974_devs, ARRAY_SIZE(lp3974_devs), +				      NULL, 0, NULL);  		break;  	case TYPE_MAX8998:  		ret = mfd_add_devices(max8998->dev, -1, -				max8998_devs, ARRAY_SIZE(max8998_devs), -				NULL, 0); +				      max8998_devs, ARRAY_SIZE(max8998_devs), +				      NULL, 0, NULL);  		break;  	default:  		ret = -EINVAL; diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index b801dc72f04..1ec79b54bd2 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -612,7 +612,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,  	if (!cell.name)  		return -ENOMEM; -	return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0); +	return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL);  }  static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 0c3a01cde2f..f8b77711ad2 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -74,12 +74,11 @@ static int mfd_platform_add_cell(struct platform_device *pdev,  static int mfd_add_device(struct device *parent, int id,  			  const struct mfd_cell *cell,  			  struct resource *mem_base, -			  int irq_base) +			  int irq_base, struct irq_domain *domain)  {  	struct resource *res;  	struct platform_device *pdev;  	struct device_node *np = NULL; -	struct irq_domain *domain = NULL;  	int ret = -ENOMEM;  	int r; @@ -97,7 +96,6 @@ static int mfd_add_device(struct device *parent, int id,  		for_each_child_of_node(parent->of_node, np) {  			if (of_device_is_compatible(np, cell->of_compatible)) {  				pdev->dev.of_node = np; -				domain = irq_find_host(parent->of_node);  				break;  			}  		} @@ -177,7 +175,7 @@ fail_alloc:  int mfd_add_devices(struct device *parent, int id,  		    struct mfd_cell *cells, int n_devs,  		    struct resource *mem_base, -		    int irq_base) +		    int irq_base, struct irq_domain *domain)  {  	int i;  	int ret = 0; @@ -191,7 +189,8 @@ int mfd_add_devices(struct device *parent, int id,  	for (i = 0; i < n_devs; i++) {  		atomic_set(&cnts[i], 0);  		cells[i].usage_count = &cnts[i]; -		ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); +		ret = mfd_add_device(parent, id, cells + i, mem_base, +				     irq_base, domain);  		if (ret)  			break;  	} @@ -247,7 +246,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)  	for (i = 0; i < n_clones; i++) {  		cell_entry.name = clones[i];  		/* don't give up if a single call fails; just report error */ -		if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0)) +		if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0, +				   NULL))  			dev_err(dev, "failed to create platform device '%s'\n",  					clones[i]);  	} diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index c4a69f193a1..a345f9bb7b4 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -453,7 +453,8 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,  	ret = mfd_add_devices(palmas->dev, -1,  			      children, ARRAY_SIZE(palmas_children), -			      NULL, regmap_irq_chip_get_base(palmas->irq_data)); +			      NULL, regmap_irq_chip_get_base(palmas->irq_data), +			      NULL);  	kfree(children);  	if (ret < 0) diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c index cdc1df7fa0e..3a8fa88567b 100644 --- a/drivers/mfd/rc5t583.c +++ b/drivers/mfd/rc5t583.c @@ -289,7 +289,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,  	}  	ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, -			ARRAY_SIZE(rc5t583_subdevs), NULL, 0); +			      ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);  	if (ret) {  		dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);  		goto err_add_devs; diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 685d61e431a..0f70dce6116 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c @@ -87,7 +87,8 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,  	rdc321x_wdt_pdata.sb_pdev = pdev;  	return mfd_add_devices(&pdev->dev, -1, -		rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0); +			       rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), +			       NULL, 0, NULL);  }  static void __devexit rdc321x_sb_remove(struct pci_dev *pdev) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 2988efde11e..49d361a618d 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -141,19 +141,19 @@ static int sec_pmic_probe(struct i2c_client *i2c,  	switch (sec_pmic->device_type) {  	case S5M8751X:  		ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, -					ARRAY_SIZE(s5m8751_devs), NULL, 0); +				      ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL);  		break;  	case S5M8763X:  		ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, -					ARRAY_SIZE(s5m8763_devs), NULL, 0); +				      ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL);  		break;  	case S5M8767X:  		ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, -					ARRAY_SIZE(s5m8767_devs), NULL, 0); +				      ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);  		break;  	case S2MPS11X:  		ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, -					ARRAY_SIZE(s2mps11_devs), NULL, 0); +				      ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);  		break;  	default:  		/* If this happens the probe function is problem */ diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c index d31fed07aef..d35da6820be 100644 --- a/drivers/mfd/sta2x11-mfd.c +++ b/drivers/mfd/sta2x11-mfd.c @@ -407,7 +407,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,  			      sta2x11_mfd_bar0,  			      ARRAY_SIZE(sta2x11_mfd_bar0),  			      &pdev->resource[0], -			      0); +			      0, NULL);  	if (err) {  		dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err);  		goto err_disable; @@ -417,7 +417,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,  			      sta2x11_mfd_bar1,  			      ARRAY_SIZE(sta2x11_mfd_bar1),  			      &pdev->resource[1], -			      0); +			      0, NULL);  	if (err) {  		dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err);  		goto err_disable; diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 2dd8d49cb30..c94f521f392 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -962,7 +962,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe,  				      struct mfd_cell *cell, int irq)  {  	return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, -			       NULL, stmpe->irq_base + irq); +			       NULL, stmpe->irq_base + irq, NULL);  }  static int __devinit stmpe_devices_init(struct stmpe *stmpe) diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 2d9e8799e73..b32940ec903 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -388,7 +388,7 @@ static int t7l66xb_probe(struct platform_device *dev)  	ret = mfd_add_devices(&dev->dev, dev->id,  			      t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), -			      iomem, t7l66xb->irq_base); +			      iomem, t7l66xb->irq_base, NULL);  	if (!ret)  		return 0; diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 048bf0532a0..b56ba6b4329 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -262,8 +262,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)  	if (blocks & TC3589x_BLOCK_GPIO) {  		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, -				ARRAY_SIZE(tc3589x_dev_gpio), NULL, -				tc3589x->irq_base); +				      ARRAY_SIZE(tc3589x_dev_gpio), NULL, +				      tc3589x->irq_base, NULL);  		if (ret) {  			dev_err(tc3589x->dev, "failed to add gpio child\n");  			return ret; @@ -273,8 +273,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)  	if (blocks & TC3589x_BLOCK_KEYPAD) {  		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, -				ARRAY_SIZE(tc3589x_dev_keypad), NULL, -				tc3589x->irq_base); +				      ARRAY_SIZE(tc3589x_dev_keypad), NULL, +				      tc3589x->irq_base, NULL);  		if (ret) {  			dev_err(tc3589x->dev, "failed to keypad child\n");  			return ret; diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index d20a284ad4b..413c891102f 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -192,7 +192,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)  	printk(KERN_INFO "Toshiba tc6387xb initialised\n");  	ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, -			      ARRAY_SIZE(tc6387xb_cells), iomem, irq); +			      ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);  	if (!ret)  		return 0; diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 9612264f0e6..dcab026fcbb 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -700,8 +700,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)  	tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data);  	ret = mfd_add_devices(&dev->dev, dev->id, -			tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), -			iomem, tcpd->irq_base); +			      tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), +			      iomem, tcpd->irq_base, NULL);  	if (!ret)  		return 0; diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c index 4fb0e6c8e8f..7c3675a74f9 100644 --- a/drivers/mfd/ti-ssp.c +++ b/drivers/mfd/ti-ssp.c @@ -412,7 +412,7 @@ static int __devinit ti_ssp_probe(struct platform_device *pdev)  		cells[id].data_size	= data->pdata_size;  	} -	error = mfd_add_devices(dev, 0, cells, 2, NULL, 0); +	error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);  	if (error < 0) {  		dev_err(dev, "cannot add mfd cells\n");  		goto error_enable; diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index a447f4ec11f..cccc626c83c 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -757,25 +757,25 @@ static int __devinit timb_probe(struct pci_dev *dev,  		err = mfd_add_devices(&dev->dev, -1,  			timberdale_cells_bar0_cfg0,  			ARRAY_SIZE(timberdale_cells_bar0_cfg0), -			&dev->resource[0], msix_entries[0].vector); +			&dev->resource[0], msix_entries[0].vector, NULL);  		break;  	case TIMB_HW_VER1:  		err = mfd_add_devices(&dev->dev, -1,  			timberdale_cells_bar0_cfg1,  			ARRAY_SIZE(timberdale_cells_bar0_cfg1), -			&dev->resource[0], msix_entries[0].vector); +			&dev->resource[0], msix_entries[0].vector, NULL);  		break;  	case TIMB_HW_VER2:  		err = mfd_add_devices(&dev->dev, -1,  			timberdale_cells_bar0_cfg2,  			ARRAY_SIZE(timberdale_cells_bar0_cfg2), -			&dev->resource[0], msix_entries[0].vector); +			&dev->resource[0], msix_entries[0].vector, NULL);  		break;  	case TIMB_HW_VER3:  		err = mfd_add_devices(&dev->dev, -1,  			timberdale_cells_bar0_cfg3,  			ARRAY_SIZE(timberdale_cells_bar0_cfg3), -			&dev->resource[0], msix_entries[0].vector); +			&dev->resource[0], msix_entries[0].vector, NULL);  		break;  	default:  		dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n", @@ -792,7 +792,7 @@ static int __devinit timb_probe(struct pci_dev *dev,  	err = mfd_add_devices(&dev->dev, 0,  		timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1), -		&dev->resource[1], msix_entries[0].vector); +		&dev->resource[1], msix_entries[0].vector, NULL);  	if (err) {  		dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);  		goto err_mfd2; @@ -803,7 +803,7 @@ static int __devinit timb_probe(struct pci_dev *dev,  		((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) {  		err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2,  			ARRAY_SIZE(timberdale_cells_bar2), -			&dev->resource[2], msix_entries[0].vector); +			&dev->resource[2], msix_entries[0].vector, NULL);  		if (err) {  			dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);  			goto err_mfd2; diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index a293b978e27..14051bdc714 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -188,7 +188,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client,  	}  	ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, -		ARRAY_SIZE(tps6105x_cells), NULL, 0); +			      ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);  	if (ret)  		goto fail; diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 33ba7723c96..1b203499c74 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -100,7 +100,7 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c,  	ret = mfd_add_devices(tps6507x->dev, -1,  			      tps6507x_devs, ARRAY_SIZE(tps6507x_devs), -			      NULL, 0); +			      NULL, 0, NULL);  	if (ret < 0)  		goto err; diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index 80e24f4b47b..50fd87c87a1 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -292,7 +292,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,  	}  	ret = mfd_add_devices(tps65090->dev, -1, tps65090s, -		ARRAY_SIZE(tps65090s), NULL, 0); +			      ARRAY_SIZE(tps65090s), NULL, 0, NULL);  	if (ret) {  		dev_err(&client->dev, "add mfd devices failed with err: %d\n",  			ret); diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 61c097a98f5..a95e9421b73 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -24,11 +24,18 @@  #include <linux/slab.h>  #include <linux/regmap.h>  #include <linux/err.h> -#include <linux/regulator/of_regulator.h> +#include <linux/of.h> +#include <linux/of_device.h>  #include <linux/mfd/core.h>  #include <linux/mfd/tps65217.h> +static struct mfd_cell tps65217s[] = { +	{ +		.name = "tps65217-pmic", +	}, +}; +  /**   * tps65217_reg_read: Read a single tps65217 register.   * @@ -133,83 +140,48 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,  }  EXPORT_SYMBOL_GPL(tps65217_clear_bits); -#ifdef CONFIG_OF -static struct of_regulator_match reg_matches[] = { -	{ .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, -	{ .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, -	{ .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, -	{ .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, -	{ .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, -	{ .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, -	{ .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, -}; - -static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) -{ -	struct device_node *node = client->dev.of_node; -	struct tps65217_board *pdata; -	struct device_node *regs; -	int count = ARRAY_SIZE(reg_matches); -	int ret, i; - -	regs = of_find_node_by_name(node, "regulators"); -	if (!regs) -		return NULL; - -	ret = of_regulator_match(&client->dev, regs, reg_matches, count); -	of_node_put(regs); -	if ((ret < 0) || (ret > count)) -		return NULL; - -	count = ret; -	pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL); -	if (!pdata) -		return NULL; - -	for (i = 0; i < count; i++) { -		if (!reg_matches[i].init_data || !reg_matches[i].of_node) -			continue; - -		pdata->tps65217_init_data[i] = reg_matches[i].init_data; -		pdata->of_node[i] = reg_matches[i].of_node; -	} - -	return pdata; -} - -static struct of_device_id tps65217_of_match[] = { -	{ .compatible = "ti,tps65217", }, -	{ }, -}; -#else -static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) -{ -	return NULL; -} -#endif -  static struct regmap_config tps65217_regmap_config = {  	.reg_bits = 8,  	.val_bits = 8,  }; +static const struct of_device_id tps65217_of_match[] = { +	{ .compatible = "ti,tps65217", .data = (void *)TPS65217 }, +	{ /* sentinel */ }, +}; +  static int __devinit tps65217_probe(struct i2c_client *client,  				const struct i2c_device_id *ids)  {  	struct tps65217 *tps; -	struct regulator_init_data *reg_data; -	struct tps65217_board *pdata = client->dev.platform_data; -	int i, ret;  	unsigned int version; +	unsigned int chip_id = ids->driver_data; +	const struct of_device_id *match; +	int ret; + +	if (client->dev.of_node) { +		match = of_match_device(tps65217_of_match, &client->dev); +		if (!match) { +			dev_err(&client->dev, +				"Failed to find matching dt id\n"); +			return -EINVAL; +		} +		chip_id = (unsigned int)match->data; +	} -	if (!pdata && client->dev.of_node) -		pdata = tps65217_parse_dt(client); +	if (!chip_id) { +		dev_err(&client->dev, "id is null.\n"); +		return -ENODEV; +	}  	tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);  	if (!tps)  		return -ENOMEM; -	tps->pdata = pdata; +	i2c_set_clientdata(client, tps); +	tps->dev = &client->dev; +	tps->id = chip_id; +  	tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config);  	if (IS_ERR(tps->regmap)) {  		ret = PTR_ERR(tps->regmap); @@ -218,8 +190,12 @@ static int __devinit tps65217_probe(struct i2c_client *client,  		return ret;  	} -	i2c_set_clientdata(client, tps); -	tps->dev = &client->dev; +	ret = mfd_add_devices(tps->dev, -1, tps65217s, +			      ARRAY_SIZE(tps65217s), NULL, 0, NULL); +	if (ret < 0) { +		dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); +		return ret; +	}  	ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);  	if (ret < 0) { @@ -232,41 +208,21 @@ static int __devinit tps65217_probe(struct i2c_client *client,  			(version & TPS65217_CHIPID_CHIP_MASK) >> 4,  			version & TPS65217_CHIPID_REV_MASK); -	for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { -		struct platform_device *pdev; - -		pdev = platform_device_alloc("tps65217-pmic", i); -		if (!pdev) { -			dev_err(tps->dev, "Cannot create regulator %d\n", i); -			continue; -		} - -		pdev->dev.parent = tps->dev; -		pdev->dev.of_node = pdata->of_node[i]; -		reg_data = pdata->tps65217_init_data[i]; -		platform_device_add_data(pdev, reg_data, sizeof(*reg_data)); -		tps->regulator_pdev[i] = pdev; - -		platform_device_add(pdev); -	} -  	return 0;  }  static int __devexit tps65217_remove(struct i2c_client *client)  {  	struct tps65217 *tps = i2c_get_clientdata(client); -	int i; -	for (i = 0; i < TPS65217_NUM_REGULATOR; i++) -		platform_device_unregister(tps->regulator_pdev[i]); +	mfd_remove_devices(tps->dev);  	return 0;  }  static const struct i2c_device_id tps65217_id_table[] = { -	{"tps65217", 0xF0}, -	{/* end of list */} +	{"tps65217", TPS65217}, +	{ /* sentinel */ }  };  MODULE_DEVICE_TABLE(i2c, tps65217_id_table); diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 353c3481212..5f58370ccf5 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -493,7 +493,8 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,  	}  	ret = mfd_add_devices(tps6586x->dev, -1, -			tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0); +			      tps6586x_cell, ARRAY_SIZE(tps6586x_cell), +			      NULL, 0, NULL);  	if (ret < 0) {  		dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);  		goto err_mfd_add; diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 1c563792c77..d3ce4d569de 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -254,7 +254,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,  	ret = mfd_add_devices(tps65910->dev, -1,  			      tps65910s, ARRAY_SIZE(tps65910s), -			      NULL, 0); +			      NULL, 0, NULL);  	if (ret < 0) {  		dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);  		return ret; diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index 74fd8cb5f37..4658b5bdcd8 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -146,7 +146,7 @@ int tps65912_device_init(struct tps65912 *tps65912)  	ret = mfd_add_devices(tps65912->dev, -1,  			      tps65912s, ARRAY_SIZE(tps65912s), -			      NULL, 0); +			      NULL, 0, NULL);  	if (ret < 0)  		goto err; diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index 838ce4eb444..77c9acb1458 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c @@ -223,7 +223,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)  	if (childs)  		ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells, -				      childs, NULL, 0); +				      childs, NULL, 0, NULL);  	else {  		dev_err(&pdev->dev, "No platform data found for childs\n");  		ret = -ENODEV; diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index b0fad0ffca5..3dca5c195a2 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -632,7 +632,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,  	}  	ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, -			      NULL, 0); +			      NULL, 0, NULL);  	if (ret)  		goto mfd_err; diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c index 872aff21e4b..b9a636d44c7 100644 --- a/drivers/mfd/vx855.c +++ b/drivers/mfd/vx855.c @@ -102,7 +102,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev,  	vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3;  	ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells), -			NULL, 0); +			NULL, 0, NULL);  	/* we always return -ENODEV here in order to enable other  	 * drivers like old, not-yet-platform_device ported i2c-viapro */ diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index f39b756df56..86e0e4309fc 100644 --- a/drivers/mfd/wl1273-core.c +++ b/drivers/mfd/wl1273-core.c @@ -241,7 +241,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,  		__func__, children);  	r = mfd_add_devices(&client->dev, -1, core->cells, -			    children, NULL, 0); +			    children, NULL, 0, NULL);  	if (r)  		goto err; diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 946698fd2dc..30173103594 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)  	case WM8310:  		ret = mfd_add_devices(wm831x->dev, wm831x_num,  				      wm8310_devs, ARRAY_SIZE(wm8310_devs), -				      NULL, 0); +				      NULL, 0, NULL);  		break;  	case WM8311:  		ret = mfd_add_devices(wm831x->dev, wm831x_num,  				      wm8311_devs, ARRAY_SIZE(wm8311_devs), -				      NULL, 0); +				      NULL, 0, NULL);  		if (!pdata || !pdata->disable_touch)  			mfd_add_devices(wm831x->dev, wm831x_num,  					touch_devs, ARRAY_SIZE(touch_devs), -					NULL, 0); +					NULL, 0, NULL);  		break;  	case WM8312:  		ret = mfd_add_devices(wm831x->dev, wm831x_num,  				      wm8312_devs, ARRAY_SIZE(wm8312_devs), -				      NULL, 0); +				      NULL, 0, NULL);  		if (!pdata || !pdata->disable_touch)  			mfd_add_devices(wm831x->dev, wm831x_num,  					touch_devs, ARRAY_SIZE(touch_devs), -					NULL, 0); +					NULL, 0, NULL);  		break;  	case WM8320: @@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)  	case WM8326:  		ret = mfd_add_devices(wm831x->dev, wm831x_num,  				      wm8320_devs, ARRAY_SIZE(wm8320_devs), -				      NULL, 0); +				      NULL, 0, NULL);  		break;  	default: @@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)  	if (ret & WM831X_XTAL_ENA) {  		ret = mfd_add_devices(wm831x->dev, wm831x_num,  				      rtc_devs, ARRAY_SIZE(rtc_devs), -				      NULL, 0); +				      NULL, 0, NULL);  		if (ret != 0) {  			dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);  			goto err_irq; @@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)  		/* Treat errors as non-critical */  		ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,  				      ARRAY_SIZE(backlight_devs), NULL, -				      0); +				      0, NULL);  		if (ret < 0)  			dev_err(wm831x->dev, "Failed to add backlight: %d\n",  				ret); diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 4b7d378551d..639ca359242 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400)  		.pdata_size = sizeof(*wm8400),  	}; -	return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); +	return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL);  }  /* diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index eec74aa55fd..2febf88cfce 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -414,7 +414,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)  	ret = mfd_add_devices(wm8994->dev, -1,  			      wm8994_regulator_devs,  			      ARRAY_SIZE(wm8994_regulator_devs), -			      NULL, 0); +			      NULL, 0, NULL);  	if (ret != 0) {  		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);  		goto err; @@ -648,7 +648,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)  	ret = mfd_add_devices(wm8994->dev, -1,  			      wm8994_devs, ARRAY_SIZE(wm8994_devs), -			      NULL, 0); +			      NULL, 0, NULL);  	if (ret != 0) {  		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);  		goto err_irq; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 98ee4381991..7edadee487b 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1391,7 +1391,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id)   */  static int ican3_reset_module(struct ican3_dev *mod)  { -	u8 val = 1 << mod->num;  	unsigned long start;  	u8 runold, runnew; @@ -1405,8 +1404,7 @@ static int ican3_reset_module(struct ican3_dev *mod)  	runold = ioread8(mod->dpm + TARGET_RUNNING);  	/* reset the module */ -	iowrite8(val, &mod->ctrl->reset_assert); -	iowrite8(val, &mod->ctrl->reset_deassert); +	iowrite8(0x00, &mod->dpmctrl->hwreset);  	/* wait until the module has finished resetting and is running */  	start = jiffies; diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index a580db29e50..26e7129332a 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -83,6 +83,11 @@  #define INSTRUCTION_LOAD_TXB(n)	(0x40 + 2 * (n))  #define INSTRUCTION_READ_RXB(n)	(((n) == 0) ? 0x90 : 0x94)  #define INSTRUCTION_RESET	0xC0 +#define RTS_TXB0		0x01 +#define RTS_TXB1		0x02 +#define RTS_TXB2		0x04 +#define INSTRUCTION_RTS(n)	(0x80 | ((n) & 0x07)) +  /* MPC251x registers */  #define CANSTAT	      0x0e @@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,  static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,  			  int tx_buf_idx)  { +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);  	u32 sid, eid, exide, rtr;  	u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,  	buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;  	memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);  	mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); -	mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); + +	/* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ +	priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); +	mcp251x_spi_trans(priv->spi, 1);  }  static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 527dbcf9533..9ded21e79db 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev)  	struct net_device *ndev = platform_get_drvdata(pdev);  	struct ti_hecc_priv *priv = netdev_priv(ndev); +	unregister_candev(ndev);  	clk_disable(priv->clk);  	clk_put(priv->clk);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	iounmap(priv->base);  	release_mem_region(res->start, resource_size(res)); -	unregister_candev(ndev);  	free_candev(ndev);  	platform_set_drvdata(pdev, NULL); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index af20c6ee2cd..e8e97a7d1d0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -662,14 +662,16 @@ void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,  				 struct bnx2x_fastpath *fp,  				 struct bnx2x_eth_q_stats *qstats)  { -	/* Do nothing if no IP/L4 csum validation was done */ - +	/* Do nothing if no L4 csum validation was done. +	 * We do not check whether IP csum was validated. For IPv4 we assume +	 * that if the card got as far as validating the L4 csum, it also +	 * validated the IP csum. IPv6 has no IP csum. +	 */  	if (cqe->fast_path_cqe.status_flags & -	    (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | -	     ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) +	    ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)  		return; -	/* If both IP/L4 validation were done, check if an error was found. */ +	/* If L4 validation was done, check if an error was found. */  	if (cqe->fast_path_cqe.type_error_flags &  	    (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 21b553229ea..dfd86a55f1d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -710,17 +710,15 @@ static inline u16 bnx2x_tx_avail(struct bnx2x *bp,  	prod = txdata->tx_bd_prod;  	cons = txdata->tx_bd_cons; -	/* NUM_TX_RINGS = number of "next-page" entries -	   It will be used as a threshold */ -	used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS; +	used = SUB_S16(prod, cons);  #ifdef BNX2X_STOP_ON_ERROR  	WARN_ON(used < 0); -	WARN_ON(used > bp->tx_ring_size); -	WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL); +	WARN_ON(used > txdata->tx_ring_size); +	WARN_ON((txdata->tx_ring_size - used) > MAX_TX_AVAIL);  #endif -	return (s16)(bp->tx_ring_size) - used; +	return (s16)(txdata->tx_ring_size) - used;  }  static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata) @@ -1088,6 +1086,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,  	txdata->txq_index = txq_index;  	txdata->tx_cons_sb = tx_cons_sb;  	txdata->parent_fp = fp; +	txdata->tx_ring_size = IS_FCOE_FP(fp) ? MAX_TX_AVAIL : bp->tx_ring_size;  	DP(NETIF_MSG_IFUP, "created tx data cid %d, txq %d\n",  	   txdata->cid, txdata->txq_index); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index 3e4cff9b1eb..b926f58e983 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -401,11 +401,11 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x70000, 8, RI_ALL_ONLINE },  	{ 0x70020, 8184, RI_ALL_OFFLINE },  	{ 0x78000, 8192, RI_E3E3B0_OFFLINE }, -	{ 0x85000, 3, RI_ALL_ONLINE }, -	{ 0x8501c, 7, RI_ALL_ONLINE }, -	{ 0x85048, 1, RI_ALL_ONLINE }, -	{ 0x85200, 32, RI_ALL_ONLINE }, -	{ 0xb0000, 16384, RI_E1H_ONLINE }, +	{ 0x85000, 3, RI_ALL_OFFLINE }, +	{ 0x8501c, 7, RI_ALL_OFFLINE }, +	{ 0x85048, 1, RI_ALL_OFFLINE }, +	{ 0x85200, 32, RI_ALL_OFFLINE }, +	{ 0xb0000, 16384, RI_E1H_OFFLINE },  	{ 0xc1000, 7, RI_ALL_ONLINE },  	{ 0xc103c, 2, RI_E2E3E3B0_ONLINE },  	{ 0xc1800, 2, RI_ALL_ONLINE }, @@ -581,17 +581,12 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x140188, 3, RI_E1E1HE2E3_ONLINE },  	{ 0x140194, 13, RI_ALL_ONLINE },  	{ 0x140200, 6, RI_E1E1HE2E3_ONLINE }, -	{ 0x140220, 4, RI_E2E3_ONLINE }, -	{ 0x140240, 4, RI_E2E3_ONLINE },  	{ 0x140260, 4, RI_E2E3_ONLINE },  	{ 0x140280, 4, RI_E2E3_ONLINE }, -	{ 0x1402a0, 4, RI_E2E3_ONLINE }, -	{ 0x1402c0, 4, RI_E2E3_ONLINE },  	{ 0x1402e0, 2, RI_E2E3_ONLINE },  	{ 0x1402e8, 2, RI_E2E3E3B0_ONLINE },  	{ 0x1402f0, 9, RI_E2E3_ONLINE },  	{ 0x140314, 44, RI_E3B0_ONLINE }, -	{ 0x1403d0, 70, RI_E3B0_ONLINE },  	{ 0x144000, 4, RI_E1E1H_ONLINE },  	{ 0x148000, 4, RI_E1E1H_ONLINE },  	{ 0x14c000, 4, RI_E1E1H_ONLINE }, @@ -704,7 +699,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x180398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x1803a0, 5, RI_E2E3E3B0_ONLINE },  	{ 0x1803b4, 2, RI_E3E3B0_ONLINE }, -	{ 0x180400, 1, RI_ALL_ONLINE },  	{ 0x180404, 255, RI_E1E1H_OFFLINE },  	{ 0x181000, 4, RI_ALL_ONLINE },  	{ 0x181010, 1020, RI_ALL_OFFLINE }, @@ -800,9 +794,9 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x1b905c, 1, RI_E3E3B0_ONLINE },  	{ 0x1b9064, 1, RI_E3B0_ONLINE },  	{ 0x1b9080, 10, RI_E3B0_ONLINE }, -	{ 0x1b9400, 14, RI_E2E3E3B0_ONLINE }, -	{ 0x1b943c, 19, RI_E2E3E3B0_ONLINE }, -	{ 0x1b9490, 10, RI_E2E3E3B0_ONLINE }, +	{ 0x1b9400, 14, RI_E2E3E3B0_OFFLINE }, +	{ 0x1b943c, 19, RI_E2E3E3B0_OFFLINE }, +	{ 0x1b9490, 10, RI_E2E3E3B0_OFFLINE },  	{ 0x1c0000, 2, RI_ALL_ONLINE },  	{ 0x200000, 65, RI_ALL_ONLINE },  	{ 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE }, @@ -814,7 +808,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x200398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2003a0, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2003a8, 2, RI_E2E3E3B0_ONLINE }, -	{ 0x200400, 1, RI_ALL_ONLINE },  	{ 0x200404, 255, RI_E1E1H_OFFLINE },  	{ 0x202000, 4, RI_ALL_ONLINE },  	{ 0x202010, 2044, RI_ALL_OFFLINE }, @@ -921,7 +914,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x280398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2803a0, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2803a8, 2, RI_E2E3E3B0_ONLINE }, -	{ 0x280400, 1, RI_ALL_ONLINE },  	{ 0x280404, 255, RI_E1E1H_OFFLINE },  	{ 0x282000, 4, RI_ALL_ONLINE },  	{ 0x282010, 2044, RI_ALL_OFFLINE }, @@ -1031,7 +1023,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x300398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x3003a0, 1, RI_E2E3E3B0_ONLINE },  	{ 0x3003a8, 2, RI_E2E3E3B0_ONLINE }, -	{ 0x300400, 1, RI_ALL_ONLINE },  	{ 0x300404, 255, RI_E1E1H_OFFLINE },  	{ 0x302000, 4, RI_ALL_ONLINE },  	{ 0x302010, 2044, RI_ALL_OFFLINE }, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c37a68d6809..ebf40cd7aa1 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -775,7 +775,7 @@ static void bnx2x_get_regs(struct net_device *dev,  	struct bnx2x *bp = netdev_priv(dev);  	struct dump_hdr dump_hdr = {0}; -	regs->version = 0; +	regs->version = 1;  	memset(p, 0, regs->len);  	if (!netif_running(bp->dev)) @@ -1587,6 +1587,12 @@ static int bnx2x_set_pauseparam(struct net_device *dev,  			bp->link_params.req_flow_ctrl[cfg_idx] =  				BNX2X_FLOW_CTRL_AUTO;  		} +		bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_NONE; +		if (epause->rx_pause) +			bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_RX; + +		if (epause->tx_pause) +			bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_TX;  	}  	DP(BNX2X_MSG_ETHTOOL, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index f4beb46c470..b046beb435b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -2667,9 +2667,11 @@ int bnx2x_update_pfc(struct link_params *params,  		return bnx2x_status;  	DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n"); -	if (CHIP_IS_E3(bp)) -		bnx2x_update_pfc_xmac(params, vars, 0); -	else { + +	if (CHIP_IS_E3(bp)) { +		if (vars->mac_type == MAC_TYPE_XMAC) +			bnx2x_update_pfc_xmac(params, vars, 0); +	} else {  		val = REG_RD(bp, MISC_REG_RESET_REG_2);  		if ((val &  		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) @@ -5432,7 +5434,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		switch (speed_mask) {  		case GP_STATUS_10M:  			vars->line_speed = SPEED_10; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_10TFD;  			else  				vars->link_status |= LINK_10THD; @@ -5440,7 +5442,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		case GP_STATUS_100M:  			vars->line_speed = SPEED_100; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_100TXFD;  			else  				vars->link_status |= LINK_100TXHD; @@ -5449,7 +5451,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		case GP_STATUS_1G:  		case GP_STATUS_1G_KX:  			vars->line_speed = SPEED_1000; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_1000TFD;  			else  				vars->link_status |= LINK_1000THD; @@ -5457,7 +5459,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		case GP_STATUS_2_5G:  			vars->line_speed = SPEED_2500; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_2500TFD;  			else  				vars->link_status |= LINK_2500THD; @@ -5531,6 +5533,7 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,  	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {  		if (SINGLE_MEDIA_DIRECT(params)) { +			vars->duplex = duplex;  			bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);  			if (phy->req_line_speed == SPEED_AUTO_NEG)  				bnx2x_xgxs_an_resolve(phy, params, vars, @@ -5625,6 +5628,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,  					LINK_STATUS_PARALLEL_DETECTION_USED;  			}  			bnx2x_ext_phy_resolve_fc(phy, params, vars); +			vars->duplex = duplex;  		}  	} diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 21054987257..0875ecfe337 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -7561,8 +7561,14 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,  	}  	rc = bnx2x_config_vlan_mac(bp, &ramrod_param); -	if (rc < 0) + +	if (rc == -EEXIST) { +		DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc); +		/* do not treat adding same MAC as error */ +		rc = 0; +	} else if (rc < 0)  		BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del")); +  	return rc;  } @@ -9825,12 +9831,13 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)  	}  #ifdef CONFIG_PCI_MSI -	/* -	 * It's expected that number of CAM entries for this functions is equal -	 * to the number evaluated based on the MSI-X table size. We want a -	 * harsh warning if these values are different! +	/* Due to new PF resource allocation by MFW T7.4 and above, it's +	 * optional that number of CAM entries will not be equal to the value +	 * advertised in PCI. +	 * Driver should use the minimal value of both as the actual status +	 * block count  	 */ -	WARN_ON(bp->igu_sb_cnt != igu_sb_cnt); +	bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt);  #endif  	if (igu_sb_cnt == 0) @@ -10294,13 +10301,11 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)  				dev_info.port_hw_config[port].  				 fcoe_wwn_node_name_lower);  	} else if (!IS_MF_SD(bp)) { -		u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg); -  		/*  		 * Read the WWN info only if the FCoE feature is enabled for  		 * this function.  		 */ -		if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) +		if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp))  			bnx2x_get_ext_wwn_info(bp, func);  	} else if (IS_MF_FCOE_SD(bp)) @@ -11073,7 +11078,14 @@ static int bnx2x_set_uc_list(struct bnx2x *bp)  	netdev_for_each_uc_addr(ha, dev) {  		rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,  				       BNX2X_UC_LIST_MAC, &ramrod_flags); -		if (rc < 0) { +		if (rc == -EEXIST) { +			DP(BNX2X_MSG_SP, +			   "Failed to schedule ADD operations: %d\n", rc); +			/* do not treat adding same MAC as error */ +			rc = 0; + +		} else if (rc < 0) { +  			BNX2X_ERR("Failed to schedule ADD operations: %d\n",  				  rc);  			return rc; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 332db64dd5b..a1d0446b39b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -101,6 +101,11 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)  	if (CHIP_REV_IS_SLOW(bp))  		return; +	/* Update MCP's statistics if possible */ +	if (bp->func_stx) +		memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, +		       sizeof(bp->func_stats)); +  	/* loader */  	if (bp->executer_idx) {  		int loader_idx = PMF_DMAE_C(bp); @@ -128,8 +133,6 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)  	} else if (bp->func_stx) {  		*stats_comp = 0; -		memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, -		       sizeof(bp->func_stats));  		bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));  	}  } @@ -1151,9 +1154,11 @@ static void bnx2x_stats_update(struct bnx2x *bp)  	if (bp->port.pmf)  		bnx2x_hw_stats_update(bp); -	if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) { -		BNX2X_ERR("storm stats were not updated for 3 times\n"); -		bnx2x_panic(); +	if (bnx2x_storm_stats_update(bp)) { +		if (bp->stats_pending++ == 3) { +			BNX2X_ERR("storm stats were not updated for 3 times\n"); +			bnx2x_panic(); +		}  		return;  	} diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index 77884191a8c..4e980a7886f 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -1086,7 +1086,7 @@ static int __init at91ether_probe(struct platform_device *pdev)  	/* Clock */  	lp->ether_clk = clk_get(&pdev->dev, "ether_clk");  	if (IS_ERR(lp->ether_clk)) { -		res = -ENODEV; +		res = PTR_ERR(lp->ether_clk);  		goto err_ioumap;  	}  	clk_enable(lp->ether_clk); diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 8971921cc1c..ab6762caa95 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -1773,6 +1773,7 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,  }  int gfar_phc_index = -1; +EXPORT_SYMBOL(gfar_phc_index);  static int gfar_get_ts_info(struct net_device *dev,  			    struct ethtool_ts_info *info) diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index c08e5d40fec..0daa66b8eca 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -515,7 +515,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)  		err = PTR_ERR(etsects->clock);  		goto no_clock;  	} -	gfar_phc_clock = ptp_clock_index(etsects->clock); +	gfar_phc_index = ptp_clock_index(etsects->clock);  	dev_set_drvdata(&dev->dev, etsects); @@ -539,7 +539,7 @@ static int gianfar_ptp_remove(struct platform_device *dev)  	gfar_write(&etsects->regs->tmr_temask, 0);  	gfar_write(&etsects->regs->tmr_ctrl,   0); -	gfar_phc_clock = -1; +	gfar_phc_index = -1;  	ptp_clock_unregister(etsects->clock);  	iounmap(etsects->regs);  	release_resource(etsects->rsrc); diff --git a/drivers/net/ethernet/i825xx/znet.c b/drivers/net/ethernet/i825xx/znet.c index bd1f1ef91e1..ba4e0cea350 100644 --- a/drivers/net/ethernet/i825xx/znet.c +++ b/drivers/net/ethernet/i825xx/znet.c @@ -139,8 +139,11 @@ struct znet_private {  /* Only one can be built-in;-> */  static struct net_device *znet_dev; +#define NETIDBLK_MAGIC		"NETIDBLK" +#define NETIDBLK_MAGIC_SIZE	8 +  struct netidblk { -	char magic[8];		/* The magic number (string) "NETIDBLK" */ +	char magic[NETIDBLK_MAGIC_SIZE];	/* The magic number (string) "NETIDBLK" */  	unsigned char netid[8]; /* The physical station address */  	char nettype, globalopt;  	char vendor[8];		/* The machine vendor and product name. */ @@ -373,14 +376,16 @@ static int __init znet_probe (void)  	struct znet_private *znet;  	struct net_device *dev;  	char *p; +	char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE);  	int err = -ENOMEM;  	/* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ -	for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++) -		if (*p == 'N'  &&  strncmp(p, "NETIDBLK", 8) == 0) +	for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++) +		if (*p == 'N' && +		    strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0)  			break; -	if (p >= (char *)phys_to_virt(0x100000)) { +	if (p > plast) {  		if (znet_debug > 1)  			printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");  		return -ENODEV; diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 9010cea68bc..b68d28a130e 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)  	}  	if (adapter->rx_queue.queue_addr != NULL) { -		if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { -			dma_unmap_single(dev, -					adapter->rx_queue.queue_dma, -					adapter->rx_queue.queue_len, -					DMA_BIDIRECTIONAL); -			adapter->rx_queue.queue_dma = DMA_ERROR_CODE; -		} -		kfree(adapter->rx_queue.queue_addr); +		dma_free_coherent(dev, adapter->rx_queue.queue_len, +				  adapter->rx_queue.queue_addr, +				  adapter->rx_queue.queue_dma);  		adapter->rx_queue.queue_addr = NULL;  	} @@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev)  		goto err_out;  	} +	dev = &adapter->vdev->dev; +  	adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) *  						rxq_entries; -	adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, -						GFP_KERNEL); +	adapter->rx_queue.queue_addr = +	    dma_alloc_coherent(dev, adapter->rx_queue.queue_len, +			       &adapter->rx_queue.queue_dma, GFP_KERNEL);  	if (!adapter->rx_queue.queue_addr) {  		netdev_err(netdev, "unable to allocate rx queue pages\n"); @@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev)  		goto err_out;  	} -	dev = &adapter->vdev->dev; -  	adapter->buffer_list_dma = dma_map_single(dev,  			adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL);  	adapter->filter_list_dma = dma_map_single(dev,  			adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); -	adapter->rx_queue.queue_dma = dma_map_single(dev, -			adapter->rx_queue.queue_addr, -			adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL);  	if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || -	    (dma_mapping_error(dev, adapter->filter_list_dma)) || -	    (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { +	    (dma_mapping_error(dev, adapter->filter_list_dma))) {  		netdev_err(netdev, "unable to map filter or buffer list "  			   "pages\n");  		rc = -ENOMEM; diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 3bfbb8df898..bde337ee1a3 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,  		return NETDEV_TX_OK;  	} +	/* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, +	 * packets may get corrupted during padding by HW. +	 * To WA this issue, pad all small packets manually. +	 */ +	if (skb->len < ETH_ZLEN) { +		if (skb_pad(skb, ETH_ZLEN - skb->len)) +			return NETDEV_TX_OK; +		skb->len = ETH_ZLEN; +		skb_set_tail_pointer(skb, ETH_ZLEN); +	} +  	mss = skb_shinfo(skb)->gso_size;  	/* The controller does a simple calculation to  	 * make sure there is enough room in the FIFO before diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index daf41792366..31d02649be4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -227,9 +227,10 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev)  			MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);  } -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)  { -	int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); +	u32 i = (obj & (table->num_obj - 1)) / +			(MLX4_TABLE_CHUNK_SIZE / table->obj_size);  	int ret = 0;  	mutex_lock(&table->mutex); @@ -262,16 +263,18 @@ out:  	return ret;  } -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)  { -	int i; +	u32 i; +	u64 offset;  	i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);  	mutex_lock(&table->mutex);  	if (--table->icm[i]->refcount == 0) { -		mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, +		offset = (u64) i * MLX4_TABLE_CHUNK_SIZE; +		mlx4_UNMAP_ICM(dev, table->virt + offset,  			       MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);  		mlx4_free_icm(dev, table->icm[i], table->coherent);  		table->icm[i] = NULL; @@ -280,9 +283,11 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)  	mutex_unlock(&table->mutex);  } -void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle) +void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, +			dma_addr_t *dma_handle)  { -	int idx, offset, dma_offset, i; +	int offset, dma_offset, i; +	u64 idx;  	struct mlx4_icm_chunk *chunk;  	struct mlx4_icm *icm;  	struct page *page = NULL; @@ -292,7 +297,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han  	mutex_lock(&table->mutex); -	idx = (obj & (table->num_obj - 1)) * table->obj_size; +	idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size;  	icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE];  	dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE; @@ -326,10 +331,11 @@ out:  }  int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			 int start, int end) +			 u32 start, u32 end)  {  	int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; -	int i, err; +	int err; +	u32 i;  	for (i = start; i <= end; i += inc) {  		err = mlx4_table_get(dev, table, i); @@ -349,9 +355,9 @@ fail:  }  void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			  int start, int end) +			  u32 start, u32 end)  { -	int i; +	u32 i;  	for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size)  		mlx4_table_put(dev, table, i); diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h index a67744f5350..dee67fa3910 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,  				gfp_t gfp_mask, int coherent);  void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);  int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			 int start, int end); +			 u32 start, u32 end);  void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			  int start, int end); +			  u32 start, u32 end);  int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,  			u64 virt, int obj_size,	u32 nobj, int reserved,  			int use_lowmem, int use_coherent);  void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); -void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); +void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle);  static inline void mlx4_icm_first(struct mlx4_icm *icm,  				  struct mlx4_icm_iter *iter) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 827b72dfce9..2f816c6aed7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1234,13 +1234,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  				mlx4_info(dev, "non-primary physical function, skipping.\n");  			else  				mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); -			goto unmap_bf; +			return err;  		}  		err = mlx4_load_fw(dev);  		if (err) {  			mlx4_err(dev, "Failed to start FW, aborting.\n"); -			goto unmap_bf; +			return err;  		}  		mlx4_cfg.log_pg_sz_m = 1; @@ -1304,7 +1304,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  		err = mlx4_init_slave(dev);  		if (err) {  			mlx4_err(dev, "Failed to initialize slave\n"); -			goto unmap_bf; +			return err;  		}  		err = mlx4_slave_cap(dev); @@ -1324,7 +1324,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  	err = mlx4_QUERY_ADAPTER(dev, &adapter);  	if (err) {  		mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); -		goto err_close; +		goto unmap_bf;  	}  	priv->eq_table.inta_pin = adapter.inta_pin; @@ -1332,6 +1332,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  	return 0; +unmap_bf: +	unmap_bf_area(dev); +  err_close:  	mlx4_close_hca(dev); @@ -1344,8 +1347,6 @@ err_stop_fw:  		mlx4_UNMAP_FA(dev);  		mlx4_free_icm(dev, priv->fw.fw_icm, 0);  	} -unmap_bf: -	unmap_bf_area(dev);  	return err;  } @@ -1996,7 +1997,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	}  slave_start: -	if (mlx4_cmd_init(dev)) { +	err = mlx4_cmd_init(dev); +	if (err) {  		mlx4_err(dev, "Failed to init command interface, aborting.\n");  		goto err_sriov;  	} diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index a018ea2a43d..e151c21baf2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,  	return err;  } -static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, +static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port,  					      enum mlx4_steer_type steer,  					      u32 qpn)  { -	struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num]; +	struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1];  	struct mlx4_promisc_qp *pqp;  	list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { @@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,  	/* If the given qpn is also a promisc qp,  	 * it should be inserted to duplicates list  	 */ -	pqp = get_promisc_qp(dev, 0, steer, qpn); +	pqp = get_promisc_qp(dev, port, steer, qpn);  	if (pqp) {  		dqp = kmalloc(sizeof *dqp, GFP_KERNEL);  		if (!dqp) { @@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,  	s_steer = &mlx4_priv(dev)->steer[port - 1]; -	pqp = get_promisc_qp(dev, 0, steer, qpn); +	pqp = get_promisc_qp(dev, port, steer, qpn);  	if (!pqp)  		return 0; /* nothing to do */ @@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,  	s_steer = &mlx4_priv(dev)->steer[port - 1];  	/* if qp is not promisc, it cannot be duplicated */ -	if (!get_promisc_qp(dev, 0, steer, qpn)) +	if (!get_promisc_qp(dev, port, steer, qpn))  		return false;  	/* The qp is promisc qp so it is a duplicate on this index @@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,  	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;  	for (i = 0;  i < members_count; i++) {  		qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; -		if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { +		if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {  			/* the qp is not promisc, the entry can't be removed */  			goto out;  		} @@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,  	mutex_lock(&priv->mcg_table.mutex); -	if (get_promisc_qp(dev, 0, steer, qpn)) { +	if (get_promisc_qp(dev, port, steer, qpn)) {  		err = 0;  /* Noting to do, already exists */  		goto out_mutex;  	} @@ -503,7 +503,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,  	s_steer = &mlx4_priv(dev)->steer[port - 1];  	mutex_lock(&priv->mcg_table.mutex); -	pqp = get_promisc_qp(dev, 0, steer, qpn); +	pqp = get_promisc_qp(dev, port, steer, qpn);  	if (unlikely(!pqp)) {  		mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);  		/* nothing to do */ @@ -650,13 +650,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port,  	return err;  } -struct mlx4_net_trans_rule_hw_ctrl { -	__be32 ctrl; -	__be32 vf_vep_port; -	__be32 qpn; -	__be32 reserved; -}; -  static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,  				  struct mlx4_net_trans_rule_hw_ctrl *hw)  { @@ -680,87 +673,18 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,  	hw->qpn = cpu_to_be32(ctrl->qpn);  } -struct mlx4_net_trans_rule_hw_ib { -	u8	size; -	u8	rsvd1; -	__be16	id; -	u32	rsvd2; -	__be32	qpn; -	__be32	qpn_mask; -	u8	dst_gid[16]; -	u8	dst_gid_msk[16]; -} __packed; - -struct mlx4_net_trans_rule_hw_eth { -	u8	size; -	u8	rsvd; -	__be16	id; -	u8	rsvd1[6]; -	u8	dst_mac[6]; -	u16	rsvd2; -	u8	dst_mac_msk[6]; -	u16	rsvd3; -	u8	src_mac[6]; -	u16	rsvd4; -	u8	src_mac_msk[6]; -	u8      rsvd5; -	u8      ether_type_enable; -	__be16  ether_type; -	__be16  vlan_id_msk; -	__be16  vlan_id; -} __packed; - -struct mlx4_net_trans_rule_hw_tcp_udp { -	u8	size; -	u8	rsvd; -	__be16	id; -	__be16	rsvd1[3]; -	__be16	dst_port; -	__be16	rsvd2; -	__be16	dst_port_msk; -	__be16	rsvd3; -	__be16	src_port; -	__be16	rsvd4; -	__be16	src_port_msk; -} __packed; - -struct mlx4_net_trans_rule_hw_ipv4 { -	u8	size; -	u8	rsvd; -	__be16	id; -	__be32	rsvd1; -	__be32	dst_ip; -	__be32	dst_ip_msk; -	__be32	src_ip; -	__be32	src_ip_msk; -} __packed; - -struct _rule_hw { -	union { -		struct { -			u8 size; -			u8 rsvd; -			__be16 id; -		}; -		struct mlx4_net_trans_rule_hw_eth eth; -		struct mlx4_net_trans_rule_hw_ib ib; -		struct mlx4_net_trans_rule_hw_ipv4 ipv4; -		struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; -	}; +const u16 __sw_id_hw[] = { +	[MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001, +	[MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005, +	[MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003, +	[MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002, +	[MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004, +	[MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006  };  static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,  			    struct _rule_hw *rule_hw)  { -	static const u16 __sw_id_hw[] = { -		[MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001, -		[MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005, -		[MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003, -		[MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002, -		[MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004, -		[MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006 -	}; -  	static const size_t __rule_hw_sz[] = {  		[MLX4_NET_TRANS_RULE_ID_ETH] =  			sizeof(struct mlx4_net_trans_rule_hw_eth), diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 4d9df8f2a12..dba69d98734 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -690,6 +690,82 @@ struct mlx4_steer {  	struct list_head steer_entries[MLX4_NUM_STEERS];  }; +struct mlx4_net_trans_rule_hw_ctrl { +	__be32 ctrl; +	__be32 vf_vep_port; +	__be32 qpn; +	__be32 reserved; +}; + +struct mlx4_net_trans_rule_hw_ib { +	u8 size; +	u8 rsvd1; +	__be16 id; +	u32 rsvd2; +	__be32 qpn; +	__be32 qpn_mask; +	u8 dst_gid[16]; +	u8 dst_gid_msk[16]; +} __packed; + +struct mlx4_net_trans_rule_hw_eth { +	u8	size; +	u8	rsvd; +	__be16	id; +	u8	rsvd1[6]; +	u8	dst_mac[6]; +	u16	rsvd2; +	u8	dst_mac_msk[6]; +	u16	rsvd3; +	u8	src_mac[6]; +	u16	rsvd4; +	u8	src_mac_msk[6]; +	u8      rsvd5; +	u8      ether_type_enable; +	__be16  ether_type; +	__be16  vlan_id_msk; +	__be16  vlan_id; +} __packed; + +struct mlx4_net_trans_rule_hw_tcp_udp { +	u8	size; +	u8	rsvd; +	__be16	id; +	__be16	rsvd1[3]; +	__be16	dst_port; +	__be16	rsvd2; +	__be16	dst_port_msk; +	__be16	rsvd3; +	__be16	src_port; +	__be16	rsvd4; +	__be16	src_port_msk; +} __packed; + +struct mlx4_net_trans_rule_hw_ipv4 { +	u8	size; +	u8	rsvd; +	__be16	id; +	__be32	rsvd1; +	__be32	dst_ip; +	__be32	dst_ip_msk; +	__be32	src_ip; +	__be32	src_ip_msk; +} __packed; + +struct _rule_hw { +	union { +		struct { +			u8 size; +			u8 rsvd; +			__be16 id; +		}; +		struct mlx4_net_trans_rule_hw_eth eth; +		struct mlx4_net_trans_rule_hw_ib ib; +		struct mlx4_net_trans_rule_hw_ipv4 ipv4; +		struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; +	}; +}; +  struct mlx4_priv {  	struct mlx4_dev		dev; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 94ceddd17ab..293c9e820c4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -42,6 +42,7 @@  #include <linux/mlx4/cmd.h>  #include <linux/mlx4/qp.h>  #include <linux/if_ether.h> +#include <linux/etherdevice.h>  #include "mlx4.h"  #include "fw.h" @@ -2776,18 +2777,133 @@ ex_put:  	return err;  } +/* + * MAC validation for Flow Steering rules. + * VF can attach rules only with a mac address which is assigned to it. + */ +static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header, +				   struct list_head *rlist) +{ +	struct mac_res *res, *tmp; +	__be64 be_mac; + +	/* make sure it isn't multicast or broadcast mac*/ +	if (!is_multicast_ether_addr(eth_header->eth.dst_mac) && +	    !is_broadcast_ether_addr(eth_header->eth.dst_mac)) { +		list_for_each_entry_safe(res, tmp, rlist, list) { +			be_mac = cpu_to_be64(res->mac << 16); +			if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN)) +				return 0; +		} +		pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n", +		       eth_header->eth.dst_mac, slave); +		return -EINVAL; +	} +	return 0; +} + +/* + * In case of missing eth header, append eth header with a MAC address + * assigned to the VF. + */ +static int add_eth_header(struct mlx4_dev *dev, int slave, +			  struct mlx4_cmd_mailbox *inbox, +			  struct list_head *rlist, int header_id) +{ +	struct mac_res *res, *tmp; +	u8 port; +	struct mlx4_net_trans_rule_hw_ctrl *ctrl; +	struct mlx4_net_trans_rule_hw_eth *eth_header; +	struct mlx4_net_trans_rule_hw_ipv4 *ip_header; +	struct mlx4_net_trans_rule_hw_tcp_udp *l4_header; +	__be64 be_mac = 0; +	__be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); + +	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; +	port = be32_to_cpu(ctrl->vf_vep_port) & 0xff; +	eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1); + +	/* Clear a space in the inbox for eth header */ +	switch (header_id) { +	case MLX4_NET_TRANS_RULE_ID_IPV4: +		ip_header = +			(struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1); +		memmove(ip_header, eth_header, +			sizeof(*ip_header) + sizeof(*l4_header)); +		break; +	case MLX4_NET_TRANS_RULE_ID_TCP: +	case MLX4_NET_TRANS_RULE_ID_UDP: +		l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *) +			    (eth_header + 1); +		memmove(l4_header, eth_header, sizeof(*l4_header)); +		break; +	default: +		return -EINVAL; +	} +	list_for_each_entry_safe(res, tmp, rlist, list) { +		if (port == res->port) { +			be_mac = cpu_to_be64(res->mac << 16); +			break; +		} +	} +	if (!be_mac) { +		pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n", +		       port); +		return -EINVAL; +	} + +	memset(eth_header, 0, sizeof(*eth_header)); +	eth_header->size = sizeof(*eth_header) >> 2; +	eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]); +	memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN); +	memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN); + +	return 0; + +} +  int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,  					 struct mlx4_vhcr *vhcr,  					 struct mlx4_cmd_mailbox *inbox,  					 struct mlx4_cmd_mailbox *outbox,  					 struct mlx4_cmd_info *cmd)  { + +	struct mlx4_priv *priv = mlx4_priv(dev); +	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; +	struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];  	int err; +	struct mlx4_net_trans_rule_hw_ctrl *ctrl; +	struct _rule_hw  *rule_header; +	int header_id;  	if (dev->caps.steering_mode !=  	    MLX4_STEERING_MODE_DEVICE_MANAGED)  		return -EOPNOTSUPP; +	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; +	rule_header = (struct _rule_hw *)(ctrl + 1); +	header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); + +	switch (header_id) { +	case MLX4_NET_TRANS_RULE_ID_ETH: +		if (validate_eth_header_mac(slave, rule_header, rlist)) +			return -EINVAL; +		break; +	case MLX4_NET_TRANS_RULE_ID_IPV4: +	case MLX4_NET_TRANS_RULE_ID_TCP: +	case MLX4_NET_TRANS_RULE_ID_UDP: +		pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); +		if (add_eth_header(dev, slave, inbox, rlist, header_id)) +			return -EINVAL; +		vhcr->in_modifier += +			sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; +		break; +	default: +		pr_err("Corrupted mailbox.\n"); +		return -EINVAL; +	} +  	err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,  			   vhcr->in_modifier, 0,  			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 342b3a79bd0..a77c558d8f4 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1378,6 +1378,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)  	struct pci_dev *root = pdev->bus->self;  	u32 aer_pos; +	/* root bus? */ +	if (!root) +		return; +  	if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&  		adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)  		return; diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index bb8c8222122..4d15bf413bd 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -751,6 +751,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev)  	sp->srings = sr;  	sp->rx_desc = sp->srings->rxvector;  	sp->tx_desc = sp->srings->txvector; +	spin_lock_init(&sp->tx_lock);  	/* A couple calculations now, saves many cycles later. */  	setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c136162e647..3be88331d17 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1066,7 +1066,7 @@ static int stmmac_open(struct net_device *dev)  	} else  		priv->tm->enable = 1;  #endif -	clk_enable(priv->stmmac_clk); +	clk_prepare_enable(priv->stmmac_clk);  	stmmac_check_ether_addr(priv); @@ -1188,7 +1188,7 @@ open_error:  	if (priv->phydev)  		phy_disconnect(priv->phydev); -	clk_disable(priv->stmmac_clk); +	clk_disable_unprepare(priv->stmmac_clk);  	return ret;  } @@ -1246,7 +1246,7 @@ static int stmmac_release(struct net_device *dev)  #ifdef CONFIG_STMMAC_DEBUG_FS  	stmmac_exit_fs();  #endif -	clk_disable(priv->stmmac_clk); +	clk_disable_unprepare(priv->stmmac_clk);  	return 0;  } @@ -2178,7 +2178,7 @@ int stmmac_suspend(struct net_device *ndev)  	else {  		stmmac_set_mac(priv->ioaddr, false);  		/* Disable clock in case of PWM is off */ -		clk_disable(priv->stmmac_clk); +		clk_disable_unprepare(priv->stmmac_clk);  	}  	spin_unlock_irqrestore(&priv->lock, flags);  	return 0; @@ -2203,7 +2203,7 @@ int stmmac_resume(struct net_device *ndev)  		priv->hw->mac->pmt(priv->ioaddr, 0);  	else  		/* enable the clk prevously disabled */ -		clk_enable(priv->stmmac_clk); +		clk_prepare_enable(priv->stmmac_clk);  	netif_device_attach(ndev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c index 2a0e1abde7e..4ccd4e2977b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c @@ -97,19 +97,19 @@ static struct clk *timer_clock;  static void stmmac_tmu_start(unsigned int new_freq)  {  	clk_set_rate(timer_clock, new_freq); -	clk_enable(timer_clock); +	clk_prepare_enable(timer_clock);  }  static void stmmac_tmu_stop(void)  { -	clk_disable(timer_clock); +	clk_disable_unprepare(timer_clock);  }  int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)  {  	timer_clock = clk_get(NULL, TMU_CHANNEL); -	if (timer_clock == NULL) +	if (IS_ERR(timer_clock))  		return -1;  	if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) { @@ -126,7 +126,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)  int stmmac_close_ext_timer(void)  { -	clk_disable(timer_clock); +	clk_disable_unprepare(timer_clock);  	tmu2_unregister_user();  	clk_put(timer_clock);  	return 0; diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c index 256eddf1f75..79510942556 100644 --- a/drivers/net/irda/sh_sir.c +++ b/drivers/net/irda/sh_sir.c @@ -280,7 +280,7 @@ static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate)  	}  	clk = clk_get(NULL, "irda_clk"); -	if (!clk) { +	if (IS_ERR(clk)) {  		dev_err(dev, "can not get irda_clk\n");  		return -EIO;  	} diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c index 2346b38b983..799789518e8 100644 --- a/drivers/net/phy/bcm87xx.c +++ b/drivers/net/phy/bcm87xx.c @@ -229,3 +229,5 @@ static void __exit bcm87xx_exit(void)  		ARRAY_SIZE(bcm87xx_driver));  }  module_exit(bcm87xx_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index cf287e0eb40..2165d5fdb8c 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -21,6 +21,12 @@  #include <linux/phy.h>  #include <linux/micrel_phy.h> +/* Operation Mode Strap Override */ +#define MII_KSZPHY_OMSO				0x16 +#define KSZPHY_OMSO_B_CAST_OFF			(1 << 9) +#define KSZPHY_OMSO_RMII_OVERRIDE		(1 << 1) +#define KSZPHY_OMSO_MII_OVERRIDE		(1 << 0) +  /* general Interrupt control/status reg in vendor specific block. */  #define MII_KSZPHY_INTCS			0x1B  #define	KSZPHY_INTCS_JABBER			(1 << 15) @@ -101,6 +107,13 @@ static int kszphy_config_init(struct phy_device *phydev)  	return 0;  } +static int ksz8021_config_init(struct phy_device *phydev) +{ +	const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE; +	phy_write(phydev, MII_KSZPHY_OMSO, val); +	return 0; +} +  static int ks8051_config_init(struct phy_device *phydev)  {  	int regval; @@ -128,9 +141,22 @@ static struct phy_driver ksphy_driver[] = {  	.config_intr	= ks8737_config_intr,  	.driver		= { .owner = THIS_MODULE,},  }, { -	.phy_id		= PHY_ID_KS8041, +	.phy_id		= PHY_ID_KSZ8021, +	.phy_id_mask	= 0x00ffffff, +	.name		= "Micrel KSZ8021", +	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause | +			   SUPPORTED_Asym_Pause), +	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, +	.config_init	= ksz8021_config_init, +	.config_aneg	= genphy_config_aneg, +	.read_status	= genphy_read_status, +	.ack_interrupt	= kszphy_ack_interrupt, +	.config_intr	= kszphy_config_intr, +	.driver		= { .owner = THIS_MODULE,}, +}, { +	.phy_id		= PHY_ID_KSZ8041,  	.phy_id_mask	= 0x00fffff0, -	.name		= "Micrel KS8041", +	.name		= "Micrel KSZ8041",  	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause  				| SUPPORTED_Asym_Pause),  	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -141,9 +167,9 @@ static struct phy_driver ksphy_driver[] = {  	.config_intr	= kszphy_config_intr,  	.driver		= { .owner = THIS_MODULE,},  }, { -	.phy_id		= PHY_ID_KS8051, +	.phy_id		= PHY_ID_KSZ8051,  	.phy_id_mask	= 0x00fffff0, -	.name		= "Micrel KS8051", +	.name		= "Micrel KSZ8051",  	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause  				| SUPPORTED_Asym_Pause),  	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -154,8 +180,8 @@ static struct phy_driver ksphy_driver[] = {  	.config_intr	= kszphy_config_intr,  	.driver		= { .owner = THIS_MODULE,},  }, { -	.phy_id		= PHY_ID_KS8001, -	.name		= "Micrel KS8001 or KS8721", +	.phy_id		= PHY_ID_KSZ8001, +	.name		= "Micrel KSZ8001 or KS8721",  	.phy_id_mask	= 0x00ffffff,  	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),  	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -201,10 +227,11 @@ MODULE_LICENSE("GPL");  static struct mdio_device_id __maybe_unused micrel_tbl[] = {  	{ PHY_ID_KSZ9021, 0x000ffffe }, -	{ PHY_ID_KS8001, 0x00ffffff }, +	{ PHY_ID_KSZ8001, 0x00ffffff },  	{ PHY_ID_KS8737, 0x00fffff0 }, -	{ PHY_ID_KS8041, 0x00fffff0 }, -	{ PHY_ID_KS8051, 0x00fffff0 }, +	{ PHY_ID_KSZ8021, 0x00ffffff }, +	{ PHY_ID_KSZ8041, 0x00fffff0 }, +	{ PHY_ID_KSZ8051, 0x00fffff0 },  	{ }  }; diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index cbf7047decc..20f31d0d153 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -570,7 +570,7 @@ static int pppoe_release(struct socket *sock)  	po = pppox_sk(sk); -	if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { +	if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {  		dev_put(po->pppoe_dev);  		po->pppoe_dev = NULL;  	} diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 341b65dbbcd..3ffe8a6e3c8 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -848,7 +848,7 @@ static struct netpoll_info *team_netpoll_info(struct team *team)  }  #endif -static void __team_port_change_check(struct team_port *port, bool linkup); +static void __team_port_change_port_added(struct team_port *port, bool linkup);  static int team_port_add(struct team *team, struct net_device *port_dev)  { @@ -948,7 +948,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev)  	team_port_enable(team, port);  	list_add_tail_rcu(&port->list, &team->port_list);  	__team_compute_features(team); -	__team_port_change_check(port, !!netif_carrier_ok(port_dev)); +	__team_port_change_port_added(port, !!netif_carrier_ok(port_dev));  	__team_options_change_check(team);  	netdev_info(dev, "Port device %s added\n", portname); @@ -983,6 +983,8 @@ err_set_mtu:  	return err;  } +static void __team_port_change_port_removed(struct team_port *port); +  static int team_port_del(struct team *team, struct net_device *port_dev)  {  	struct net_device *dev = team->dev; @@ -999,8 +1001,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev)  	__team_option_inst_mark_removed_port(team, port);  	__team_options_change_check(team);  	__team_option_inst_del_port(team, port); -	port->removed = true; -	__team_port_change_check(port, false); +	__team_port_change_port_removed(port);  	team_port_disable(team, port);  	list_del_rcu(&port->list);  	netdev_rx_handler_unregister(port_dev); @@ -2251,13 +2252,11 @@ static void __team_options_change_check(struct team *team)  }  /* rtnl lock is held */ -static void __team_port_change_check(struct team_port *port, bool linkup) + +static void __team_port_change_send(struct team_port *port, bool linkup)  {  	int err; -	if (!port->removed && port->state.linkup == linkup) -		return; -  	port->changed = true;  	port->state.linkup = linkup;  	team_refresh_port_linkup(port); @@ -2282,6 +2281,23 @@ send_event:  } +static void __team_port_change_check(struct team_port *port, bool linkup) +{ +	if (port->state.linkup != linkup) +		__team_port_change_send(port, linkup); +} + +static void __team_port_change_port_added(struct team_port *port, bool linkup) +{ +	__team_port_change_send(port, linkup); +} + +static void __team_port_change_port_removed(struct team_port *port) +{ +	port->removed = true; +	__team_port_change_send(port, false); +} +  static void team_port_change_check(struct team_port *port, bool linkup)  {  	struct team *team = port->team; diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 4fd48df6b98..32e31c5c5dc 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -962,6 +962,10 @@ static const struct usb_device_id	products [] = {  	USB_DEVICE (0x2001, 0x3c05),  	.driver_info = (unsigned long) &ax88772_info,  }, { +       // DLink DUB-E100 H/W Ver C1 +       USB_DEVICE (0x2001, 0x1a02), +       .driver_info = (unsigned long) &ax88772_info, +}, {  	// Linksys USB1000  	USB_DEVICE (0x1737, 0x0039),  	.driver_info = (unsigned long) &ax88178_info, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index adfab3fc547..3543c9e5782 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -297,7 +297,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)  	if (ret < 0)  		goto err; -	if (info->subdriver && info->subdriver->suspend) +	if (intf == info->control && info->subdriver && info->subdriver->suspend)  		ret = info->subdriver->suspend(intf, message);  	if (ret < 0)  		usbnet_resume(intf); @@ -310,13 +310,14 @@ static int qmi_wwan_resume(struct usb_interface *intf)  	struct usbnet *dev = usb_get_intfdata(intf);  	struct qmi_wwan_state *info = (void *)&dev->data;  	int ret = 0; +	bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume); -	if (info->subdriver && info->subdriver->resume) +	if (callsub)  		ret = info->subdriver->resume(intf);  	if (ret < 0)  		goto err;  	ret = usbnet_resume(intf); -	if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend) +	if (ret < 0 && callsub && info->subdriver->suspend)  		info->subdriver->suspend(intf, PMSG_SUSPEND);  err:  	return ret; @@ -365,16 +366,20 @@ static const struct usb_device_id products[] = {  	},  	/* 2. Combined interface devices matching on class+protocol */ +	{	/* Huawei E367 and possibly others in "Windows mode" */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 7), +		.driver_info        = (unsigned long)&qmi_wwan_info, +	},  	{	/* Huawei E392, E398 and possibly others in "Windows mode" */  		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	}, -	{	/* Pantech UML290 */ -		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), +	{	/* Pantech UML290, P4200 and more */ +		USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	},  	{	/* Pantech UML290 - newer firmware */ -		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), +		USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	}, @@ -382,6 +387,7 @@ static const struct usb_device_id products[] = {  	{QMI_FIXED_INTF(0x19d2, 0x0055, 1)},	/* ZTE (Vodafone) K3520-Z */  	{QMI_FIXED_INTF(0x19d2, 0x0063, 4)},	/* ZTE (Vodafone) K3565-Z */  	{QMI_FIXED_INTF(0x19d2, 0x0104, 4)},	/* ZTE (Vodafone) K4505-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x0157, 5)},	/* ZTE MF683 */  	{QMI_FIXED_INTF(0x19d2, 0x0167, 4)},	/* ZTE MF820D */  	{QMI_FIXED_INTF(0x19d2, 0x0326, 4)},	/* ZTE MF821D */  	{QMI_FIXED_INTF(0x19d2, 0x1008, 4)},	/* ZTE (Vodafone) K3570-Z */ @@ -398,7 +404,6 @@ static const struct usb_device_id products[] = {  	/* 4. Gobi 1000 devices */  	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */  	{QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */ -	{QMI_GOBI1K_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */  	{QMI_GOBI1K_DEVICE(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */  	{QMI_GOBI1K_DEVICE(0x413c, 0x8172)},	/* Dell Gobi Modem device */  	{QMI_GOBI1K_DEVICE(0x1410, 0xa001)},	/* Novatel Gobi Modem device */ @@ -440,6 +445,7 @@ static const struct usb_device_id products[] = {  	{QMI_GOBI_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */  	{QMI_GOBI_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x9013)},	/* Sierra Wireless Gobi 3000 Modem device (MC8355) */ +	{QMI_GOBI_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */  	{QMI_GOBI_DEVICE(0x1199, 0x9015)},	/* Sierra Wireless Gobi 3000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x9019)},	/* Sierra Wireless Gobi 3000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x901b)},	/* Sierra Wireless MC7770 */ diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 7be49ea60b6..8e22417fa6c 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -656,7 +656,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)  		return -EIO;  	} -	*datap = *attrdata; +	*datap = le16_to_cpu(*attrdata);  	kfree(attrdata);  	return result; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index fd4b26d46fd..fc9f578a1e2 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1201,19 +1201,26 @@ deferred:  }  EXPORT_SYMBOL_GPL(usbnet_start_xmit); -static void rx_alloc_submit(struct usbnet *dev, gfp_t flags) +static int rx_alloc_submit(struct usbnet *dev, gfp_t flags)  {  	struct urb	*urb;  	int		i; +	int		ret = 0;  	/* don't refill the queue all at once */  	for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) {  		urb = usb_alloc_urb(0, flags);  		if (urb != NULL) { -			if (rx_submit(dev, urb, flags) == -ENOLINK) -				return; +			ret = rx_submit(dev, urb, flags); +			if (ret) +				goto err; +		} else { +			ret = -ENOMEM; +			goto err;  		}  	} +err: +	return ret;  }  /*-------------------------------------------------------------------------*/ @@ -1257,7 +1264,8 @@ static void usbnet_bh (unsigned long param)  		int	temp = dev->rxq.qlen;  		if (temp < RX_QLEN(dev)) { -			rx_alloc_submit(dev, GFP_ATOMIC); +			if (rx_alloc_submit(dev, GFP_ATOMIC) == -ENOLINK) +				return;  			if (temp != dev->rxq.qlen)  				netif_dbg(dev, link, dev->net,  					  "rxqlen %d --> %d\n", diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index aaaca9aa229..3f575afd8cf 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -10,6 +10,7 @@  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/module.h>  #include <linux/bitops.h>  #include <linux/cdev.h>  #include <linux/dma-mapping.h> diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 2588848f4a8..d066f2516e4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -2982,6 +2982,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,  	case EEP_RX_MASK:  		return pBase->txrxMask & 0xf;  	case EEP_PAPRD: +		if (AR_SREV_9462(ah)) +			return false; +		if (!ah->config.enable_paprd); +			return false;  		return !!(pBase->featureEnable & BIT(5));  	case EEP_CHAIN_MASK_REDUCE:  		return (pBase->miscConfiguration >> 0x3) & 0x1; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2c9f7d7ed4c..0ed3846f9cb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)  	};  	int training_power;  	int i, val; +	u32 am2pm_mask = ah->paprd_ratemask;  	if (IS_CHAN_2GHZ(ah->curchan))  		training_power = ar9003_get_training_power_2g(ah); @@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)  	}  	ah->paprd_training_power = training_power; +	if (AR_SREV_9330(ah)) +		am2pm_mask = 0; +  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,  		      ah->paprd_ratemask);  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, -		      ah->paprd_ratemask); +		      am2pm_mask);  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,  		      ah->paprd_ratemask_ht40); @@ -782,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)  }  EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); +static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah, +				       struct ath9k_hw_cal_data *caldata, +				       int chain) +{ +	u32 *pa_in = caldata->pa_table[chain]; +	int capdiv_offset, quick_drop_offset; +	int capdiv2g, quick_drop; +	int count = 0; +	int i; + +	if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah)) +		return false; + +	capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, +				  AR_PHY_65NM_CH0_TXRF3_CAPDIV2G); + +	quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, +				    AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP); + +	if (quick_drop) +		quick_drop -= 0x40; + +	for (i = 0; i < NUM_BIN + 1; i++) { +		if (pa_in[i] == 1400) +			count++; +	} + +	if (AR_SREV_9485(ah)) { +		if (pa_in[23] < 800) { +			capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150); +			capdiv2g += capdiv_offset; +			if (capdiv2g > 7) { +				capdiv2g = 7; +				if (pa_in[23] < 600) { +					quick_drop++; +					if (quick_drop > 0) +						quick_drop = 0; +				} +			} +		} else if (pa_in[23] == 1400) { +			quick_drop_offset = min_t(int, count / 3, 2); +			quick_drop += quick_drop_offset; +			capdiv2g += quick_drop_offset / 2; + +			if (capdiv2g > 7) +				capdiv2g = 7; + +			if (quick_drop > 0) { +				quick_drop = 0; +				capdiv2g -= quick_drop_offset; +				if (capdiv2g < 0) +					capdiv2g = 0; +			} +		} else { +			return false; +		} +	} else if (AR_SREV_9330(ah)) { +		if (pa_in[23] < 1000) { +			capdiv_offset = (1000 - pa_in[23]) / 100; +			capdiv2g += capdiv_offset; +			if (capdiv_offset > 3) { +				capdiv_offset = 1; +				quick_drop--; +			} + +			capdiv2g += capdiv_offset; +			if (capdiv2g > 6) +				capdiv2g = 6; +			if (quick_drop < -4) +				quick_drop = -4; +		} else if (pa_in[23] == 1400) { +			if (count > 3) { +				quick_drop++; +				capdiv2g -= count / 4; +				if (quick_drop > -2) +					quick_drop = -2; +			} else { +				capdiv2g--; +			} + +			if (capdiv2g < 0) +				capdiv2g = 0; +		} else { +			return false; +		} +	} + +	REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, +		      AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g); +	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, +		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, +		      quick_drop); + +	return true; +} +  int ar9003_paprd_create_curve(struct ath_hw *ah,  			      struct ath9k_hw_cal_data *caldata, int chain)  { @@ -817,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,  	if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))  		status = -2; +	if (ar9003_paprd_retrain_pa_in(ah, caldata, chain)) +		status = -EINPROGRESS; +  	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,  		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 7bfbaf065a4..84d3d495686 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -625,6 +625,10 @@  #define AR_PHY_AIC_CTRL_4_B0	(AR_SM_BASE + 0x4c0)  #define AR_PHY_AIC_STAT_2_B0	(AR_SM_BASE + 0x4cc) +#define AR_PHY_65NM_CH0_TXRF3       0x16048 +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G		0x0000001e +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S	1 +  #define AR_PHY_65NM_CH0_SYNTH4      0x1608c  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 68b643c8943..c8ef30127ad 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1577,6 +1577,8 @@ int ath9k_init_debug(struct ath_hw *ah)  			    sc->debug.debugfs_phy, sc, &fops_tx_chainmask);  	debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,  			    sc->debug.debugfs_phy, sc, &fops_disable_ani); +	debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, +			    &sc->sc_ah->config.enable_paprd);  	debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,  			    sc, &fops_regidx);  	debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index bacdb8fb4ef..9f83f71742a 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -341,7 +341,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)  {  	struct ath_btcoex *btcoex = &sc->btcoex; -	ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); +	if (btcoex->hw_timer_enabled) +		ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);  }  u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 60b6a9daff7..4faf0a39587 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)  		ah->config.spurchans[i][1] = AR_NO_SPUR;  	} -	/* PAPRD needs some more work to be enabled */ -	ah->config.paprd_disable = 1; -  	ah->config.rx_intr_mitigation = true;  	ah->config.pcieSerDesWrite = true; @@ -978,9 +975,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,  	else  		imr_reg |= AR_IMR_TXOK; -	if (opmode == NL80211_IFTYPE_AP) -		imr_reg |= AR_IMR_MIB; -  	ENABLE_REGWRITE_BUFFER(ah);  	REG_WRITE(ah, AR_IMR, imr_reg); @@ -1778,6 +1772,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  		/* Operating channel changed, reset channel calibration data */  		memset(caldata, 0, sizeof(*caldata));  		ath9k_init_nfcal_hist_buffer(ah, chan); +	} else if (caldata) { +		caldata->paprd_packet_sent = false;  	}  	ah->noise = ath9k_hw_getchan_noise(ah, chan); @@ -2501,9 +2497,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)  		pCap->rx_status_len = sizeof(struct ar9003_rxs);  		pCap->tx_desc_len = sizeof(struct ar9003_txc);  		pCap->txs_len = sizeof(struct ar9003_txs); -		if (!ah->config.paprd_disable && -		    ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) -			pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;  	} else {  		pCap->tx_desc_len = sizeof(struct ath_desc);  		if (AR_SREV_9280_20(ah)) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ce7332c64ef..de6968fc64f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -236,7 +236,6 @@ enum ath9k_hw_caps {  	ATH9K_HW_CAP_LDPC			= BIT(6),  	ATH9K_HW_CAP_FASTCLOCK			= BIT(7),  	ATH9K_HW_CAP_SGI_20			= BIT(8), -	ATH9K_HW_CAP_PAPRD			= BIT(9),  	ATH9K_HW_CAP_ANT_DIV_COMB		= BIT(10),  	ATH9K_HW_CAP_2GHZ			= BIT(11),  	ATH9K_HW_CAP_5GHZ			= BIT(12), @@ -287,12 +286,12 @@ struct ath9k_ops_config {  	u8 pcie_clock_req;  	u32 pcie_waen;  	u8 analog_shiftreg; -	u8 paprd_disable;  	u32 ofdm_trig_low;  	u32 ofdm_trig_high;  	u32 cck_trig_high;  	u32 cck_trig_low;  	u32 enable_ani; +	u32 enable_paprd;  	int serialize_regmode;  	bool rx_intr_mitigation;  	bool tx_intr_mitigation; @@ -405,6 +404,7 @@ struct ath9k_hw_cal_data {  	int8_t iCoff;  	int8_t qCoff;  	bool rtt_done; +	bool paprd_packet_sent;  	bool paprd_done;  	bool nfcal_pending;  	bool nfcal_interference; diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index d4549e9aac5..7b88b9c39cc 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -254,8 +254,9 @@ void ath_paprd_calibrate(struct work_struct *work)  	int chain_ok = 0;  	int chain;  	int len = 1800; +	int ret; -	if (!caldata) +	if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)  		return;  	ath9k_ps_wakeup(sc); @@ -282,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work)  			continue;  		chain_ok = 0; - -		ath_dbg(common, CALIBRATE, -			"Sending PAPRD frame for thermal measurement on chain %d\n", -			chain); -		if (!ath_paprd_send_frame(sc, skb, chain)) -			goto fail_paprd; -  		ar9003_paprd_setup_gain_table(ah, chain);  		ath_dbg(common, CALIBRATE, @@ -302,7 +296,13 @@ void ath_paprd_calibrate(struct work_struct *work)  			break;  		} -		if (ar9003_paprd_create_curve(ah, caldata, chain)) { +		ret = ar9003_paprd_create_curve(ah, caldata, chain); +		if (ret == -EINPROGRESS) { +			ath_dbg(common, CALIBRATE, +				"PAPRD curve on chain %d needs to be re-trained\n", +				chain); +			break; +		} else if (ret) {  			ath_dbg(common, CALIBRATE,  				"PAPRD create curve failed on chain %d\n",  				chain); @@ -423,7 +423,7 @@ set_timer:  		cal_interval = min(cal_interval, (u32)short_cal_interval);  	mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); -	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { +	if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) {  		if (!ah->caldata->paprd_done)  			ieee80211_queue_work(sc->hw, &sc->paprd_work);  		else if (!ah->paprd_table_write_done) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c9da6b2ecb..0d4155aec48 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2018,6 +2018,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,  	ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); +	if (sc->sc_ah->caldata) +		sc->sc_ah->caldata->paprd_packet_sent = true; +  	if (!(tx_flags & ATH_TX_ERROR))  		/* Frame was ACKed */  		tx_info->flags |= IEEE80211_TX_STAT_ACK; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 49765d34b4e..7c4ee72f9d5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -638,6 +638,8 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev)  		oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),  				       GFP_KERNEL); +		if (!oobirq_entry) +			return -ENOMEM;  		oobirq_entry->irq = res->start;  		oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;  		list_add_tail(&oobirq_entry->list, &oobirq_lh); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 2621dd3d7dc..6f70953f0ba 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -764,8 +764,11 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)  {  	char iovbuf[32];  	int retcode; +	__le32 arp_mode_le; -	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); +	arp_mode_le = cpu_to_le32(arp_mode); +	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, +			sizeof(iovbuf));  	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,  				   iovbuf, sizeof(iovbuf));  	retcode = retcode >= 0 ? 0 : retcode; @@ -781,8 +784,11 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)  {  	char iovbuf[32];  	int retcode; +	__le32 arp_enable_le; -	brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, +	arp_enable_le = cpu_to_le32(arp_enable); + +	brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,  			iovbuf, sizeof(iovbuf));  	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,  				   iovbuf, sizeof(iovbuf)); @@ -800,10 +806,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  	char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];	/*  Room for  				 "event_msgs" + '\0' + bitvec  */  	char buf[128], *ptr; -	u32 roaming = 1; -	uint bcn_timeout = 3; -	int scan_assoc_time = 40; -	int scan_unassoc_time = 40; +	__le32 roaming_le = cpu_to_le32(1); +	__le32 bcn_timeout_le = cpu_to_le32(3); +	__le32 scan_assoc_time_le = cpu_to_le32(40); +	__le32 scan_unassoc_time_le = cpu_to_le32(40);  	int i;  	struct brcmf_bus_dcmd *cmdlst;  	struct list_head *cur, *q; @@ -829,14 +835,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  	/* Setup timeout if Beacons are lost and roam is off to report  		 link down */ -	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, +	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,  		    sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,  				  sizeof(iovbuf));  	/* Enable/Disable build-in roaming to allowed ext supplicant to take  		 of romaing */ -	brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, +	brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,  		      iovbuf, sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,  				  sizeof(iovbuf)); @@ -848,9 +854,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  				  sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, -			 (char *)&scan_assoc_time, sizeof(scan_assoc_time)); +		 (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, -			 (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); +		 (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));  	/* Set and enable ARP offload feature */  	brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a299d42da8e..58f89fa9c9f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb)  	else  		devinfo->bus_pub.bus->dstats.tx_errors++; -	dev_kfree_skb(req->skb); +	brcmu_pkt_buf_free_skb(req->skb);  	req->skb = NULL;  	brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); @@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)  		devinfo->bus_pub.bus->dstats.rx_packets++;  	} else {  		devinfo->bus_pub.bus->dstats.rx_errors++; -		dev_kfree_skb(skb); +		brcmu_pkt_buf_free_skb(skb);  		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  		return;  	} @@ -550,13 +550,15 @@ static void brcmf_usb_rx_complete(struct urb *urb)  		if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {  			brcmf_dbg(ERROR, "rx protocol error\n");  			brcmu_pkt_buf_free_skb(skb); +			brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  			devinfo->bus_pub.bus->dstats.rx_errors++;  		} else {  			brcmf_rx_packet(devinfo->dev, ifidx, skb);  			brcmf_usb_rx_refill(devinfo, req);  		}  	} else { -		dev_kfree_skb(skb); +		brcmu_pkt_buf_free_skb(skb); +		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  	}  	return; @@ -581,14 +583,13 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,  	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,  			  skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,  			  req); -	req->urb->transfer_flags |= URB_ZERO_PACKET;  	req->devinfo = devinfo; +	brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);  	ret = usb_submit_urb(req->urb, GFP_ATOMIC); -	if (ret == 0) { -		brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); -	} else { -		dev_kfree_skb(req->skb); +	if (ret) { +		brcmf_usb_del_fromq(devinfo, req); +		brcmu_pkt_buf_free_skb(req->skb);  		req->skb = NULL;  		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  	} @@ -683,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)  	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);  	if (!req) { +		brcmu_pkt_buf_free_skb(skb);  		brcmf_dbg(ERROR, "no req to send\n");  		return -ENOMEM;  	} -	if (!req->urb) { -		brcmf_dbg(ERROR, "no urb for req %p\n", req); -		return -ENOBUFS; -	}  	req->skb = skb;  	req->devinfo = devinfo;  	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,  			  skb->data, skb->len, brcmf_usb_tx_complete, req);  	req->urb->transfer_flags |= URB_ZERO_PACKET; +	brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);  	ret = usb_submit_urb(req->urb, GFP_ATOMIC); -	if (!ret) { -		brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); -	} else { +	if (ret) { +		brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n"); +		brcmf_usb_del_fromq(devinfo, req); +		brcmu_pkt_buf_free_skb(req->skb);  		req->skb = NULL;  		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);  	} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 28c5fbb4af2..50b5553b696 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -500,8 +500,10 @@ static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,  	params_le->active_time = cpu_to_le32(-1);  	params_le->passive_time = cpu_to_le32(-1);  	params_le->home_time = cpu_to_le32(-1); -	if (ssid && ssid->SSID_len) -		memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); +	if (ssid && ssid->SSID_len) { +		params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len); +		memcpy(¶ms_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len); +	}  }  static s32 @@ -1876,16 +1878,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,  	}  	if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { -		scb_val.val = cpu_to_le32(0); +		memset(&scb_val, 0, sizeof(scb_val));  		err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,  				      sizeof(struct brcmf_scb_val_le)); -		if (err) +		if (err) {  			WL_ERR("Could not get rssi (%d)\n", err); - -		rssi = le32_to_cpu(scb_val.val); -		sinfo->filled |= STATION_INFO_SIGNAL; -		sinfo->signal = rssi; -		WL_CONN("RSSI %d dBm\n", rssi); +		} else { +			rssi = le32_to_cpu(scb_val.val); +			sinfo->filled |= STATION_INFO_SIGNAL; +			sinfo->signal = rssi; +			WL_CONN("RSSI %d dBm\n", rssi); +		}  	}  done: diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 7ed7d757702..64a48f06d68 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -77,7 +77,7 @@  					 NL80211_RRF_NO_IBSS)  static const struct ieee80211_regdomain brcms_regdom_x2 = { -	.n_reg_rules = 7, +	.n_reg_rules = 6,  	.alpha2 = "X2",  	.reg_rules = {  		BRCM_2GHZ_2412_2462, diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 1e86ea2266d..dbeebef562d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1442,6 +1442,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)  	return err;  err_free_irq: +	trans_pcie->irq_requested = false;  	free_irq(trans_pcie->irq, trans);  error:  	iwl_free_isr_ict(trans); diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index e970897f6ab..4cb234349fb 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev)  	mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); +	/* If we're powered off anyway, just let the mmc layer remove the +	 * card. */ +	if (!lbs_iface_active(card->priv)) +		return -ENOSYS; +  	dev_info(dev, "%s: suspend: PM flags = 0x%x\n",  		 sdio_func_id(func), flags); diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index c68adec3cc8..565527aee0e 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,  	cmd_code = le16_to_cpu(host_cmd->command);  	cmd_size = le16_to_cpu(host_cmd->size); -	skb_trim(cmd_node->cmd_skb, cmd_size); +	/* Adjust skb length */ +	if (cmd_node->cmd_skb->len > cmd_size) +		/* +		 * cmd_size is less than sizeof(struct host_cmd_ds_command). +		 * Trim off the unused portion. +		 */ +		skb_trim(cmd_node->cmd_skb, cmd_size); +	else if (cmd_node->cmd_skb->len < cmd_size) +		/* +		 * cmd_size is larger than sizeof(struct host_cmd_ds_command) +		 * because we have appended custom IE TLV. Increase skb length +		 * accordingly. +		 */ +		skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);  	do_gettimeofday(&tstamp);  	dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 8b9dbd76a25..64328af496f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1624,6 +1625,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_BIT8, 1); +	rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2400pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc43..7564ae992b7 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@  #define GPIOCSR_BIT5			FIELD32(0x00000020)  #define GPIOCSR_BIT6			FIELD32(0x00000040)  #define GPIOCSR_BIT7			FIELD32(0x00000080) +#define GPIOCSR_BIT8			FIELD32(0x00000100)  /*   * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d2cf8a4bc8b..3de0406735f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1942,6 +1943,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_DIR0, 1); +	rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3aae36bb0a9..89fee311d8f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)  	u16 reg;  	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); -	return rt2x00_get_field32(reg, MAC_CSR19_BIT7); +	return rt2x00_get_field16(reg, MAC_CSR19_BIT7);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u16 reg;  	/*  	 * Allocate eeprom data. @@ -1781,6 +1782,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); +	rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); +	rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7ee..196bd5103e4 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,15 @@   * MAC_CSR19: GPIO control register.   */  #define MAC_CSR19			0x0426 -#define MAC_CSR19_BIT0			FIELD32(0x0001) -#define MAC_CSR19_BIT1			FIELD32(0x0002) -#define MAC_CSR19_BIT2			FIELD32(0x0004) -#define MAC_CSR19_BIT3			FIELD32(0x0008) -#define MAC_CSR19_BIT4			FIELD32(0x0010) -#define MAC_CSR19_BIT5			FIELD32(0x0020) -#define MAC_CSR19_BIT6			FIELD32(0x0040) -#define MAC_CSR19_BIT7			FIELD32(0x0080) +#define MAC_CSR19_BIT0			FIELD16(0x0001) +#define MAC_CSR19_BIT1			FIELD16(0x0002) +#define MAC_CSR19_BIT2			FIELD16(0x0004) +#define MAC_CSR19_BIT3			FIELD16(0x0008) +#define MAC_CSR19_BIT4			FIELD16(0x0010) +#define MAC_CSR19_BIT5			FIELD16(0x0020) +#define MAC_CSR19_BIT6			FIELD16(0x0040) +#define MAC_CSR19_BIT7			FIELD16(0x0080) +#define MAC_CSR19_BIT8			FIELD16(0x0100)  /*   * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index cb8c2aca54e..b93516d832f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4089,6 +4089,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  		msleep(1);  		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0);  		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);  		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  	} diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 98aa426a356..4765bbd654c 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -983,6 +983,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -996,6 +997,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); +	rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2800_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6cf336595e2..6b4226b7161 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,  	skb_pull(entry->skb, RXINFO_DESC_SIZE);  	/* -	 * FIXME: we need to check for rx_pkt_len validity +	 * Check for rx_pkt_len validity. Return if invalid, leaving +	 * rxdesc->size zeroed out by the upper level.  	 */ +	if (unlikely(rx_pkt_len == 0 || +			rx_pkt_len > entry->queue->data_size)) { +		ERROR(entry->queue->rt2x00dev, +			"Bad frame size %d, forcing to 0\n", rx_pkt_len); +		return; +	} +  	rxd = (__le32 *)(entry->skb->data + rx_pkt_len);  	/* @@ -736,6 +744,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -749,6 +758,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); +	rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2800_probe_hw_mode(rt2x00dev); @@ -1157,6 +1174,8 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x1690, 0x0744) },  	{ USB_DEVICE(0x1690, 0x0761) },  	{ USB_DEVICE(0x1690, 0x0764) }, +	/* ASUS */ +	{ USB_DEVICE(0x0b05, 0x179d) },  	/* Cisco */  	{ USB_DEVICE(0x167b, 0x4001) },  	/* EnGenius */ @@ -1222,7 +1241,6 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x0b05, 0x1760) },  	{ USB_DEVICE(0x0b05, 0x1761) },  	{ USB_DEVICE(0x0b05, 0x1790) }, -	{ USB_DEVICE(0x0b05, 0x179d) },  	/* AzureWave */  	{ USB_DEVICE(0x13d3, 0x3262) },  	{ USB_DEVICE(0x13d3, 0x3284) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a6b88bd4a1a..3f07e36f462 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)  	 */  	if (unlikely(rxdesc.size == 0 ||  		     rxdesc.size > entry->queue->data_size)) { -		WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", +		ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",  			rxdesc.size, entry->queue->data_size);  		dev_kfree_skb(entry->skb);  		goto renew_skb; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3f7bc5cadf9..b8ec9616392 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Disable power saving. @@ -2850,6 +2851,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); +	rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt61pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0..8f3da5a5676 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry {  #define MAC_CSR13_BIT10			FIELD32(0x00000400)  #define MAC_CSR13_BIT11			FIELD32(0x00000800)  #define MAC_CSR13_BIT12			FIELD32(0x00001000) +#define MAC_CSR13_BIT13			FIELD32(0x00002000)  /*   * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ba6e434b859..248436c13ce 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -2190,6 +2191,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); +	rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt73usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d..df1cc116b83 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry {  #define MAC_CSR13_BIT10			FIELD32(0x00000400)  #define MAC_CSR13_BIT11			FIELD32(0x00000800)  #define MAC_CSR13_BIT12			FIELD32(0x00001000) +#define MAC_CSR13_BIT13			FIELD32(0x00002000) +#define MAC_CSR13_BIT14			FIELD32(0x00004000) +#define MAC_CSR13_BIT15			FIELD32(0x00008000)  /*   * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 04c3aef8a4f..2925094b2d9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -117,6 +117,7 @@  #define CHIP_VER_B			BIT(4)  #define CHIP_92C_BITMASK		BIT(0) +#define CHIP_UNKNOWN			BIT(7)  #define CHIP_92C_1T2R			0x03  #define CHIP_92C			0x01  #define CHIP_88C			0x00 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index bd0da7ef290..dd4bb0950a5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -994,8 +994,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)  		version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C :  			   VERSION_A_CHIP_88C;  	} else { -		version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : -			   VERSION_B_CHIP_88C; +		version = (enum version_8192c) (CHIP_VER_B | +				((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | +				((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); +		if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & +		     CHIP_VER_RTL_MASK)) { +			version = (enum version_8192c)(version | +				   ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) +				   ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | +				   CHIP_VENDOR_UMC)); +		}  	}  	switch (version) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 3aa927f8b9b..7d8f96405f4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -162,10 +162,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)  	/* request fw */  	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && -	    !IS_92C_SERIAL(rtlhal->version)) +	    !IS_92C_SERIAL(rtlhal->version)) {  		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; -	else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) +	} else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {  		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; +		pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); +	}  	rtlpriv->max_fw_size = 0x4000;  	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 3782e1cd369..934d861a323 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -2196,10 +2196,8 @@ static int __init acer_wmi_init(void)  		interface->capability &= ~ACER_CAP_BRIGHTNESS;  		pr_info("Brightness must be controlled by acpi video driver\n");  	} else { -#ifdef CONFIG_ACPI_VIDEO  		pr_info("Disabling ACPI video driver\n");  		acpi_video_unregister(); -#endif  	}  	if (wmi_has_guid(WMID_GUID3)) { diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index dfb1a92ce94..db8f63841b4 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -101,7 +101,7 @@ static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port,  	for (i = 0; i < 4; i++) {  		tmpval = (val >> (i * 8)) & 0xff; -		outb(tmpval, port + i); +		outb(tmpval, gmux_data->iostart + port + i);  	}  } @@ -142,8 +142,9 @@ static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port)  	u8 val;  	mutex_lock(&gmux_data->index_lock); -	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);  	gmux_index_wait_ready(gmux_data); +	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); +	gmux_index_wait_complete(gmux_data);  	val = inb(gmux_data->iostart + GMUX_PORT_VALUE);  	mutex_unlock(&gmux_data->index_lock); @@ -166,8 +167,9 @@ static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port)  	u32 val;  	mutex_lock(&gmux_data->index_lock); -	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);  	gmux_index_wait_ready(gmux_data); +	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); +	gmux_index_wait_complete(gmux_data);  	val = inl(gmux_data->iostart + GMUX_PORT_VALUE);  	mutex_unlock(&gmux_data->index_lock); @@ -461,18 +463,22 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,  	ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);  	if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {  		if (gmux_is_indexed(gmux_data)) { +			u32 version;  			mutex_init(&gmux_data->index_lock);  			gmux_data->indexed = true; +			version = gmux_read32(gmux_data, +				GMUX_PORT_VERSION_MAJOR); +			ver_major = (version >> 24) & 0xff; +			ver_minor = (version >> 16) & 0xff; +			ver_release = (version >> 8) & 0xff;  		} else {  			pr_info("gmux device not present\n");  			ret = -ENODEV;  			goto err_release;  		} -		pr_info("Found indexed gmux\n"); -	} else { -		pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, -			ver_release);  	} +	pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, +		ver_release, (gmux_data->indexed ? "indexed" : "classic"));  	memset(&props, 0, sizeof(props));  	props.type = BACKLIGHT_PLATFORM; @@ -505,9 +511,7 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,  	 * Disable the other backlight choices.  	 */  	acpi_video_dmi_promote_vendor(); -#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)  	acpi_video_unregister(); -#endif  	apple_bl_unregister();  	gmux_data->power_state = VGA_SWITCHEROO_ON; @@ -593,9 +597,7 @@ static void __devexit gmux_remove(struct pnp_dev *pnp)  	kfree(gmux_data);  	acpi_video_dmi_demote_vendor(); -#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)  	acpi_video_register(); -#endif  	apple_bl_register();  } diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index e38f91be0b1..4b568df5664 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -85,7 +85,7 @@ static char *wled_type = "unknown";  static char *bled_type = "unknown";  module_param(wled_type, charp, 0444); -MODULE_PARM_DESC(wlan_status, "Set the wled type on boot " +MODULE_PARM_DESC(wled_type, "Set the wled type on boot "  		 "(unknown, led or rfkill). "  		 "default is unknown"); @@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev,  	 * The significance of others is yet to be found.  	 * If we don't find the method, we assume the device are present.  	 */ -	rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp); +	rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp);  	if (!ACPI_FAILURE(rv)) -		len += sprintf(page + len, "HRWS value         : %#x\n", +		len += sprintf(page + len, "HWRS value         : %#x\n",  			       (uint) temp);  	/*  	 * Another value for userspace: the ASYM method returns 0x02 for @@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus)  	 * The significance of others is yet to be found.  	 */  	status = -	    acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); +	    acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result);  	if (!ACPI_FAILURE(status)) -		pr_notice("  HRWS returned %x", (int)hwrs_result); +		pr_notice("  HWRS returned %x", (int)hwrs_result);  	if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))  		asus->have_rsts = true; diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 2eb9fe8e8ef..c0e9ff489b2 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -47,9 +47,7 @@  #include <linux/thermal.h>  #include <acpi/acpi_bus.h>  #include <acpi/acpi_drivers.h> -#ifdef CONFIG_ACPI_VIDEO  #include <acpi/video.h> -#endif  #include "asus-wmi.h" @@ -1704,10 +1702,8 @@ static int asus_wmi_add(struct platform_device *pdev)  	if (asus->driver->quirks->wmi_backlight_power)  		acpi_video_dmi_promote_vendor();  	if (!acpi_video_backlight_support()) { -#ifdef CONFIG_ACPI_VIDEO  		pr_info("Disabling ACPI video driver\n");  		acpi_video_unregister(); -#endif  		err = asus_wmi_backlight_init(asus);  		if (err && err != -ENODEV)  			goto fail_backlight; diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index dab91b48d22..5ca264179f4 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -610,12 +610,12 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)  		if (!bus) {  			pr_warn("Unable to find PCI bus 1?\n"); -			goto out_unlock; +			goto out_put_dev;  		}  		if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {  			pr_err("Unable to read PCI config space?\n"); -			goto out_unlock; +			goto out_put_dev;  		}  		absent = (l == 0xffffffff); @@ -627,7 +627,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)  				absent ? "absent" : "present");  			pr_warn("skipped wireless hotplug as probably "  				"inappropriate for this model\n"); -			goto out_unlock; +			goto out_put_dev;  		}  		if (!blocked) { @@ -635,7 +635,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)  			if (dev) {  				/* Device already present */  				pci_dev_put(dev); -				goto out_unlock; +				goto out_put_dev;  			}  			dev = pci_scan_single_device(bus, 0);  			if (dev) { @@ -650,6 +650,8 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)  				pci_dev_put(dev);  			}  		} +out_put_dev: +		pci_dev_put(port);  	}  out_unlock: diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index c1ca7bcebb6..dd90d15f521 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -26,9 +26,7 @@  #include <linux/seq_file.h>  #include <linux/debugfs.h>  #include <linux/ctype.h> -#ifdef CONFIG_ACPI_VIDEO  #include <acpi/video.h> -#endif  /*   * This driver is needed because a number of Samsung laptops do not hook @@ -1558,9 +1556,7 @@ static int __init samsung_init(void)  		samsung->handle_backlight = false;  	} else if (samsung->quirks->broken_acpi_video) {  		pr_info("Disabling ACPI video driver\n"); -#ifdef CONFIG_ACPI_VIDEO  		acpi_video_unregister(); -#endif  	}  #endif diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 80e37794931..52daaa816e5 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -545,7 +545,7 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY",	/* 600e/x, 770e, 770x */   */  static int acpi_evalf(acpi_handle handle, -		      void *res, char *method, char *fmt, ...) +		      int *res, char *method, char *fmt, ...)  {  	char *fmt0 = fmt;  	struct acpi_object_list params; @@ -606,7 +606,7 @@ static int acpi_evalf(acpi_handle handle,  		success = (status == AE_OK &&  			   out_obj.type == ACPI_TYPE_INTEGER);  		if (success && res) -			*(int *)res = out_obj.integer.value; +			*res = out_obj.integer.value;  		break;  	case 'v':		/* void */  		success = status == AE_OK; @@ -7386,17 +7386,18 @@ static int fan_get_status(u8 *status)  	 * Add TPACPI_FAN_RD_ACPI_FANS ? */  	switch (fan_status_access_mode) { -	case TPACPI_FAN_RD_ACPI_GFAN: +	case TPACPI_FAN_RD_ACPI_GFAN: {  		/* 570, 600e/x, 770e, 770x */ +		int res; -		if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) +		if (unlikely(!acpi_evalf(gfan_handle, &res, NULL, "d")))  			return -EIO;  		if (likely(status)) -			*status = s & 0x07; +			*status = res & 0x07;  		break; - +	}  	case TPACPI_FAN_RD_TPEC:  		/* all except 570, 600e/x, 770e, 770x */  		if (unlikely(!acpi_ec_read(fan_status_offset, &s))) diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 0b66d0f2592..4b6688909fe 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -100,6 +100,13 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,  		writel(period_cycles, pc->mmio_base + CAP3);  	} +	if (!test_bit(PWMF_ENABLED, &pwm->flags)) { +		reg_val = readw(pc->mmio_base + ECCTL2); +		/* Disable APWM mode to put APWM output Low */ +		reg_val &= ~ECCTL2_APWM_MODE; +		writew(reg_val, pc->mmio_base + ECCTL2); +	} +  	pm_runtime_put_sync(pc->chip.dev);  	return 0;  } diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index c3756d1be19..b1996bcd5b7 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -104,6 +104,7 @@ struct ehrpwm_pwm_chip {  	struct pwm_chip	chip;  	unsigned int	clk_rate;  	void __iomem	*mmio_base; +	unsigned long period_cycles[NUM_PWM_CHANNEL];  };  static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) @@ -210,6 +211,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,  	unsigned long long c;  	unsigned long period_cycles, duty_cycles;  	unsigned short ps_divval, tb_divval; +	int i;  	if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC)  		return -ERANGE; @@ -229,6 +231,28 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,  		duty_cycles = (unsigned long)c;  	} +	/* +	 * Period values should be same for multiple PWM channels as IP uses +	 * same period register for multiple channels. +	 */ +	for (i = 0; i < NUM_PWM_CHANNEL; i++) { +		if (pc->period_cycles[i] && +				(pc->period_cycles[i] != period_cycles)) { +			/* +			 * Allow channel to reconfigure period if no other +			 * channels being configured. +			 */ +			if (i == pwm->hwpwm) +				continue; + +			dev_err(chip->dev, "Period value conflicts with channel %d\n", +					i); +			return -EINVAL; +		} +	} + +	pc->period_cycles[pwm->hwpwm] = period_cycles; +  	/* Configure clock prescaler to support Low frequency PWM wave */  	if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,  				&tb_divval)) { @@ -320,10 +344,15 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)  static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)  { +	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); +  	if (test_bit(PWMF_ENABLED, &pwm->flags)) {  		dev_warn(chip->dev, "Removing PWM device without disabling\n");  		pm_runtime_put_sync(chip->dev);  	} + +	/* set period value to zero on free */ +	pc->period_cycles[pwm->hwpwm] = 0;  }  static const struct pwm_ops ehrpwm_pwm_ops = { diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 6caa222af77..ab00cab905b 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -22,6 +22,7 @@  #include <linux/err.h>  #include <linux/platform_device.h> +#include <linux/regulator/of_regulator.h>  #include <linux/regulator/driver.h>  #include <linux/regulator/machine.h>  #include <linux/mfd/tps65217.h> @@ -281,37 +282,130 @@ static const struct regulator_desc regulators[] = {  			   NULL),  }; +#ifdef CONFIG_OF +static struct of_regulator_match reg_matches[] = { +	{ .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, +	{ .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, +	{ .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, +	{ .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, +	{ .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, +	{ .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, +	{ .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, +}; + +static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) +{ +	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); +	struct device_node *node = tps->dev->of_node; +	struct tps65217_board *pdata; +	struct device_node *regs; +	int i, count; + +	regs = of_find_node_by_name(node, "regulators"); +	if (!regs) +		return NULL; + +	count = of_regulator_match(pdev->dev.parent, regs, +				reg_matches, TPS65217_NUM_REGULATOR); +	of_node_put(regs); +	if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) +		return NULL; + +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return NULL; + +	for (i = 0; i < count; i++) { +		if (!reg_matches[i].init_data || !reg_matches[i].of_node) +			continue; + +		pdata->tps65217_init_data[i] = reg_matches[i].init_data; +		pdata->of_node[i] = reg_matches[i].of_node; +	} + +	return pdata; +} +#else +static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) +{ +	return NULL; +} +#endif +  static int __devinit tps65217_regulator_probe(struct platform_device *pdev)  { +	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); +	struct tps65217_board *pdata = dev_get_platdata(tps->dev); +	struct regulator_init_data *reg_data;  	struct regulator_dev *rdev; -	struct tps65217 *tps; -	struct tps_info *info = &tps65217_pmic_regs[pdev->id];  	struct regulator_config config = { }; +	int i, ret; -	/* Already set by core driver */ -	tps = dev_to_tps65217(pdev->dev.parent); -	tps->info[pdev->id] = info; +	if (tps->dev->of_node) +		pdata = tps65217_parse_dt(pdev); -	config.dev = &pdev->dev; -	config.of_node = pdev->dev.of_node; -	config.init_data = pdev->dev.platform_data; -	config.driver_data = tps; +	if (!pdata) { +		dev_err(&pdev->dev, "Platform data not found\n"); +		return -EINVAL; +	} + +	if (tps65217_chip_id(tps) != TPS65217) { +		dev_err(&pdev->dev, "Invalid tps chip version\n"); +		return -ENODEV; +	} + +	platform_set_drvdata(pdev, tps); + +	for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { + +		reg_data = pdata->tps65217_init_data[i]; -	rdev = regulator_register(®ulators[pdev->id], &config); -	if (IS_ERR(rdev)) -		return PTR_ERR(rdev); +		/* +		 * Regulator API handles empty constraints but not NULL +		 * constraints +		 */ +		if (!reg_data) +			continue; -	platform_set_drvdata(pdev, rdev); +		/* Register the regulators */ +		tps->info[i] = &tps65217_pmic_regs[i]; +		config.dev = tps->dev; +		config.init_data = reg_data; +		config.driver_data = tps; +		config.regmap = tps->regmap; +		if (tps->dev->of_node) +			config.of_node = pdata->of_node[i]; + +		rdev = regulator_register(®ulators[i], &config); +		if (IS_ERR(rdev)) { +			dev_err(tps->dev, "failed to register %s regulator\n", +				pdev->name); +			ret = PTR_ERR(rdev); +			goto err_unregister_regulator; +		} + +		/* Save regulator for cleanup */ +		tps->rdev[i] = rdev; +	}  	return 0; + +err_unregister_regulator: +	while (--i >= 0) +		regulator_unregister(tps->rdev[i]); + +	return ret;  }  static int __devexit tps65217_regulator_remove(struct platform_device *pdev)  { -	struct regulator_dev *rdev = platform_get_drvdata(pdev); +	struct tps65217 *tps = platform_get_drvdata(pdev); +	unsigned int i; + +	for (i = 0; i < TPS65217_NUM_REGULATOR; i++) +		regulator_unregister(tps->rdev[i]);  	platform_set_drvdata(pdev, NULL); -	regulator_unregister(rdev);  	return 0;  } diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 590cfafc7c1..1859f71372e 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -1008,8 +1008,8 @@ static int rpmsg_probe(struct virtio_device *vdev)  	return 0;  free_coherent: -	dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, bufs_va, -					vrp->bufs_dma); +	dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, +					bufs_va, vrp->bufs_dma);  vqs_del:  	vdev->config->del_vqs(vrp->vdev);  free_vrp: @@ -1043,7 +1043,7 @@ static void __devexit rpmsg_remove(struct virtio_device *vdev)  	vdev->config->del_vqs(vrp->vdev); -	dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, +	dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE,  					vrp->rbufs, vrp->bufs_dma);  	kfree(vrp); diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index c5d06fe83bb..9277d945bf4 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -495,6 +495,11 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)  	if (ret < 0)  		goto out1; +	/* ensure interrupts are disabled, bootloaders can be strange */ +	ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); +	if (ret < 0) +		dev_warn(&pdev->dev, "unable to disable interrupt\n"); +  	/* init cached IRQ enable bits */  	ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);  	if (ret < 0) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 15370a2c5ff..0595c763daf 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -534,11 +534,11 @@ static void dasd_change_state(struct dasd_device *device)  	if (rc)  		device->target = device->state; -	if (device->state == device->target) -		wake_up(&dasd_init_waitq); -  	/* let user-space know that the device status changed */  	kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); + +	if (device->state == device->target) +		wake_up(&dasd_init_waitq);  }  /* @@ -2157,6 +2157,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)  		    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&  		    (!dasd_eer_enabled(device))) {  			cqr->status = DASD_CQR_FAILED; +			cqr->intrc = -EAGAIN;  			continue;  		}  		/* Don't try to start requests if device is stopped */ @@ -3270,6 +3271,16 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)  			dasd_schedule_device_bh(device);  		}  		if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { +			if (!(device->path_data.opm & eventlpm) && +			    !(device->path_data.tbvpm & eventlpm)) { +				/* +				 * we can not establish a pathgroup on an +				 * unavailable path, so trigger a path +				 * verification first +				 */ +				device->path_data.tbvpm |= eventlpm; +				dasd_schedule_device_bh(device); +			}  			DBF_DEV_EVENT(DBF_WARNING, device, "%s",  				      "Pathgroup re-established\n");  			if (device->discipline->kick_validate) diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 157defe5e06..6b556995bb3 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -384,6 +384,29 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu,  		group->next = NULL;  }; +static int +suborder_not_supported(struct dasd_ccw_req *cqr) +{ +	char *sense; +	char reason; +	char msg_format; +	char msg_no; + +	sense = dasd_get_sense(&cqr->irb); +	if (!sense) +		return 0; + +	reason = sense[0]; +	msg_format = (sense[7] & 0xF0); +	msg_no = (sense[7] & 0x0F); + +	/* command reject, Format 0 MSG 4 - invalid parameter */ +	if ((reason == 0x80) && (msg_format == 0x00) && (msg_no == 0x04)) +		return 1; + +	return 0; +} +  static int read_unit_address_configuration(struct dasd_device *device,  					   struct alias_lcu *lcu)  { @@ -435,6 +458,8 @@ static int read_unit_address_configuration(struct dasd_device *device,  	do {  		rc = dasd_sleep_on(cqr); +		if (rc && suborder_not_supported(cqr)) +			return -EOPNOTSUPP;  	} while (rc && (cqr->retries > 0));  	if (rc) {  		spin_lock_irqsave(&lcu->lock, flags); @@ -521,7 +546,7 @@ static void lcu_update_work(struct work_struct *work)  	 * processing the data  	 */  	spin_lock_irqsave(&lcu->lock, flags); -	if (rc || (lcu->flags & NEED_UAC_UPDATE)) { +	if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {  		DBF_DEV_EVENT(DBF_WARNING, device, "could not update"  			    " alias data in lcu (rc = %d), retry later", rc);  		schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 2fb2b9ea97e..c48c72abbef 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1507,7 +1507,8 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,   * call might change behaviour of DASD devices.   */  static int -dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) +dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, +		  unsigned long flags)  {  	struct dasd_ccw_req *cqr;  	int rc; @@ -1516,10 +1517,19 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)  	if (IS_ERR(cqr))  		return PTR_ERR(cqr); +	/* +	 * set flags e.g. turn on failfast, to prevent blocking +	 * the calling function should handle failed requests +	 */ +	cqr->flags |= flags; +  	rc = dasd_sleep_on(cqr);  	if (!rc)  		/* trigger CIO to reprobe devices */  		css_schedule_reprobe(); +	else if (cqr->intrc == -EAGAIN) +		rc = -EAGAIN; +  	dasd_sfree_request(cqr, cqr->memdev);  	return rc;  } @@ -1527,7 +1537,8 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)  /*   * Valide storage server of current device.   */ -static void dasd_eckd_validate_server(struct dasd_device *device) +static int dasd_eckd_validate_server(struct dasd_device *device, +				     unsigned long flags)  {  	int rc;  	struct dasd_eckd_private *private; @@ -1536,17 +1547,18 @@ static void dasd_eckd_validate_server(struct dasd_device *device)  	private = (struct dasd_eckd_private *) device->private;  	if (private->uid.type == UA_BASE_PAV_ALIAS ||  	    private->uid.type == UA_HYPER_PAV_ALIAS) -		return; +		return 0;  	if (dasd_nopav || MACHINE_IS_VM)  		enable_pav = 0;  	else  		enable_pav = 1; -	rc = dasd_eckd_psf_ssc(device, enable_pav); +	rc = dasd_eckd_psf_ssc(device, enable_pav, flags);  	/* may be requested feature is not available on server,  	 * therefore just report error and go ahead */  	DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "  			"returned rc=%d", private->uid.ssid, rc); +	return rc;  }  /* @@ -1556,7 +1568,13 @@ static void dasd_eckd_do_validate_server(struct work_struct *work)  {  	struct dasd_device *device = container_of(work, struct dasd_device,  						  kick_validate); -	dasd_eckd_validate_server(device); +	if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST) +	    == -EAGAIN) { +		/* schedule worker again if failed */ +		schedule_work(&device->kick_validate); +		return; +	} +  	dasd_put_device(device);  } @@ -1685,7 +1703,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)  	if (rc)  		goto out_err2; -	dasd_eckd_validate_server(device); +	dasd_eckd_validate_server(device, 0);  	/* device may report different configuration data after LCU setup */  	rc = dasd_eckd_read_conf(device); @@ -4153,7 +4171,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)  	rc = dasd_alias_make_device_known_to_lcu(device);  	if (rc)  		return rc; -	dasd_eckd_validate_server(device); +	dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST);  	/* RE-Read Configuration Data */  	rc = dasd_eckd_read_conf(device); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index ed25c8740a9..fc916f5d731 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1426,6 +1426,8 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)  		return IO_SCH_REPROBE;  	if (cdev->online)  		return IO_SCH_VERIFY; +	if (cdev->private->state == DEV_STATE_NOT_OPER) +		return IO_SCH_UNREG_ATTACH;  	return IO_SCH_NOP;  } @@ -1519,11 +1521,14 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)  			goto out;  		break;  	case IO_SCH_UNREG_ATTACH: +		spin_lock_irqsave(sch->lock, flags);  		if (cdev->private->flags.resuming) {  			/* Device will be handled later. */  			rc = 0; -			goto out; +			goto out_unlock;  		} +		sch_set_cdev(sch, NULL); +		spin_unlock_irqrestore(sch->lock, flags);  		/* Unregister ccw device. */  		ccw_device_unregister(cdev);  		break; diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 33d6630529d..91eec60252e 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1264,6 +1264,9 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)  	int rc = 0;  	u64 mask64; +	memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1)); +	memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2)); +  	bnx2i_adjust_qp_size(hba);  	iscsi_init.flags = diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 796482badf1..2b4261cb774 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1315,8 +1315,9 @@ static void complete_scsi_command(struct CommandList *cp)  	}  		break;  	case CMD_PROTOCOL_ERR: +		cmd->result = DID_ERROR << 16;  		dev_warn(&h->pdev->dev, "cp %p has " -			"protocol error \n", cp); +			"protocol error\n", cp);  		break;  	case CMD_HARDWARE_ERR:  		cmd->result = DID_ERROR << 16; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index dc27598785e..ed38454228c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4066,7 +4066,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)  	spin_lock_init(&instance->cmd_pool_lock);  	spin_lock_init(&instance->hba_lock);  	spin_lock_init(&instance->completion_lock); -	spin_lock_init(&poll_aen_lock);  	mutex_init(&instance->aen_mutex);  	mutex_init(&instance->reset_mutex); @@ -5392,6 +5391,8 @@ static int __init megasas_init(void)  	printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,  	       MEGASAS_EXT_VERSION); +	spin_lock_init(&poll_aen_lock); +  	support_poll_for_event = 2;  	support_device_change = 1; diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 9d46fcbe775..9d5a56c4b33 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1209,6 +1209,13 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)  	u16 message_control; +	/* Check whether controller SAS2008 B0 controller, +	   if it is SAS2008 B0 controller use IO-APIC instead of MSIX */ +	if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && +	    ioc->pdev->revision == 0x01) { +		return -EINVAL; +	} +  	base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);  	if (!base) {  		dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " @@ -2424,10 +2431,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)  	}  	/* command line tunables  for max controller queue depth */ -	if (max_queue_depth != -1) -		max_request_credit = (max_queue_depth < facts->RequestCredit) -		    ? max_queue_depth : facts->RequestCredit; -	else +	if (max_queue_depth != -1 && max_queue_depth != 0) { +		max_request_credit = min_t(u16, max_queue_depth + +			ioc->hi_priority_depth + ioc->internal_depth, +			facts->RequestCredit); +		if (max_request_credit > MAX_HBA_QUEUE_DEPTH) +			max_request_credit =  MAX_HBA_QUEUE_DEPTH; +	} else  		max_request_credit = min_t(u16, facts->RequestCredit,  		    MAX_HBA_QUEUE_DEPTH); @@ -2502,7 +2512,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)  	/* set the scsi host can_queue depth  	 * with some internal commands that could be outstanding  	 */ -	ioc->shost->can_queue = ioc->scsiio_depth - (2); +	ioc->shost->can_queue = ioc->scsiio_depth;  	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "  	    "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4a6381c8725..de2337f255a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -42,6 +42,8 @@  #include <trace/events/scsi.h> +static void scsi_eh_done(struct scsi_cmnd *scmd); +  #define SENSE_TIMEOUT		(10*HZ)  /* @@ -241,6 +243,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)  	if (! scsi_command_normalize_sense(scmd, &sshdr))  		return FAILED;	/* no valid sense data */ +	if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) +		/* +		 * nasty: for mid-layer issued TURs, we need to return the +		 * actual sense data without any recovery attempt.  For eh +		 * issued ones, we need to try to recover and interpret +		 */ +		return SUCCESS; +  	if (scsi_sense_is_deferred(&sshdr))  		return NEEDS_RETRY; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ffd77739ae3..faa790fba13 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -776,7 +776,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)  	}  	if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ -		req->errors = result;  		if (result) {  			if (sense_valid && req->sense) {  				/* @@ -792,6 +791,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)  			if (!sense_deferred)  				error = __scsi_error_from_host_byte(cmd, result);  		} +		/* +		 * __scsi_error_from_host_byte may have reset the host_byte +		 */ +		req->errors = cmd->result;  		req->resid_len = scsi_get_resid(cmd); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 56a93794c47..d947ffc20ce 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -764,6 +764,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,  	sdev->model = (char *) (sdev->inquiry + 16);  	sdev->rev = (char *) (sdev->inquiry + 32); +	if (strncmp(sdev->vendor, "ATA     ", 8) == 0) { +		/* +		 * sata emulation layer device.  This is a hack to work around +		 * the SATL power management specifications which state that +		 * when the SATL detects the device has gone into standby +		 * mode, it shall respond with NOT READY. +		 */ +		sdev->allow_restart = 1; +	} +  	if (*bflags & BLIST_ISROM) {  		sdev->type = TYPE_ROM;  		sdev->removable = 1; diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index c7030fbee79..3e79a2f0004 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -331,7 +331,7 @@ static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,  	int i;  	for_each_sg(table->sgl, sg_elem, table->nents, i) -		sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length); +		sg[idx++] = *sg_elem;  	*p_idx = idx;  } diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 32c26d795ed..8f32a1323a7 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -355,7 +355,7 @@ int __init register_intc_controller(struct intc_desc *desc)  			if (unlikely(res)) {  				if (res == -EEXIST) {  					res = irq_domain_associate(d->domain, -								   irq, irq); +								   irq2, irq2);  					if (unlikely(res)) {  						pr_err("domain association "  						       "failure\n"); diff --git a/drivers/sh/pfc/pinctrl.c b/drivers/sh/pfc/pinctrl.c index 2804eaae804..0646bf6e788 100644 --- a/drivers/sh/pfc/pinctrl.c +++ b/drivers/sh/pfc/pinctrl.c @@ -208,10 +208,13 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,  		break;  	case PINMUX_TYPE_GPIO: +	case PINMUX_TYPE_INPUT: +	case PINMUX_TYPE_OUTPUT:  		break;  	default:  		pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type); -		return -ENOTSUPP; +		ret = -ENOTSUPP; +		goto err;  	}  	ret = 0; diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index d0cafd63719..f2ffd963f1c 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -51,10 +51,12 @@ 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_IOW(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOR(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) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 6c81e377262..cc8931fde83 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1412,6 +1412,13 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev,  		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");  		return -EINVAL;  	} +	/* +	 * Need to 'get' the PCI device to match the 'put' in dio200_detach(). +	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once +	 * support for manual attachment of PCI devices via dio200_attach() +	 * has been removed. +	 */ +	pci_dev_get(pci_dev);  	return dio200_pci_common_attach(dev, pci_dev);  } diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index aabba9886b7..f5028790303 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -565,6 +565,13 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,  		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");  		return -EINVAL;  	} +	/* +	 * Need to 'get' the PCI device to match the 'put' in pc236_detach(). +	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once +	 * support for manual attachment of PCI devices via pc236_attach() +	 * has been removed. +	 */ +	pci_dev_get(pci_dev);  	return pc236_pci_common_attach(dev, pci_dev);  } diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 40ec1ffebba..8191c4e28e0 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -298,6 +298,13 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev,  		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");  		return -EINVAL;  	} +	/* +	 * Need to 'get' the PCI device to match the 'put' in pc263_detach(). +	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once +	 * support for manual attachment of PCI devices via pc263_attach() +	 * has been removed. +	 */ +	pci_dev_get(pci_dev);  	return pc263_pci_common_attach(dev, pci_dev);  } diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 4e17f13e57f..8bf109e7bb0 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1503,6 +1503,13 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)  			DRIVER_NAME ": BUG! cannot determine board type!\n");  		return -EINVAL;  	} +	/* +	 * Need to 'get' the PCI device to match the 'put' in pci224_detach(). +	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once +	 * support for manual attachment of PCI devices via pci224_attach() +	 * has been removed. +	 */ +	pci_dev_get(pci_dev);  	return pci224_attach_common(dev, pci_dev, NULL);  } diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 1b67d0c61fa..66e74bd1226 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2925,6 +2925,13 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev,  			"amplc_pci230: BUG! cannot determine board type!\n");  		return -EINVAL;  	} +	/* +	 * Need to 'get' the PCI device to match the 'put' in pci230_detach(). +	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once +	 * support for manual attachment of PCI devices via pci230_attach() +	 * has been removed. +	 */ +	pci_dev_get(pci_dev);  	return pci230_attach_common(dev, pci_dev);  } diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 874e02e4766..67a914a10b5 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -378,7 +378,7 @@ das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,  	int chan;  	lsb = data[0] & 0xff; -	msb = (data[0] >> 8) & 0xf; +	msb = (data[0] >> 8) & 0xff;  	chan = CR_CHAN(insn->chanspec); @@ -623,7 +623,7 @@ static const struct das08_board_struct das08_boards[] = {  		.ai = das08_ai_rinsn,  		.ai_nbits = 16,  		.ai_pg = das08_pg_none, -		.ai_encoding = das08_encode12, +		.ai_encoding = das08_encode16,  		.ao = das08jr_ao_winsn,  		.ao_nbits = 16,  		.di = das08jr_di_rbits, @@ -922,6 +922,13 @@ das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev)  		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");  		return -EINVAL;  	} +	/* +	 * Need to 'get' the PCI device to match the 'put' in das08_detach(). +	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once +	 * support for manual attachment of PCI devices via das08_attach() +	 * has been removed. +	 */ +	pci_dev_get(pdev);  	return das08_pci_attach_common(dev, pdev);  } diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 18d108fd967..f3da59063ed 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -121,8 +121,10 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,  	if (rx_array == NULL)  		return -ENOMEM;  	ret = lis3l02dq_read_all(indio_dev, rx_array); -	if (ret < 0) +	if (ret < 0) { +		kfree(rx_array);  		return ret; +	}  	for (i = 0; i < scan_count; i++)  		data[i] = combine_8_to_16(rx_array[i*4+1],  					rx_array[i*4+3]); diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 095837285f4..19a064d649e 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -647,6 +647,8 @@ static ssize_t ad7192_write_frequency(struct device *dev,  	ret = strict_strtoul(buf, 10, &lval);  	if (ret)  		return ret; +	if (lval == 0) +		return -EINVAL;  	mutex_lock(&indio_dev->mlock);  	if (iio_buffer_enabled(indio_dev)) { diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 93aa431287a..eb8e9d69efd 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -195,6 +195,8 @@ static ssize_t adis16260_write_frequency(struct device *dev,  	ret = strict_strtol(buf, 10, &val);  	if (ret)  		return ret; +	if (val == 0) +		return -EINVAL;  	mutex_lock(&indio_dev->mlock);  	if (spi_get_device_id(st->us)) { diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 1f4c17779b5..a618327e06e 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -234,6 +234,8 @@ static ssize_t adis16400_write_frequency(struct device *dev,  	ret = strict_strtol(buf, 10, &val);  	if (ret)  		return ret; +	if (val == 0) +		return -EINVAL;  	mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index f04ece7fbc2..3ccff189f25 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -425,6 +425,8 @@ static ssize_t ade7753_write_frequency(struct device *dev,  	ret = strict_strtol(buf, 10, &val);  	if (ret)  		return ret; +	if (val == 0) +		return -EINVAL;  	mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 6cee28a5e87..abb1e9c8d09 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -445,6 +445,8 @@ static ssize_t ade7754_write_frequency(struct device *dev,  	ret = strict_strtol(buf, 10, &val);  	if (ret)  		return ret; +	if (val == 0) +		return -EINVAL;  	mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index b3f7e0fa961..eb0a2a98f38 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -385,6 +385,8 @@ static ssize_t ade7759_write_frequency(struct device *dev,  	ret = strict_strtol(buf, 10, &val);  	if (ret)  		return ret; +	if (val == 0) +		return -EINVAL;  	mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 695ea35f75b..d0a7e408efe 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -837,7 +837,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)  	}  	ret = mfd_add_devices(nvec->dev, -1, nvec_devices, -			      ARRAY_SIZE(nvec_devices), base, 0); +			      ARRAY_SIZE(nvec_devices), base, 0, NULL);  	if (ret)  		dev_err(nvec->dev, "error adding subdevices\n"); diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5e2856c0e0b..55e9c865585 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -48,13 +48,20 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,  	mode->vsync_end = mode->vsync_start + timings->vsw;  	mode->vtotal = mode->vsync_end + timings->vbp; -	/* note: whether or not it is interlaced, +/- h/vsync, etc, -	 * which should be set in the mode flags, is not exposed in -	 * the omap_video_timings struct.. but hdmi driver tracks -	 * those separately so all we have to have to set the mode -	 * is the way to recover these timings values, and the -	 * omap_dss_driver would do the rest. -	 */ +	mode->flags = 0; + +	if (timings->interlace) +		mode->flags |= DRM_MODE_FLAG_INTERLACE; + +	if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) +		mode->flags |= DRM_MODE_FLAG_PHSYNC; +	else +		mode->flags |= DRM_MODE_FLAG_NHSYNC; + +	if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) +		mode->flags |= DRM_MODE_FLAG_PVSYNC; +	else +		mode->flags |= DRM_MODE_FLAG_NVSYNC;  }  static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -71,6 +78,22 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,  	timings->vfp = mode->vsync_start - mode->vdisplay;  	timings->vsw = mode->vsync_end - mode->vsync_start;  	timings->vbp = mode->vtotal - mode->vsync_end; + +	timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + +	if (mode->flags & DRM_MODE_FLAG_PHSYNC) +		timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	else +		timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW; + +	if (mode->flags & DRM_MODE_FLAG_PVSYNC) +		timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	else +		timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW; + +	timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; +	timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; +	timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;  }  static void omap_connector_dpms(struct drm_connector *connector, int mode) @@ -187,7 +210,7 @@ static int omap_connector_get_modes(struct drm_connector *connector)  		}  	} else {  		struct drm_display_mode *mode = drm_mode_create(dev); -		struct omap_video_timings timings; +		struct omap_video_timings timings = {0};  		dssdrv->get_timings(dssdev, &timings); @@ -291,7 +314,7 @@ void omap_connector_mode_set(struct drm_connector *connector,  	struct omap_connector *omap_connector = to_omap_connector(connector);  	struct omap_dss_device *dssdev = omap_connector->dssdev;  	struct omap_dss_driver *dssdrv = dssdev->driver; -	struct omap_video_timings timings; +	struct omap_video_timings timings = {0};  	copy_timings_drm_to_omap(&timings, mode); diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index d9832194580..758ce0a8d82 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -8,6 +8,7 @@  #include <linux/cdev.h>  #include <linux/uaccess.h>  #include <linux/netdevice.h> +#include <linux/etherdevice.h>  #include <linux/poll.h>  #include <linux/sched.h>  #include "ozconfig.h" @@ -213,7 +214,7 @@ static int oz_set_active_pd(u8 *addr)  		if (old_pd)  			oz_pd_put(old_pd);  	} else { -		if (!memcmp(addr, "\0\0\0\0\0\0", sizeof(addr))) { +		if (is_zero_ether_addr(addr)) {  			spin_lock_bh(&g_cdev.lock);  			pd = g_cdev.active_pd;  			g_cdev.active_pd = 0; diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 0e26d5f6cf2..495ee1205e0 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -117,13 +117,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter,  	if (skb == NULL)  		goto _recv_indicatepkt_drop;  	skb->data = precv_frame->u.hdr.rx_data; -#ifdef NET_SKBUFF_DATA_USES_OFFSET -	skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail - -		     precv_frame->u.hdr.rx_head); -#else -	skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail; -#endif  	skb->len = precv_frame->u.hdr.len; +	skb_set_tail_pointer(skb, skb->len);  	if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1))  		skb->ip_summed = CHECKSUM_UNNECESSARY;  	else diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index e4bdf2a2b58..3aa895ec650 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -200,7 +200,7 @@ s_vProcessRxMACHeader (      } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {          cbHeaderSize += 6;          pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); -	if ((*pwType == cpu_to_le16(ETH_P_IPX)) || +	if ((*pwType == cpu_to_be16(ETH_P_IPX)) ||  	    (*pwType == cpu_to_le16(0xF380))) {  		cbHeaderSize -= 8;              pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index bb464527fc1..b6e04e7b629 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1699,7 +1699,7 @@ s_bPacketToWirelessUsb(      // 802.1H      if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {  	if (pDevice->dwDiagRefCount == 0) { -		if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) || +		if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) ||  		    (psEthHeader->wType == cpu_to_le16(0xF380))) {  			memcpy((PBYTE) (pbyPayloadHead),  			       abySNAP_Bridgetunnel, 6); @@ -2838,10 +2838,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)      Packet_Type = skb->data[ETH_HLEN+1];      Descriptor_type = skb->data[ETH_HLEN+1+1+2];      Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); -    if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { -	/* 802.1x OR eapol-key challenge frame transfer */ -	if (((Protocol_Version == 1) || (Protocol_Version == 2)) && -		(Packet_Type == 3)) { +	if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { +		/* 802.1x OR eapol-key challenge frame transfer */ +		if (((Protocol_Version == 1) || (Protocol_Version == 2)) && +			(Packet_Type == 3)) {                          bTxeapol_key = TRUE;                         if(!(Key_info & BIT3) &&  //WPA or RSN group-key challenge  			   (Key_info & BIT8) && (Key_info & BIT9)) {    //send 2/2 key @@ -2987,19 +2987,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)          }      } -    if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { -        if (pDevice->byBBType != BB_TYPE_11A) { -            pDevice->wCurrentRate = RATE_1M; -            pDevice->byACKRate = RATE_1M; -            pDevice->byTopCCKBasicRate = RATE_1M; -            pDevice->byTopOFDMBasicRate = RATE_6M; -        } else { -            pDevice->wCurrentRate = RATE_6M; -            pDevice->byACKRate = RATE_6M; -            pDevice->byTopCCKBasicRate = RATE_1M; -            pDevice->byTopOFDMBasicRate = RATE_6M; -        } -    } +	if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { +		if (pDevice->byBBType != BB_TYPE_11A) { +			pDevice->wCurrentRate = RATE_1M; +			pDevice->byACKRate = RATE_1M; +			pDevice->byTopCCKBasicRate = RATE_1M; +			pDevice->byTopOFDMBasicRate = RATE_6M; +		} else { +			pDevice->wCurrentRate = RATE_6M; +			pDevice->byACKRate = RATE_6M; +			pDevice->byTopCCKBasicRate = RATE_1M; +			pDevice->byTopOFDMBasicRate = RATE_6M; +		} +	}      DBG_PRT(MSG_LEVEL_DEBUG,  	    KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n", @@ -3015,7 +3015,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)      if (bNeedEncryption == TRUE) {          DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); -	if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) { +	if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) {  		bNeedEncryption = FALSE;              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));              if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index fabff4d650e..0970127344e 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -327,9 +327,9 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,  	return result;  } -int prism2_scan(struct wiphy *wiphy, struct net_device *dev, -		struct cfg80211_scan_request *request) +int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)  { +	struct net_device *dev = request->wdev->netdev;  	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);  	wlandevice_t *wlandev = dev->ml_priv;  	struct p80211msg_dot11req_scan msg1; diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index c214977b4ab..52b43b7b83d 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1251,13 +1251,12 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw,  					void *pampd, struct tmem_pool *pool,  					struct tmem_oid *oid, uint32_t index)  { -	int ret = 0; -  	BUG_ON(!is_ephemeral(pool)); -	zbud_decompress((struct page *)(data), pampd); +	if (zbud_decompress((struct page *)(data), pampd) < 0) +		return -EINVAL;  	zbud_free_and_delist((struct zbud_hdr *)pampd);  	atomic_dec(&zcache_curr_eph_pampd_count); -	return ret; +	return 0;  }  /* diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 0694d9b1bce..6aba4395e8d 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -221,6 +221,7 @@ static int iscsi_login_zero_tsih_s1(  {  	struct iscsi_session *sess = NULL;  	struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; +	int ret;  	sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL);  	if (!sess) { @@ -257,9 +258,17 @@ static int iscsi_login_zero_tsih_s1(  		return -ENOMEM;  	}  	spin_lock(&sess_idr_lock); -	idr_get_new(&sess_idr, NULL, &sess->session_index); +	ret = idr_get_new(&sess_idr, NULL, &sess->session_index);  	spin_unlock(&sess_idr_lock); +	if (ret < 0) { +		pr_err("idr_get_new() for sess_idr failed\n"); +		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +				ISCSI_LOGIN_STATUS_NO_RESOURCES); +		kfree(sess); +		return -ENOMEM; +	} +  	sess->creation_time = get_jiffies_64();  	spin_lock_init(&sess->session_stats_lock);  	/* diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 91799973081..41641ba5482 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -218,6 +218,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)  		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;  		return -EINVAL;  	} +	if (cmd->data_length < 4) { +		pr_warn("SET TARGET PORT GROUPS parameter list length %u too" +			" small\n", cmd->data_length); +		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; +		return -EINVAL; +	} +  	buf = transport_kmap_data_sg(cmd);  	/* diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index cf2c66f3c11..9fc9a6006ca 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -669,6 +669,13 @@ int target_report_luns(struct se_cmd *se_cmd)  	unsigned char *buf;  	u32 lun_count = 0, offset = 8, i; +	if (se_cmd->data_length < 16) { +		pr_warn("REPORT LUNS allocation length %u too small\n", +			se_cmd->data_length); +		se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; +		return -EINVAL; +	} +  	buf = transport_kmap_data_sg(se_cmd);  	if (!buf)  		return -ENOMEM; diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 76db75e836e..9ba495477fd 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -325,17 +325,30 @@ static int iblock_execute_unmap(struct se_cmd *cmd)  	struct iblock_dev *ibd = dev->dev_ptr;  	unsigned char *buf, *ptr = NULL;  	sector_t lba; -	int size = cmd->data_length; +	int size;  	u32 range;  	int ret = 0;  	int dl, bd_dl; +	if (cmd->data_length < 8) { +		pr_warn("UNMAP parameter list length %u too small\n", +			cmd->data_length); +		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; +		return -EINVAL; +	} +  	buf = transport_kmap_data_sg(cmd);  	dl = get_unaligned_be16(&buf[0]);  	bd_dl = get_unaligned_be16(&buf[2]); -	size = min(size - 8, bd_dl); +	size = cmd->data_length - 8; +	if (bd_dl > size) +		pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", +			cmd->data_length, bd_dl); +	else +		size = bd_dl; +  	if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {  		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;  		ret = -EINVAL; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 1e946502c37..956c84c6b66 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1540,6 +1540,14 @@ static int core_scsi3_decode_spec_i_port(  	tidh_new->dest_local_nexus = 1;  	list_add_tail(&tidh_new->dest_list, &tid_dest_list); +	if (cmd->data_length < 28) { +		pr_warn("SPC-PR: Received PR OUT parameter list" +			" length too small: %u\n", cmd->data_length); +		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; +		ret = -EINVAL; +		goto out; +	} +  	buf = transport_kmap_data_sg(cmd);  	/*  	 * For a PERSISTENT RESERVE OUT specify initiator ports payload, diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 5552fa7426b..9d7ce3daa26 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -667,7 +667,8 @@ static void pscsi_free_device(void *p)  	kfree(pdv);  } -static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) +static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, +				     unsigned char *sense_buffer)  {  	struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;  	struct scsi_device *sd = pdv->pdv_sd; @@ -679,7 +680,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)  	 * not been allocated because TCM is handling the emulation directly.  	 */  	if (!pt) -		return 0; +		return;  	cdb = &pt->pscsi_cdb[0];  	result = pt->pscsi_result; @@ -687,11 +688,11 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)  	 * Hack to make sure that Write-Protect modepage is set if R/O mode is  	 * forced.  	 */ +	if (!cmd->se_deve || !cmd->data_length) +		goto after_mode_sense; +  	if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&  	     (status_byte(result) << 1) == SAM_STAT_GOOD) { -		if (!cmd->se_deve) -			goto after_mode_sense; -  		if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) {  			unsigned char *buf = transport_kmap_data_sg(cmd); @@ -708,7 +709,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)  	}  after_mode_sense: -	if (sd->type != TYPE_TAPE) +	if (sd->type != TYPE_TAPE || !cmd->data_length)  		goto after_mode_select;  	/* @@ -750,10 +751,10 @@ after_mode_sense:  	}  after_mode_select: -	if (status_byte(result) & CHECK_CONDITION) -		return 1; - -	return 0; +	if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) { +		memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER); +		cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; +	}  }  enum { @@ -1184,13 +1185,6 @@ fail:  	return -ENOMEM;  } -static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd) -{ -	struct pscsi_plugin_task *pt = cmd->priv; - -	return pt->pscsi_sense; -} -  /*	pscsi_get_device_rev():   *   * @@ -1273,7 +1267,6 @@ static struct se_subsystem_api pscsi_template = {  	.check_configfs_dev_params = pscsi_check_configfs_dev_params,  	.set_configfs_dev_params = pscsi_set_configfs_dev_params,  	.show_configfs_dev_params = pscsi_show_configfs_dev_params, -	.get_sense_buffer	= pscsi_get_sense_buffer,  	.get_device_rev		= pscsi_get_device_rev,  	.get_device_type	= pscsi_get_device_type,  	.get_blocks		= pscsi_get_blocks, diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4c861de538c..388a922c8f6 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -877,9 +877,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd)  static int spc_emulate_request_sense(struct se_cmd *cmd)  {  	unsigned char *cdb = cmd->t_task_cdb; -	unsigned char *buf; +	unsigned char *rbuf;  	u8 ua_asc = 0, ua_ascq = 0; -	int err = 0; +	unsigned char buf[SE_SENSE_BUF]; + +	memset(buf, 0, SE_SENSE_BUF);  	if (cdb[1] & 0x01) {  		pr_err("REQUEST_SENSE description emulation not" @@ -888,20 +890,21 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)  		return -ENOSYS;  	} -	buf = transport_kmap_data_sg(cmd); - -	if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { +	rbuf = transport_kmap_data_sg(cmd); +	if (cmd->scsi_sense_reason != 0) { +		/* +		 * Out of memory.  We will fail with CHECK CONDITION, so +		 * we must not clear the unit attention condition. +		 */ +		target_complete_cmd(cmd, CHECK_CONDITION); +		return 0; +	} else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {  		/*  		 * CURRENT ERROR, UNIT ATTENTION  		 */  		buf[0] = 0x70;  		buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; -		if (cmd->data_length < 18) { -			buf[7] = 0x00; -			err = -EINVAL; -			goto end; -		}  		/*  		 * The Additional Sense Code (ASC) from the UNIT ATTENTION  		 */ @@ -915,11 +918,6 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)  		buf[0] = 0x70;  		buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; -		if (cmd->data_length < 18) { -			buf[7] = 0x00; -			err = -EINVAL; -			goto end; -		}  		/*  		 * NO ADDITIONAL SENSE INFORMATION  		 */ @@ -927,8 +925,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)  		buf[7] = 0x0A;  	} -end: -	transport_kunmap_data_sg(cmd); +	if (rbuf) { +		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); +		transport_kunmap_data_sg(cmd); +	} +  	target_complete_cmd(cmd, GOOD);  	return 0;  } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4de3186dc44..269f5448839 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -567,6 +567,34 @@ static void target_complete_failure_work(struct work_struct *work)  	transport_generic_request_failure(cmd);  } +/* + * Used when asking transport to copy Sense Data from the underlying + * Linux/SCSI struct scsi_cmnd + */ +static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd) +{ +	unsigned char *buffer = cmd->sense_buffer; +	struct se_device *dev = cmd->se_dev; +	u32 offset = 0; + +	WARN_ON(!cmd->se_lun); + +	if (!dev) +		return NULL; + +	if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) +		return NULL; + +	offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); + +	/* Automatically padded */ +	cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; + +	pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n", +		dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); +	return &buffer[offset]; +} +  void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)  {  	struct se_device *dev = cmd->se_dev; @@ -580,11 +608,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)  	cmd->transport_state &= ~CMD_T_BUSY;  	if (dev && dev->transport->transport_complete) { -		if (dev->transport->transport_complete(cmd, -				cmd->t_data_sg) != 0) { -			cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; +		dev->transport->transport_complete(cmd, +				cmd->t_data_sg, +				transport_get_sense_buffer(cmd)); +		if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)  			success = 1; -		}  	}  	/* @@ -1181,15 +1209,20 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)  			/* Returns CHECK_CONDITION + INVALID_CDB_FIELD */  			goto out_invalid_cdb_field;  		} - +		/* +		 * For the overflow case keep the existing fabric provided +		 * ->data_length.  Otherwise for the underflow case, reset +		 * ->data_length to the smaller SCSI expected data transfer +		 * length. +		 */  		if (size > cmd->data_length) {  			cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;  			cmd->residual_count = (size - cmd->data_length);  		} else {  			cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;  			cmd->residual_count = (cmd->data_length - size); +			cmd->data_length = size;  		} -		cmd->data_length = size;  	}  	return 0; @@ -1816,61 +1849,6 @@ execute:  EXPORT_SYMBOL(target_execute_cmd);  /* - * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd - */ -static int transport_get_sense_data(struct se_cmd *cmd) -{ -	unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; -	struct se_device *dev = cmd->se_dev; -	unsigned long flags; -	u32 offset = 0; - -	WARN_ON(!cmd->se_lun); - -	if (!dev) -		return 0; - -	spin_lock_irqsave(&cmd->t_state_lock, flags); -	if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { -		spin_unlock_irqrestore(&cmd->t_state_lock, flags); -		return 0; -	} - -	if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) -		goto out; - -	if (!dev->transport->get_sense_buffer) { -		pr_err("dev->transport->get_sense_buffer is NULL\n"); -		goto out; -	} - -	sense_buffer = dev->transport->get_sense_buffer(cmd); -	if (!sense_buffer) { -		pr_err("ITT 0x%08x cmd %p: Unable to locate" -			" sense buffer for task with sense\n", -			cmd->se_tfo->get_task_tag(cmd), cmd); -		goto out; -	} - -	spin_unlock_irqrestore(&cmd->t_state_lock, flags); - -	offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); - -	memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); - -	/* Automatically padded */ -	cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; - -	pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", -		dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); -	return 0; - -out: -	spin_unlock_irqrestore(&cmd->t_state_lock, flags); -	return -1; -} - -/*   * Process all commands up to the last received ORDERED task attribute which   * requires another blocking boundary   */ @@ -1985,7 +1963,7 @@ static void transport_handle_queue_full(  static void target_complete_ok_work(struct work_struct *work)  {  	struct se_cmd *cmd = container_of(work, struct se_cmd, work); -	int reason = 0, ret; +	int ret;  	/*  	 * Check if we need to move delayed/dormant tasks from cmds on the @@ -2002,23 +1980,19 @@ static void target_complete_ok_work(struct work_struct *work)  		schedule_work(&cmd->se_dev->qf_work_queue);  	/* -	 * Check if we need to retrieve a sense buffer from +	 * Check if we need to send a sense buffer from  	 * the struct se_cmd in question.  	 */  	if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { -		if (transport_get_sense_data(cmd) < 0) -			reason = TCM_NON_EXISTENT_LUN; - -		if (cmd->scsi_status) { -			ret = transport_send_check_condition_and_sense( -					cmd, reason, 1); -			if (ret == -EAGAIN || ret == -ENOMEM) -				goto queue_full; +		WARN_ON(!cmd->scsi_status); +		ret = transport_send_check_condition_and_sense( +					cmd, 0, 1); +		if (ret == -EAGAIN || ret == -ENOMEM) +			goto queue_full; -			transport_lun_remove_cmd(cmd); -			transport_cmd_check_stop_to_fabric(cmd); -			return; -		} +		transport_lun_remove_cmd(cmd); +		transport_cmd_check_stop_to_fabric(cmd); +		return;  	}  	/*  	 * Check for a callback, used by amongst other things @@ -2216,7 +2190,6 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)  	struct page **pages;  	int i; -	BUG_ON(!sg);  	/*  	 * We need to take into account a possible offset here for fabrics like  	 * tcm_loop who may be using a contig buffer from the SCSI midlayer for @@ -2224,13 +2197,17 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)  	 */  	if (!cmd->t_data_nents)  		return NULL; -	else if (cmd->t_data_nents == 1) + +	BUG_ON(!sg); +	if (cmd->t_data_nents == 1)  		return kmap(sg_page(sg)) + sg->offset;  	/* >1 page. use vmap */  	pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); -	if (!pages) +	if (!pages) { +		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;  		return NULL; +	}  	/* convert sg[] to pages[] */  	for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { @@ -2239,8 +2216,10 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)  	cmd->t_data_vmap = vmap(pages, cmd->t_data_nents,  VM_MAP, PAGE_KERNEL);  	kfree(pages); -	if (!cmd->t_data_vmap) +	if (!cmd->t_data_vmap) { +		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;  		return NULL; +	}  	return cmd->t_data_vmap + cmd->t_data_sg[0].offset;  } @@ -2326,19 +2305,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)  	 * into the fabric for data transfers, go ahead and complete it right  	 * away.  	 */ -	if (!cmd->data_length) { +	if (!cmd->data_length && +	    cmd->t_task_cdb[0] != REQUEST_SENSE && +	    cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {  		spin_lock_irq(&cmd->t_state_lock);  		cmd->t_state = TRANSPORT_COMPLETE;  		cmd->transport_state |= CMD_T_ACTIVE;  		spin_unlock_irq(&cmd->t_state_lock); -		if (cmd->t_task_cdb[0] == REQUEST_SENSE) { -			u8 ua_asc = 0, ua_ascq = 0; - -			core_scsi3_ua_clear_for_request_sense(cmd, -					&ua_asc, &ua_ascq); -		} -  		INIT_WORK(&cmd->work, target_complete_ok_work);  		queue_work(target_completion_wq, &cmd->work);  		return 0; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d5c689d6217..e309e8b0aab 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -132,6 +132,7 @@  #define  UCR4_OREN  	 (1<<1)  /* Receiver overrun interrupt enable */  #define  UCR4_DREN  	 (1<<0)  /* Recv data ready interrupt enable */  #define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */ +#define  UFCR_DCEDTE	 (1<<6)  /* DCE/DTE mode select */  #define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */  #define  UFCR_RFDIV_REG(x)	(((x) < 7 ? 6 - (x) : 6) << 7)  #define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */ @@ -667,22 +668,11 @@ static void imx_break_ctl(struct uart_port *port, int break_state)  static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)  {  	unsigned int val; -	unsigned int ufcr_rfdiv; - -	/* set receiver / transmitter trigger level. -	 * RFDIV is set such way to satisfy requested uartclk value -	 */ -	val = TXTL << 10 | RXTL; -	ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2) -			/ sport->port.uartclk; - -	if(!ufcr_rfdiv) -		ufcr_rfdiv = 1; - -	val |= UFCR_RFDIV_REG(ufcr_rfdiv); +	/* set receiver / transmitter trigger level */ +	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE); +	val |= TXTL << UFCR_TXTL_SHF | RXTL;  	writel(val, sport->port.membase + UFCR); -  	return 0;  } @@ -754,6 +744,7 @@ static int imx_startup(struct uart_port *port)  		}  	} +	spin_lock_irqsave(&sport->port.lock, flags);  	/*  	 * Finally, clear and enable interrupts  	 */ @@ -807,7 +798,6 @@ static int imx_startup(struct uart_port *port)  	/*  	 * Enable modem status interrupts  	 */ -	spin_lock_irqsave(&sport->port.lock,flags);  	imx_enable_ms(&sport->port);  	spin_unlock_irqrestore(&sport->port.lock,flags); @@ -837,10 +827,13 @@ static void imx_shutdown(struct uart_port *port)  {  	struct imx_port *sport = (struct imx_port *)port;  	unsigned long temp; +	unsigned long flags; +	spin_lock_irqsave(&sport->port.lock, flags);  	temp = readl(sport->port.membase + UCR2);  	temp &= ~(UCR2_TXEN);  	writel(temp, sport->port.membase + UCR2); +	spin_unlock_irqrestore(&sport->port.lock, flags);  	if (USE_IRDA(sport)) {  		struct imxuart_platform_data *pdata; @@ -869,12 +862,14 @@ static void imx_shutdown(struct uart_port *port)  	 * Disable all interrupts, port and break condition.  	 */ +	spin_lock_irqsave(&sport->port.lock, flags);  	temp = readl(sport->port.membase + UCR1);  	temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);  	if (USE_IRDA(sport))  		temp &= ~(UCR1_IREN);  	writel(temp, sport->port.membase + UCR1); +	spin_unlock_irqrestore(&sport->port.lock, flags);  }  static void @@ -1217,6 +1212,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count)  	struct imx_port *sport = imx_ports[co->index];  	struct imx_port_ucrs old_ucr;  	unsigned int ucr1; +	unsigned long flags; + +	spin_lock_irqsave(&sport->port.lock, flags);  	/*  	 *	First, save UCR1/2/3 and then disable interrupts @@ -1242,6 +1240,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)  	while (!(readl(sport->port.membase + USR2) & USR2_TXDC));  	imx_port_ucrs_restore(&sport->port, &old_ucr); + +	spin_unlock_irqrestore(&sport->port.lock, flags);  }  /* diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index c7a032a4f0c..d214448b677 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n)  }  /** - * hw_device_state: enables/disables interrupts & starts/stops device (execute - *                  without interruption) + * hw_device_state: enables/disables interrupts (execute without interruption)   * @dma: 0 => disable, !0 => enable and set dma engine   *   * This function returns an error code @@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma)  		/* interrupt, error, port change, reset, sleep/suspend */  		hw_write(ci, OP_USBINTR, ~0,  			     USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); -		hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);  	} else { -		hw_write(ci, OP_USBCMD, USBCMD_RS, 0);  		hw_write(ci, OP_USBINTR, ~0, 0);  	}  	return 0; @@ -774,10 +771,7 @@ __acquires(mEp->lock)  {  	struct ci13xxx_req *mReq, *mReqTemp;  	struct ci13xxx_ep *mEpTemp = mEp; -	int uninitialized_var(retval); - -	if (list_empty(&mEp->qh.queue)) -		return -EINVAL; +	int retval = 0;  	list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,  			queue) { @@ -1420,6 +1414,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)  	return -ENOTSUPP;  } +/* Change Data+ pullup status + * this func is used by usb_gadget_connect/disconnet + */ +static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) +{ +	struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); + +	if (is_on) +		hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); +	else +		hw_write(ci, OP_USBCMD, USBCMD_RS, 0); + +	return 0; +} +  static int ci13xxx_start(struct usb_gadget *gadget,  			 struct usb_gadget_driver *driver);  static int ci13xxx_stop(struct usb_gadget *gadget, @@ -1432,6 +1441,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget,  static const struct usb_gadget_ops usb_gadget_ops = {  	.vbus_session	= ci13xxx_vbus_session,  	.wakeup		= ci13xxx_wakeup, +	.pullup		= ci13xxx_pullup,  	.vbus_draw	= ci13xxx_vbus_draw,  	.udc_start	= ci13xxx_start,  	.udc_stop	= ci13xxx_stop, @@ -1455,7 +1465,12 @@ static int init_eps(struct ci13xxx *ci)  			mEp->ep.name      = mEp->name;  			mEp->ep.ops       = &usb_ep_ops; -			mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; +			/* +			 * for ep0: maxP defined in desc, for other +			 * eps, maxP is set by epautoconfig() called +			 * by gadget layer +			 */ +			mEp->ep.maxpacket = (unsigned short)~0;  			INIT_LIST_HEAD(&mEp->qh.queue);  			mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, @@ -1475,6 +1490,7 @@ static int init_eps(struct ci13xxx *ci)  				else  					ci->ep0in = mEp; +				mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;  				continue;  			} @@ -1484,6 +1500,17 @@ static int init_eps(struct ci13xxx *ci)  	return retval;  } +static void destroy_eps(struct ci13xxx *ci) +{ +	int i; + +	for (i = 0; i < ci->hw_ep_max; i++) { +		struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; + +		dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); +	} +} +  /**   * ci13xxx_start: register a gadget driver   * @gadget: our gadget @@ -1691,7 +1718,7 @@ static int udc_start(struct ci13xxx *ci)  	if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) {  		if (ci->transceiver == NULL) {  			retval = -ENODEV; -			goto free_pools; +			goto destroy_eps;  		}  	} @@ -1729,7 +1756,7 @@ static int udc_start(struct ci13xxx *ci)  remove_trans:  	if (!IS_ERR_OR_NULL(ci->transceiver)) { -		otg_set_peripheral(ci->transceiver->otg, &ci->gadget); +		otg_set_peripheral(ci->transceiver->otg, NULL);  		if (ci->global_phy)  			usb_put_phy(ci->transceiver);  	} @@ -1742,6 +1769,8 @@ unreg_device:  put_transceiver:  	if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)  		usb_put_phy(ci->transceiver); +destroy_eps: +	destroy_eps(ci);  free_pools:  	dma_pool_destroy(ci->td_pool);  free_qh_pool: @@ -1756,18 +1785,12 @@ free_qh_pool:   */  static void udc_stop(struct ci13xxx *ci)  { -	int i; -  	if (ci == NULL)  		return;  	usb_del_gadget_udc(&ci->gadget); -	for (i = 0; i < ci->hw_ep_max; i++) { -		struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; - -		dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); -	} +	destroy_eps(ci);  	dma_pool_destroy(ci->td_pool);  	dma_pool_destroy(ci->qh_pool); diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 65a55abb791..5f0cb417b73 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -109,12 +109,14 @@ static struct usb_driver wdm_driver;  /* return intfdata if we own the interface, else look up intf in the list */  static struct wdm_device *wdm_find_device(struct usb_interface *intf)  { -	struct wdm_device *desc = NULL; +	struct wdm_device *desc;  	spin_lock(&wdm_device_list_lock);  	list_for_each_entry(desc, &wdm_device_list, device_list)  		if (desc->intf == intf) -			break; +			goto found; +	desc = NULL; +found:  	spin_unlock(&wdm_device_list_lock);  	return desc; @@ -122,12 +124,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf)  static struct wdm_device *wdm_find_device_by_minor(int minor)  { -	struct wdm_device *desc = NULL; +	struct wdm_device *desc;  	spin_lock(&wdm_device_list_lock);  	list_for_each_entry(desc, &wdm_device_list, device_list)  		if (desc->intf->minor == minor) -			break; +			goto found; +	desc = NULL; +found:  	spin_unlock(&wdm_device_list_lock);  	return desc; diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index d9569658476..3440812b4a8 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,  	/* print devices for all busses */  	list_for_each_entry(bus, &usb_bus_list, bus_list) {  		/* recurse through all children of the root hub */ -		if (!bus->root_hub) +		if (!bus_to_hcd(bus)->rh_registered)  			continue;  		usb_lock_device(bus->root_hub);  		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index bc84106ac05..75ba2091f9b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1011,10 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd)  	if (retval) {  		dev_err (parent_dev, "can't register root hub for %s, %d\n",  				dev_name(&usb_dev->dev), retval); -	} -	mutex_unlock(&usb_bus_list_lock); - -	if (retval == 0) { +	} else {  		spin_lock_irq (&hcd_root_hub_lock);  		hcd->rh_registered = 1;  		spin_unlock_irq (&hcd_root_hub_lock); @@ -1023,6 +1020,7 @@ static int register_root_hub(struct usb_hcd *hcd)  		if (HCD_DEAD(hcd))  			usb_hc_died (hcd);	/* This time clean up */  	} +	mutex_unlock(&usb_bus_list_lock);  	return retval;  } diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f15501f4c58..e77a8e8eaa2 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {  	{ USB_DEVICE(0x04b4, 0x0526), .driver_info =  			USB_QUIRK_CONFIG_INTF_STRINGS }, +	/* Microchip Joss Optical infrared touchboard device */ +	{ USB_DEVICE(0x04d8, 0x000c), .driver_info = +			USB_QUIRK_CONFIG_INTF_STRINGS }, +  	/* Samsung Android phone modem - ID conflict with SPH-I500 */  	{ USB_DEVICE(0x04e8, 0x6601), .driver_info =  			USB_QUIRK_CONFIG_INTF_STRINGS }, diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a7304..a68ff53124d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -436,16 +436,21 @@ static int __devinit dwc3_probe(struct platform_device *pdev)  		dev_err(dev, "missing IRQ\n");  		return -ENODEV;  	} -	dwc->xhci_resources[1] = *res; +	dwc->xhci_resources[1].start = res->start; +	dwc->xhci_resources[1].end = res->end; +	dwc->xhci_resources[1].flags = res->flags; +	dwc->xhci_resources[1].name = res->name;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		dev_err(dev, "missing memory resource\n");  		return -ENODEV;  	} -	dwc->xhci_resources[0] = *res; +	dwc->xhci_resources[0].start = res->start;  	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +  					DWC3_XHCI_REGS_END; +	dwc->xhci_resources[0].flags = res->flags; +	dwc->xhci_resources[0].name = res->name;  	 /*  	  * Request memory region but exclude xHCI regs, diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9b94886b66e..e4d5ca86b9d 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -720,7 +720,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,  		transferred = min_t(u32, ur->length,  				transfer_size - length);  		memcpy(ur->buf, dwc->ep0_bounce, transferred); -		dwc->ep0_bounced = false;  	} else {  		transferred = ur->length - length;  	} diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 58fdfad96b4..c2813c2b005 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -263,8 +263,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,  	if (req->request.status == -EINPROGRESS)  		req->request.status = status; -	usb_gadget_unmap_request(&dwc->gadget, &req->request, -			req->direction); +	if (dwc->ep0_bounced && dep->number == 0) +		dwc->ep0_bounced = false; +	else +		usb_gadget_unmap_request(&dwc->gadget, &req->request, +				req->direction);  	dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",  			req, dep->name, req->request.actual, @@ -1026,6 +1029,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,  	if (list_empty(&dep->request_list)) {  		dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",  			dep->name); +		dep->flags |= DWC3_EP_PENDING_REQUEST;  		return;  	} @@ -1089,6 +1093,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)  	if (dep->flags & DWC3_EP_PENDING_REQUEST) {  		int	ret; +		/* +		 * If xfernotready is already elapsed and it is a case +		 * of isoc transfer, then issue END TRANSFER, so that +		 * you can receive xfernotready again and can have +		 * notion of current microframe. +		 */ +		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { +			dwc3_stop_active_transfer(dwc, dep->number); +			return 0; +		} +  		ret = __dwc3_gadget_kick_transfer(dep, 0, true);  		if (ret && ret != -EBUSY) {  			struct dwc3	*dwc = dep->dwc; diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index c9e66dfb02e..1e35963bd4e 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -475,8 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep,  	unsigned long	flags;  	if (!_ep || !ep -			|| !desc || ep->ep.desc -			|| _ep->name == ep0name +			|| !desc || _ep->name == ep0name  			|| desc->bDescriptorType != USB_DT_ENDPOINT  			|| (maxpacket = usb_endpoint_maxp(desc)) == 0  			|| maxpacket > ep->maxpacket) { @@ -530,7 +529,6 @@ ok:  	tmp |= AT91_UDP_EPEDS;  	__raw_writel(tmp, ep->creg); -	ep->ep.desc = desc;  	ep->ep.maxpacket = maxpacket;  	/* @@ -1635,7 +1633,6 @@ static int at91_start(struct usb_gadget *gadget,  	udc->driver = driver;  	udc->gadget.dev.driver = &driver->driver;  	udc->gadget.dev.of_node = udc->pdev->dev.of_node; -	dev_set_drvdata(&udc->gadget.dev, &driver->driver);  	udc->enabled = 1;  	udc->selfpowered = 1; @@ -1656,7 +1653,6 @@ static int at91_stop(struct usb_gadget *gadget,  	spin_unlock_irqrestore(&udc->lock, flags);  	udc->gadget.dev.driver = NULL; -	dev_set_drvdata(&udc->gadget.dev, NULL);  	udc->driver = NULL;  	DBG("unbound from %s\n", driver->driver.name); diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index b799106027a..afdbb1cbf5d 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1916,6 +1916,27 @@ done:  	return retval;  } +/* usb 3.0 root hub device descriptor */ +struct { +	struct usb_bos_descriptor bos; +	struct usb_ss_cap_descriptor ss_cap; +} __packed usb3_bos_desc = { + +	.bos = { +		.bLength		= USB_DT_BOS_SIZE, +		.bDescriptorType	= USB_DT_BOS, +		.wTotalLength		= cpu_to_le16(sizeof(usb3_bos_desc)), +		.bNumDeviceCaps		= 1, +	}, +	.ss_cap = { +		.bLength		= USB_DT_USB_SS_CAP_SIZE, +		.bDescriptorType	= USB_DT_DEVICE_CAPABILITY, +		.bDevCapabilityType	= USB_SS_CAP_TYPE, +		.wSpeedSupported	= cpu_to_le16(USB_5GBPS_OPERATION), +		.bFunctionalitySupport	= ilog2(USB_5GBPS_OPERATION), +	}, +}; +  static inline void  ss_hub_descriptor(struct usb_hub_descriptor *desc)  { @@ -2006,6 +2027,18 @@ static int dummy_hub_control(  		else  			hub_descriptor((struct usb_hub_descriptor *) buf);  		break; + +	case DeviceRequest | USB_REQ_GET_DESCRIPTOR: +		if (hcd->speed != HCD_USB3) +			goto error; + +		if ((wValue >> 8) != USB_DT_BOS) +			goto error; + +		memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc)); +		retval = sizeof(usb3_bos_desc); +		break; +  	case GetHubStatus:  		*(__le32 *) buf = cpu_to_le32(0);  		break; @@ -2503,10 +2536,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)  	hs_hcd->has_tt = 1;  	retval = usb_add_hcd(hs_hcd, 0, 0); -	if (retval != 0) { -		usb_put_hcd(hs_hcd); -		return retval; -	} +	if (retval) +		goto put_usb2_hcd;  	if (mod_data.is_super_speed) {  		ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev, @@ -2525,6 +2556,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)  put_usb3_hcd:  	usb_put_hcd(ss_hcd);  dealloc_usb2_hcd: +	usb_remove_hcd(hs_hcd); +put_usb2_hcd:  	usb_put_hcd(hs_hcd);  	the_controller.hs_hcd = the_controller.ss_hcd = NULL;  	return retval; diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 8adc79d1b40..829aba75a6d 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -34,11 +34,15 @@  /* Debugging ****************************************************************/  #ifdef VERBOSE_DEBUG +#ifndef pr_vdebug  #  define pr_vdebug pr_debug +#endif /* pr_vdebug */  #  define ffs_dump_mem(prefix, ptr, len) \  	print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)  #else +#ifndef pr_vdebug  #  define pr_vdebug(...)                 do { } while (0) +#endif /* pr_vdebug */  #  define ffs_dump_mem(prefix, ptr, len) do { } while (0)  #endif /* VERBOSE_DEBUG */ diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index b13e0bb5f5b..0bb617e1dda 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)  	if (hsotg->num_of_eps == 0) {  		dev_err(dev, "wrong number of EPs (zero)\n"); +		ret = -EINVAL;  		goto err_supplies;  	} @@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)  		      GFP_KERNEL);  	if (!eps) {  		dev_err(dev, "cannot get memory\n"); +		ret = -ENOMEM;  		goto err_supplies;  	} @@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)  						     GFP_KERNEL);  	if (!hsotg->ctrl_req) {  		dev_err(dev, "failed to allocate ctrl req\n"); +		ret = -ENOMEM;  		goto err_ep_mem;  	} diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 5b3f5fffea9..da6d479ff9a 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -132,11 +132,15 @@ static unsigned	n_ports;  #ifdef VERBOSE_DEBUG +#ifndef pr_vdebug  #define pr_vdebug(fmt, arg...) \  	pr_debug(fmt, ##arg) +#endif /* pr_vdebug */  #else +#ifndef pr_vdebig  #define pr_vdebug(fmt, arg...) \  	({ if (0) pr_debug(fmt, ##arg); }) +#endif /* pr_vdebug */  #endif  /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 9bc39ca460c..4b66374bdc8 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)  	else {  		qtd = list_entry (qh->qtd_list.next,  				struct ehci_qtd, qtd_list); -		/* first qtd may already be partially processed */ -		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) +		/* +		 * first qtd may already be partially processed. +		 * If we come here during unlink, the QH overlay region +		 * might have reference to the just unlinked qtd. The +		 * qtd is updated in qh_completions(). Update the QH +		 * overlay here. +		 */ +		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { +			qh->hw->hw_qtd_next = qtd->hw_next;  			qtd = NULL; +		}  	}  	if (qtd) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index a665b3eaa74..0bf72f943b0 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -467,7 +467,8 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)  	/* From the GPIO notifying the over-current situation, find  	 * out the corresponding port */  	at91_for_each_port(port) { -		if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { +		if (gpio_is_valid(pdata->overcurrent_pin[port]) && +				gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {  			gpio = pdata->overcurrent_pin[port];  			break;  		} @@ -570,6 +571,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)  	if (pdata) {  		at91_for_each_port(i) { +			/* +			 * do not configure PIO if not in relation with +			 * real USB port on board +			 */ +			if (i >= pdata->ports) { +				pdata->vbus_pin[i] = -EINVAL; +				pdata->overcurrent_pin[i] = -EINVAL; +				break; +			} +  			if (!gpio_is_valid(pdata->vbus_pin[i]))  				continue;  			gpio = pdata->vbus_pin[i]; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index c5e9e4a76f1..966d1484ee7 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -75,7 +75,9 @@  #define	NB_PIF0_PWRDOWN_1	0x01100013  #define USB_INTEL_XUSB2PR      0xD0 +#define USB_INTEL_USB2PRM      0xD4  #define USB_INTEL_USB3_PSSEN   0xD8 +#define USB_INTEL_USB3PRM      0xDC  static struct amd_chipset_info {  	struct pci_dev	*nb_dev; @@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)  		return;  	} -	ports_available = 0xffffffff; +	/* Read USB3PRM, the USB 3.0 Port Routing Mask Register +	 * Indicate the ports that can be changed from OS. +	 */ +	pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, +			&ports_available); + +	dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", +			ports_available); +  	/* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable -	 * Register, to turn on SuperSpeed terminations for all -	 * available ports. +	 * Register, to turn on SuperSpeed terminations for the +	 * switchable ports.  	 */  	pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,  			cpu_to_le32(ports_available)); @@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)  	dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled "  			"under xHCI: 0x%x\n", ports_available); -	ports_available = 0xffffffff; +	/* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register +	 * Indicate the USB 2.0 ports to be controlled by the xHCI host. +	 */ + +	pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, +			&ports_available); + +	dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", +			ports_available); +  	/* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to  	 * switch the USB 2.0 power and data lines over to the xHCI  	 * host. @@ -822,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)  	void __iomem *op_reg_base;  	u32 val;  	int timeout; +	int len = pci_resource_len(pdev, 0);  	if (!mmio_resource_enabled(pdev, 0))  		return; -	base = ioremap_nocache(pci_resource_start(pdev, 0), -				pci_resource_len(pdev, 0)); +	base = ioremap_nocache(pci_resource_start(pdev, 0), len);  	if (base == NULL)  		return; @@ -837,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)  	 */  	ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);  	do { +		if ((ext_cap_offset + sizeof(val)) > len) { +			/* We're reading garbage from the controller */ +			dev_warn(&pdev->dev, +				 "xHCI controller failing to respond"); +			return; +		} +  		if (!ext_cap_offset)  			/* We've reached the end of the extended capabilities */  			goto hc_init; +  		val = readl(base + ext_cap_offset);  		if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)  			break; @@ -870,9 +897,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)  	/* Disable any BIOS SMIs and clear all SMI events*/  	writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); +hc_init:  	if (usb_is_intel_switchable_xhci(pdev))  		usb_enable_xhci_ports(pdev); -hc_init: +  	op_reg_base = base + XHCI_HC_LENGTH(readl(base));  	/* Wait for the host controller to be ready before writing any diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index ef004a5de20..7f69a39163c 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);  static inline void usb_amd_quirk_pll_disable(void) {}  static inline void usb_amd_quirk_pll_enable(void) {}  static inline void usb_amd_dev_put(void) {} +static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}  #endif  /* CONFIG_PCI */  #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */ diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 74bfc868b7a..d5eb357aa5c 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg)  		 * when this bit is set.  		 */  		pls |= USB_PORT_STAT_CONNECTION; +	} else { +		/* +		 * If CAS bit isn't set but the Port is already at +		 * Compliance Mode, fake a connection so the USB core +		 * notices the Compliance state and resets the port. +		 * This resolves an issue generated by the SN65LVPE502CP +		 * in which sometimes the port enters compliance mode +		 * caused by a delay on the host-device negotiation. +		 */ +		if (pls == USB_SS_PORT_LS_COMP_MOD) +			pls |= USB_PORT_STAT_CONNECTION;  	} +  	/* update status field */  	*status |= pls;  } +/* + * Function for Compliance Mode Quirk. + * + * This Function verifies if all xhc USB3 ports have entered U0, if so, + * the compliance mode timer is deleted. A port won't enter + * compliance mode if it has previously entered U0. + */ +void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) +{ +	u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); +	bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); + +	if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) +		return; + +	if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { +		xhci->port_status_u0 |= 1 << wIndex; +		if (xhci->port_status_u0 == all_ports_seen_u0) { +			del_timer_sync(&xhci->comp_mode_recovery_timer); +			xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n"); +			xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n"); +		} +	} +} +  int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  		u16 wIndex, char *buf, u16 wLength)  { @@ -651,6 +688,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  		/* Update Port Link State for super speed ports*/  		if (hcd->speed == HCD_USB3) {  			xhci_hub_report_link_state(&status, temp); +			/* +			 * Verify if all USB3 Ports Have entered U0 already. +			 * Delete Compliance Mode Timer if so. +			 */ +			xhci_del_comp_mod_timer(xhci, temp, wIndex);  		}  		if (bus_state->port_c_suspend & (1 << wIndex))  			status |= 1 << USB_PORT_FEAT_C_SUSPEND; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 689bc18b051..df90fe51b4a 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev)  		goto put_hcd;  	} -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); +	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);  	if (!hcd->regs) {  		dev_dbg(&pdev->dev, "error mapping memory\n");  		ret = -EFAULT; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c59d5b5b6c7..6ece0ed288d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -26,6 +26,7 @@  #include <linux/module.h>  #include <linux/moduleparam.h>  #include <linux/slab.h> +#include <linux/dmi.h>  #include "xhci.h" @@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)  #endif +static void compliance_mode_recovery(unsigned long arg) +{ +	struct xhci_hcd *xhci; +	struct usb_hcd *hcd; +	u32 temp; +	int i; + +	xhci = (struct xhci_hcd *)arg; + +	for (i = 0; i < xhci->num_usb3_ports; i++) { +		temp = xhci_readl(xhci, xhci->usb3_ports[i]); +		if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { +			/* +			 * Compliance Mode Detected. Letting USB Core +			 * handle the Warm Reset +			 */ +			xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", +					i + 1); +			xhci_dbg(xhci, "Attempting Recovery routine!\n"); +			hcd = xhci->shared_hcd; + +			if (hcd->state == HC_STATE_SUSPENDED) +				usb_hcd_resume_root_hub(hcd); + +			usb_hcd_poll_rh_status(hcd); +		} +	} + +	if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) +		mod_timer(&xhci->comp_mode_recovery_timer, +			jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +} + +/* + * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver + * that causes ports behind that hardware to enter compliance mode sometimes. + * The quirk creates a timer that polls every 2 seconds the link state of + * each host controller's port and recovers it by issuing a Warm reset + * if Compliance mode is detected, otherwise the port will become "dead" (no + * device connections or disconnections will be detected anymore). Becasue no + * status event is generated when entering compliance mode (per xhci spec), + * this quirk is needed on systems that have the failing hardware installed. + */ +static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) +{ +	xhci->port_status_u0 = 0; +	init_timer(&xhci->comp_mode_recovery_timer); + +	xhci->comp_mode_recovery_timer.data = (unsigned long) xhci; +	xhci->comp_mode_recovery_timer.function = compliance_mode_recovery; +	xhci->comp_mode_recovery_timer.expires = jiffies + +			msecs_to_jiffies(COMP_MODE_RCVRY_MSECS); + +	set_timer_slack(&xhci->comp_mode_recovery_timer, +			msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +	add_timer(&xhci->comp_mode_recovery_timer); +	xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); +} + +/* + * This function identifies the systems that have installed the SN65LVPE502CP + * USB3.0 re-driver and that need the Compliance Mode Quirk. + * Systems: + * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 + */ +static bool compliance_mode_recovery_timer_quirk_check(void) +{ +	const char *dmi_product_name, *dmi_sys_vendor; + +	dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); +	dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + +	if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) +		return false; + +	if (strstr(dmi_product_name, "Z420") || +			strstr(dmi_product_name, "Z620") || +			strstr(dmi_product_name, "Z820")) +		return true; + +	return false; +} + +static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) +{ +	return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1)); +} + +  /*   * Initialize memory for HCD and xHC (one-time init).   * @@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd)  	retval = xhci_mem_init(xhci, GFP_KERNEL);  	xhci_dbg(xhci, "Finished xhci_init\n"); +	/* Initializing Compliance Mode Recovery Data If Needed */ +	if (compliance_mode_recovery_timer_quirk_check()) { +		xhci->quirks |= XHCI_COMP_MODE_QUIRK; +		compliance_mode_recovery_timer_init(xhci); +	} +  	return retval;  } @@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd)  	del_timer_sync(&xhci->event_ring_timer);  #endif +	/* Deleting Compliance Mode Recovery Timer */ +	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && +			(!(xhci_all_ports_seen_u0(xhci)))) +		del_timer_sync(&xhci->comp_mode_recovery_timer); +  	if (xhci->quirks & XHCI_AMD_PLL_FIX)  		usb_amd_dev_put(); @@ -659,7 +760,7 @@ void xhci_shutdown(struct usb_hcd *hcd)  {  	struct xhci_hcd *xhci = hcd_to_xhci(hcd); -	if (xhci->quirks && XHCI_SPURIOUS_REBOOT) +	if (xhci->quirks & XHCI_SPURIOUS_REBOOT)  		usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));  	spin_lock_irq(&xhci->lock); @@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci)  	}  	spin_unlock_irq(&xhci->lock); +	/* +	 * Deleting Compliance Mode Recovery Timer because the xHCI Host +	 * is about to be suspended. +	 */ +	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && +			(!(xhci_all_ports_seen_u0(xhci)))) { +		del_timer_sync(&xhci->comp_mode_recovery_timer); +		xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); +	} +  	/* step 5: remove core well power */  	/* synchronize irq when using MSI-X */  	xhci_msix_sync_irqs(xhci); @@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)  		usb_hcd_resume_root_hub(hcd);  		usb_hcd_resume_root_hub(xhci->shared_hcd);  	} + +	/* +	 * If system is subject to the Quirk, Compliance Mode Timer needs to +	 * be re-initialized Always after a system resume. Ports are subject +	 * to suffer the Compliance Mode issue again. It doesn't matter if +	 * ports have entered previously to U0 before system's suspension. +	 */ +	if (xhci->quirks & XHCI_COMP_MODE_QUIRK) +		compliance_mode_recovery_timer_init(xhci); +  	return retval;  }  #endif	/* CONFIG_PM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c713256297a..1a05908c667 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1495,6 +1495,7 @@ struct xhci_hcd {  #define XHCI_LPM_SUPPORT	(1 << 11)  #define XHCI_INTEL_HOST		(1 << 12)  #define XHCI_SPURIOUS_REBOOT	(1 << 13) +#define XHCI_COMP_MODE_QUIRK	(1 << 14)  	unsigned int		num_active_eps;  	unsigned int		limit_active_eps;  	/* There are two roothubs to keep track of bus suspend info for */ @@ -1511,6 +1512,11 @@ struct xhci_hcd {  	unsigned		sw_lpm_support:1;  	/* support xHCI 1.0 spec USB2 hardware LPM */  	unsigned		hw_lpm_support:1; +	/* Compliance Mode Recovery Data */ +	struct timer_list	comp_mode_recovery_timer; +	u32			port_status_u0; +/* Compliance Mode Timer Triggered every 2 seconds */ +#define COMP_MODE_RCVRY_MSECS 2000  };  /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 4bb717d0bd4..1ae378d5fc6 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2049,7 +2049,7 @@ static int musb_urb_enqueue(  	 * we only have work to do in the former case.  	 */  	spin_lock_irqsave(&musb->lock, flags); -	if (hep->hcpriv) { +	if (hep->hcpriv || !next_urb(qh)) {  		/* some concurrent activity submitted another urb to hep...  		 * odd, rare, error prone, but legal.  		 */ diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 57a608584e1..c1be687e00e 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base)  	struct platform_device *pdev = to_platform_device(dev);  	int irq = platform_get_irq_byname(pdev, "dma"); -	if (irq == 0) { +	if (irq <= 0) {  		dev_err(dev, "No DMA interrupt line!\n");  		return NULL;  	} diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1a1bd9cf40c..34162544237 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev)  	ret = platform_device_add(musb);  	if (ret) {  		dev_err(&pdev->dev, "failed to register musb device\n"); -		goto err1; +		goto err2;  	}  	return 0; diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index ecd173032fd..143c4e9e1be 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)  	    usbhs_pipe_is_dcp(pipe))  		goto usbhsf_pio_prepare_push; -	if (len % 4) /* 32bit alignment */ +	if (len & 0x7) /* 8byte alignment */  		goto usbhsf_pio_prepare_push;  	if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ @@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)  	/* use PIO if packet is less than pio_dma_border */  	len = usbhsf_fifo_rcv_len(priv, fifo);  	len = min(pkt->length - pkt->actual, len); -	if (len % 4) /* 32bit alignment */ +	if (len & 0x7) /* 8byte alignment */  		goto usbhsf_pio_prepare_pop_unselect;  	if (len < usbhs_get_dparam(priv, pio_dma_border)) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5620db6469e..f906b3aec21 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -704,6 +704,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) },  	{ USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },  	{ USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },  	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, @@ -804,13 +805,32 @@ static struct usb_device_id id_table_combined [] = {  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, -	{ USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, +					USB_CLASS_VENDOR_SPEC, +					USB_SUBCLASS_VENDOR_SPEC, 0x00) },  	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },  	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },  	{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, +	{ USB_DEVICE(FTDI_VID, PI_C865_PID) }, +	{ USB_DEVICE(FTDI_VID, PI_C857_PID) }, +	{ USB_DEVICE(PI_VID, PI_C866_PID) }, +	{ USB_DEVICE(PI_VID, PI_C663_PID) }, +	{ USB_DEVICE(PI_VID, PI_C725_PID) }, +	{ USB_DEVICE(PI_VID, PI_E517_PID) }, +	{ USB_DEVICE(PI_VID, PI_C863_PID) },  	{ USB_DEVICE(PI_VID, PI_E861_PID) }, +	{ USB_DEVICE(PI_VID, PI_C867_PID) }, +	{ USB_DEVICE(PI_VID, PI_E609_PID) }, +	{ USB_DEVICE(PI_VID, PI_E709_PID) }, +	{ USB_DEVICE(PI_VID, PI_100F_PID) }, +	{ USB_DEVICE(PI_VID, PI_1011_PID) }, +	{ USB_DEVICE(PI_VID, PI_1012_PID) }, +	{ USB_DEVICE(PI_VID, PI_1013_PID) }, +	{ USB_DEVICE(PI_VID, PI_1014_PID) }, +	{ USB_DEVICE(PI_VID, PI_1015_PID) }, +	{ USB_DEVICE(PI_VID, PI_1016_PID) },  	{ USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },  	{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },  	{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5dd96ca6c38..41fe5826100 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -75,6 +75,9 @@  #define FTDI_OPENDCC_GATEWAY_PID	0xBFDB  #define FTDI_OPENDCC_GBM_PID	0xBFDC +/* NZR SEM 16+ USB (http://www.nzr.de) */ +#define FTDI_NZR_SEM_USB_PID	0xC1E0	/* NZR SEM-LOG16+ */ +  /*   * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)   */ @@ -539,7 +542,10 @@  /*   * Microchip Technology, Inc.   * - * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are + * used by single function CDC ACM class based firmware demo + * applications.  The VID/PID has also been used in firmware + * emulating FTDI serial chips by:   * Hornby Elite - Digital Command Control Console   * http://www.hornby.com/hornby-dcc/controllers/   */ @@ -791,8 +797,27 @@   * Physik Instrumente   * http://www.physikinstrumente.com/en/products/   */ +/* These two devices use the VID of FTDI */ +#define PI_C865_PID	0xe0a0  /* PI C-865 Piezomotor Controller */ +#define PI_C857_PID	0xe0a1  /* PI Encoder Trigger Box */ +  #define PI_VID              0x1a72  /* Vendor ID */ -#define PI_E861_PID         0x1008  /* E-861 piezo controller USB connection */ +#define PI_C866_PID	0x1000  /* PI C-866 Piezomotor Controller */ +#define PI_C663_PID	0x1001  /* PI C-663 Mercury-Step */ +#define PI_C725_PID	0x1002  /* PI C-725 Piezomotor Controller */ +#define PI_E517_PID	0x1005  /* PI E-517 Digital Piezo Controller Operation Module */ +#define PI_C863_PID	0x1007  /* PI C-863 */ +#define PI_E861_PID	0x1008  /* PI E-861 Piezomotor Controller */ +#define PI_C867_PID	0x1009  /* PI C-867 Piezomotor Controller */ +#define PI_E609_PID	0x100D  /* PI E-609 Digital Piezo Controller */ +#define PI_E709_PID	0x100E  /* PI E-709 Digital Piezo Controller */ +#define PI_100F_PID	0x100F  /* PI Digital Piezo Controller */ +#define PI_1011_PID	0x1011  /* PI Digital Piezo Controller */ +#define PI_1012_PID	0x1012  /* PI Motion Controller */ +#define PI_1013_PID	0x1013  /* PI Motion Controller */ +#define PI_1014_PID	0x1014  /* PI Device */ +#define PI_1015_PID	0x1015  /* PI Device */ +#define PI_1016_PID	0x1016  /* PI Digital Servo Module */  /*   * Kondo Kagaku Co.Ltd. diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index cc40f47ecea..5ce88d1bc6f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = {  	{ 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, 0x1018, 0xff, 0xff, 0xff), -	  .driver_info = (kernel_ulong_t)&net_intf3_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) }, @@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = {  	 .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),  	 .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, +	{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, +  	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },  	{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },  	{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 211a4920b88..d8dedc7d391 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -76,9 +76,24 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)  			schedule_work(&virqfd->inject);  	} -	if (flags & POLLHUP) -		/* The eventfd is closing, detach from VFIO */ -		virqfd_deactivate(virqfd); +	if (flags & POLLHUP) { +		unsigned long flags; +		spin_lock_irqsave(&virqfd->vdev->irqlock, flags); + +		/* +		 * The eventfd is closing, if the virqfd has not yet been +		 * queued for release, as determined by testing whether the +		 * vdev pointer to it is still valid, queue it now.  As +		 * with kvm irqfds, we know we won't race against the virqfd +		 * going away because we hold wqh->lock to get here. +		 */ +		if (*(virqfd->pvirqfd) == virqfd) { +			*(virqfd->pvirqfd) = NULL; +			virqfd_deactivate(virqfd); +		} + +		spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags); +	}  	return 0;  } @@ -93,7 +108,6 @@ static void virqfd_ptable_queue_proc(struct file *file,  static void virqfd_shutdown(struct work_struct *work)  {  	struct virqfd *virqfd = container_of(work, struct virqfd, shutdown); -	struct virqfd **pvirqfd = virqfd->pvirqfd;  	u64 cnt;  	eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt); @@ -101,7 +115,6 @@ static void virqfd_shutdown(struct work_struct *work)  	eventfd_ctx_put(virqfd->eventfd);  	kfree(virqfd); -	*pvirqfd = NULL;  }  static void virqfd_inject(struct work_struct *work) @@ -122,15 +135,11 @@ static int virqfd_enable(struct vfio_pci_device *vdev,  	int ret = 0;  	unsigned int events; -	if (*pvirqfd) -		return -EBUSY; -  	virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);  	if (!virqfd)  		return -ENOMEM;  	virqfd->pvirqfd = pvirqfd; -	*pvirqfd = virqfd;  	virqfd->vdev = vdev;  	virqfd->handler = handler;  	virqfd->thread = thread; @@ -154,6 +163,23 @@ static int virqfd_enable(struct vfio_pci_device *vdev,  	virqfd->eventfd = ctx;  	/* +	 * virqfds can be released by closing the eventfd or directly +	 * through ioctl.  These are both done through a workqueue, so +	 * we update the pointer to the virqfd under lock to avoid +	 * pushing multiple jobs to release the same virqfd. +	 */ +	spin_lock_irq(&vdev->irqlock); + +	if (*pvirqfd) { +		spin_unlock_irq(&vdev->irqlock); +		ret = -EBUSY; +		goto fail; +	} +	*pvirqfd = virqfd; + +	spin_unlock_irq(&vdev->irqlock); + +	/*  	 * Install our own custom wake-up handling so we are notified via  	 * a callback whenever someone signals the underlying eventfd.  	 */ @@ -187,19 +213,29 @@ fail:  		fput(file);  	kfree(virqfd); -	*pvirqfd = NULL;  	return ret;  } -static void virqfd_disable(struct virqfd *virqfd) +static void virqfd_disable(struct vfio_pci_device *vdev, +			   struct virqfd **pvirqfd)  { -	if (!virqfd) -		return; +	unsigned long flags; + +	spin_lock_irqsave(&vdev->irqlock, flags); + +	if (*pvirqfd) { +		virqfd_deactivate(*pvirqfd); +		*pvirqfd = NULL; +	} -	virqfd_deactivate(virqfd); +	spin_unlock_irqrestore(&vdev->irqlock, flags); -	/* Block until we know all outstanding shutdown jobs have completed. */ +	/* +	 * Block until we know all outstanding shutdown jobs have completed. +	 * Even if we don't queue the job, flush the wq to be sure it's +	 * been released. +	 */  	flush_workqueue(vfio_irqfd_cleanup_wq);  } @@ -392,8 +428,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)  static void vfio_intx_disable(struct vfio_pci_device *vdev)  {  	vfio_intx_set_signal(vdev, -1); -	virqfd_disable(vdev->ctx[0].unmask); -	virqfd_disable(vdev->ctx[0].mask); +	virqfd_disable(vdev, &vdev->ctx[0].unmask); +	virqfd_disable(vdev, &vdev->ctx[0].mask);  	vdev->irq_type = VFIO_PCI_NUM_IRQS;  	vdev->num_ctx = 0;  	kfree(vdev->ctx); @@ -539,8 +575,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)  	vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);  	for (i = 0; i < vdev->num_ctx; i++) { -		virqfd_disable(vdev->ctx[i].unmask); -		virqfd_disable(vdev->ctx[i].mask); +		virqfd_disable(vdev, &vdev->ctx[i].unmask); +		virqfd_disable(vdev, &vdev->ctx[i].mask);  	}  	if (msix) { @@ -577,7 +613,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,  					     vfio_send_intx_eventfd, NULL,  					     &vdev->ctx[0].unmask, fd); -		virqfd_disable(vdev->ctx[0].unmask); +		virqfd_disable(vdev, &vdev->ctx[0].unmask);  	}  	return 0; diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 1eff743ec49..ae60406ea8a 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -814,6 +814,9 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,  	hpwdt_timer_reg = pci_mem_addr + 0x70;  	hpwdt_timer_con = pci_mem_addr + 0x72; +	/* Make sure that timer is disabled until /dev/watchdog is opened */ +	hpwdt_stop(); +  	/* Make sure that we have a valid soft_margin */  	if (hpwdt_change_timer(soft_margin))  		hpwdt_change_timer(DEFAULT_MARGIN); diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 6aa46a90ff0..3796434991f 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -128,11 +128,12 @@ EXPORT_SYMBOL_GPL(watchdog_register_device);  void watchdog_unregister_device(struct watchdog_device *wdd)  {  	int ret; -	int devno = wdd->cdev.dev; +	int devno;  	if (wdd == NULL)  		return; +	devno = wdd->cdev.dev;  	ret = watchdog_dev_unregister(wdd);  	if (ret)  		pr_err("error unregistering /dev/watchdog (err=%d)\n", ret); diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 1ffd03bf8e1..7f124160848 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -314,8 +314,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)  		}  	} -	err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset, -				pages, true); +	err = gnttab_unmap_refs(map->unmap_ops + offset, +			use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset, +			pages);  	if (err)  		return err; diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 0bfc1ef1125..006726688ba 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -870,7 +870,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,  EXPORT_SYMBOL_GPL(gnttab_map_refs);  int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, -		      struct page **pages, unsigned int count, bool clear_pte) +		      struct gnttab_map_grant_ref *kmap_ops, +		      struct page **pages, unsigned int count)  {  	int i, ret;  	bool lazy = false; @@ -888,7 +889,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,  	}  	for (i = 0; i < count; i++) { -		ret = m2p_remove_override(pages[i], clear_pte); +		ret = m2p_remove_override(pages[i], kmap_ops ? +				       &kmap_ops[i] : NULL);  		if (ret)  			return ret;  	}  |