diff options
Diffstat (limited to 'drivers')
273 files changed, 3589 insertions, 1778 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 34f1e1064db..f42a03029b7 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_SFI)		+= sfi/  obj-$(CONFIG_PNP)		+= pnp/  obj-$(CONFIG_ARM_AMBA)		+= amba/ +obj-$(CONFIG_VIRTIO)		+= virtio/  obj-$(CONFIG_XEN)		+= xen/  # regulators early, since some subsystems rely on them to initialize @@ -108,7 +109,6 @@ obj-$(CONFIG_PPC_PS3)		+= ps3/  obj-$(CONFIG_OF)		+= of/  obj-$(CONFIG_SSB)		+= ssb/  obj-$(CONFIG_VHOST_NET)		+= vhost/ -obj-$(CONFIG_VIRTIO)		+= virtio/  obj-$(CONFIG_VLYNQ)		+= vlynq/  obj-$(CONFIG_STAGING)		+= staging/  obj-y				+= platform/ diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 19dacfd4316..62122134693 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -31,7 +31,7 @@  #include <acpi/acpi_bus.h>  #include <acpi/acpi_drivers.h> -#define ACPI_PROCESSOR_AGGREGATOR_CLASS	"processor_aggregator" +#define ACPI_PROCESSOR_AGGREGATOR_CLASS	"acpi_pad"  #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"  #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80  static DEFINE_MUTEX(isolated_cpus_lock); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 37132dc2da0..743576bf1bd 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -527,7 +527,7 @@ int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id,  	if (!event_is_open)  		return 0; -	event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); +	event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);  	if (!event)  		return -ENOMEM; diff --git a/drivers/acpi/hest.c b/drivers/acpi/hest.c index 4bb18c980ac..1c527a19287 100644 --- a/drivers/acpi/hest.c +++ b/drivers/acpi/hest.c @@ -123,6 +123,10 @@ int acpi_hest_firmware_first_pci(struct pci_dev *pci)  {  	acpi_status status = AE_NOT_FOUND;  	struct acpi_table_header *hest = NULL; + +	if (acpi_disabled) +		return 0; +  	status = acpi_get_table(ACPI_SIG_HEST, 1, &hest);  	if (ACPI_SUCCESS(status)) { diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b0a71ecee68..e4804fb05e2 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -401,11 +401,13 @@ int acpi_pci_irq_enable(struct pci_dev *dev)  	 * driver reported one, then use it. Exit in any case.  	 */  	if (gsi < 0) { +		u32 dev_gsi;  		dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));  		/* Interrupt Line values above 0xF are forbidden */ -		if (dev->irq > 0 && (dev->irq <= 0xF)) { -			printk(" - using IRQ %d\n", dev->irq); -			acpi_register_gsi(&dev->dev, dev->irq, +		if (dev->irq > 0 && (dev->irq <= 0xF) && +		    (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { +			printk(" - using ISA IRQ %d\n", dev->irq); +			acpi_register_gsi(&dev->dev, dev_gsi,  					  ACPI_LEVEL_SENSITIVE,  					  ACPI_ACTIVE_LOW);  			return 0; diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index e8c32a49f14..66f67293341 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -35,7 +35,7 @@  #define ACPI_POWER_METER_NAME		"power_meter"  ACPI_MODULE_NAME(ACPI_POWER_METER_NAME);  #define ACPI_POWER_METER_DEVICE_NAME	"Power Meter" -#define ACPI_POWER_METER_CLASS		"power_meter_resource" +#define ACPI_POWER_METER_CLASS		"pwr_meter_resource"  #define NUM_SENSORS			17 diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 36704b887cc..f8be23b6c12 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -18,7 +18,7 @@  #define PREFIX "ACPI: " -#define ACPI_SMB_HC_CLASS	"smbus_host_controller" +#define ACPI_SMB_HC_CLASS	"smbus_host_ctl"  #define ACPI_SMB_HC_DEVICE_NAME	"ACPI SMBus HC"  struct acpi_smb_hc { diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index f74834a544f..baa76bbf244 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -450,6 +450,38 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {  		},  	},  	{ +	.callback = init_set_sci_en_on_resume, +	.ident = "Lenovo ThinkPad T410", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), +		}, +	}, +	{ +	.callback = init_set_sci_en_on_resume, +	.ident = "Lenovo ThinkPad T510", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), +		}, +	}, +	{ +	.callback = init_set_sci_en_on_resume, +	.ident = "Lenovo ThinkPad W510", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), +		}, +	}, +	{ +	.callback = init_set_sci_en_on_resume, +	.ident = "Lenovo ThinkPad X201[s]", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), +		}, +	}, +	{  	.callback = init_old_suspend_ordering,  	.ident = "Panasonic CF51-2L",  	.matches = { @@ -458,6 +490,30 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {  		DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),  		},  	}, +	{ +	.callback = init_set_sci_en_on_resume, +	.ident = "Dell Studio 1558", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +		DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"), +		}, +	}, +	{ +	.callback = init_set_sci_en_on_resume, +	.ident = "Dell Studio 1557", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +		DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), +		}, +	}, +	{ +	.callback = init_set_sci_en_on_resume, +	.ident = "Dell Studio 1555", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +		DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"), +		}, +	},  	{},  };  #endif /* CONFIG_SUSPEND */ diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 4164dd244dd..d94b8f0bd74 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -424,7 +424,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {  	PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),  	PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),  	PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), -	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x3e520e17), +	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),  	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),  	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),  	PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b), @@ -446,7 +446,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), -	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x9351e59d), +	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),  	PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),  	PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index 8ad4ffea692..6e6b6a11b3c 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c @@ -80,20 +80,6 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)  }  EXPORT_SYMBOL_GPL(iommu_detach_device); -int iommu_map_range(struct iommu_domain *domain, unsigned long iova, -		    phys_addr_t paddr, size_t size, int prot) -{ -	return iommu_ops->map(domain, iova, paddr, size, prot); -} -EXPORT_SYMBOL_GPL(iommu_map_range); - -void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, -		      size_t size) -{ -	iommu_ops->unmap(domain, iova, size); -} -EXPORT_SYMBOL_GPL(iommu_unmap_range); -  phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,  			       unsigned long iova)  { @@ -107,3 +93,32 @@ int iommu_domain_has_cap(struct iommu_domain *domain,  	return iommu_ops->domain_has_cap(domain, cap);  }  EXPORT_SYMBOL_GPL(iommu_domain_has_cap); + +int iommu_map(struct iommu_domain *domain, unsigned long iova, +	      phys_addr_t paddr, int gfp_order, int prot) +{ +	unsigned long invalid_mask; +	size_t size; + +	size         = 0x1000UL << gfp_order; +	invalid_mask = size - 1; + +	BUG_ON((iova | paddr) & invalid_mask); + +	return iommu_ops->map(domain, iova, paddr, gfp_order, prot); +} +EXPORT_SYMBOL_GPL(iommu_map); + +int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) +{ +	unsigned long invalid_mask; +	size_t size; + +	size         = 0x1000UL << gfp_order; +	invalid_mask = size - 1; + +	BUG_ON(iova & invalid_mask); + +	return iommu_ops->unmap(domain, iova, gfp_order); +} +EXPORT_SYMBOL_GPL(iommu_unmap); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 81865ee2eff..765bcf0df3b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(platform_device_alloc);   * released.   */  int platform_device_add_resources(struct platform_device *pdev, -				  struct resource *res, unsigned int num) +				  const struct resource *res, unsigned int num)  {  	struct resource *r; @@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister);   */  struct platform_device *platform_device_register_simple(const char *name,  							int id, -							struct resource *res, +							const struct resource *res,  							unsigned int num)  {  	struct platform_device *pdev; diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 0182a22c423..832798aa14f 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -66,6 +66,7 @@  #include <linux/blkdev.h>  #include <linux/elevator.h>  #include <linux/interrupt.h> +#include <linux/platform_device.h>  #include <asm/setup.h>  #include <asm/uaccess.h> @@ -1696,34 +1697,18 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)  	return get_disk(unit[drive].gendisk);  } -static int __init amiga_floppy_init(void) +static int __init amiga_floppy_probe(struct platform_device *pdev)  {  	int i, ret; -	if (!MACH_IS_AMIGA) -		return -ENODEV; - -	if (!AMIGAHW_PRESENT(AMI_FLOPPY)) -		return -ENODEV; -  	if (register_blkdev(FLOPPY_MAJOR,"fd"))  		return -EBUSY; -	/* -	 *  We request DSKPTR, DSKLEN and DSKDATA only, because the other -	 *  floppy registers are too spreaded over the custom register space -	 */ -	ret = -EBUSY; -	if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) { -		printk("fd: cannot get floppy registers\n"); -		goto out_blkdev; -	} -  	ret = -ENOMEM;  	if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) ==  	    NULL) {  		printk("fd: cannot get chip mem buffer\n"); -		goto out_memregion; +		goto out_blkdev;  	}  	ret = -EBUSY; @@ -1792,18 +1777,13 @@ out_irq2:  	free_irq(IRQ_AMIGA_DSKBLK, NULL);  out_irq:  	amiga_chip_free(raw_buf); -out_memregion: -	release_mem_region(CUSTOM_PHYSADDR+0x20, 8);  out_blkdev:  	unregister_blkdev(FLOPPY_MAJOR,"fd");  	return ret;  } -module_init(amiga_floppy_init); -#ifdef MODULE -  #if 0 /* not safe to unload */ -void cleanup_module(void) +static int __exit amiga_floppy_remove(struct platform_device *pdev)  {  	int i; @@ -1820,12 +1800,25 @@ void cleanup_module(void)  	custom.dmacon = DMAF_DISK; /* disable DMA */  	amiga_chip_free(raw_buf);  	blk_cleanup_queue(floppy_queue); -	release_mem_region(CUSTOM_PHYSADDR+0x20, 8);  	unregister_blkdev(FLOPPY_MAJOR, "fd");  }  #endif -#else +static struct platform_driver amiga_floppy_driver = { +	.driver   = { +		.name	= "amiga-floppy", +		.owner	= THIS_MODULE, +	}, +}; + +static int __init amiga_floppy_init(void) +{ +	return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe); +} + +module_init(amiga_floppy_init); + +#ifndef MODULE  static int __init amiga_floppy_setup (char *str)  {  	int n; @@ -1840,3 +1833,5 @@ static int __init amiga_floppy_setup (char *str)  __setup("floppy=", amiga_floppy_setup);  #endif + +MODULE_ALIAS("platform:amiga-floppy"); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 67e0fc54224..93d1f9b469d 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1695,6 +1695,7 @@ int drbd_send_protocol(struct drbd_conf *mdev)  			cf |= CF_DRY_RUN;  		else {  			dev_err(DEV, "--dry-run is not supported by peer"); +			kfree(p);  			return 0;  		}  	} diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index ed9f1de24a7..3f096e7959b 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -899,7 +899,8 @@ retry:  	drbd_thread_start(&mdev->asender); -	drbd_send_protocol(mdev); +	if (!drbd_send_protocol(mdev)) +		return -1;  	drbd_send_sync_param(mdev, &mdev->sync_conf);  	drbd_send_sizes(mdev, 0);  	drbd_send_uuids(mdev); diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 44bf6d11197..d48a1dfd7b2 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -235,7 +235,7 @@ void drbd_endio_pri(struct bio *bio, int error)  	if (unlikely(error)) {  		what = (bio_data_dir(bio) == WRITE)  			? write_completed_with_error -			: (bio_rw(bio) == READA) +			: (bio_rw(bio) == READ)  			  ? read_completed_with_error  			  : read_ahead_completed_with_error;  	} else diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 034e6dfc878..81c78b3ce2d 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -164,12 +164,12 @@ unsigned long read_timer(void)  	unsigned long t, flags;  	int i; -	spin_lock_irqsave(&i8253_lock, flags); +	raw_spin_lock_irqsave(&i8253_lock, flags);  	t = jiffies * 11932;  	outb_p(0, 0x43);  	i = inb_p(0x40);  	i |= inb(0x40) << 8; -	spin_unlock_irqrestore(&i8253_lock, flags); +	raw_spin_unlock_irqrestore(&i8253_lock, flags);  	return(t - i);  }  #endif diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index ddf19425245..8a549db2aa7 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -48,6 +48,7 @@  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> +#include <linux/compat.h>  #include <linux/kthread.h>  #include <linux/errno.h>  #include <linux/spinlock.h> @@ -2984,7 +2985,7 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)  	mutex_unlock(&ctl_mutex);  } -static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  {  	void __user *argp = (void __user *)arg;  	struct pkt_ctrl_command ctrl_cmd; @@ -3021,10 +3022,20 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm  	return ret;  } +#ifdef CONFIG_COMPAT +static long pkt_ctl_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ +	return pkt_ctl_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif  static const struct file_operations pkt_ctl_fops = { -	.ioctl	 = pkt_ctl_ioctl, -	.owner	 = THIS_MODULE, +	.open		= nonseekable_open, +	.unlocked_ioctl	= pkt_ctl_ioctl, +#ifdef CONFIG_COMPAT +	.compat_ioctl	= pkt_ctl_compat_ioctl, +#endif +	.owner		= THIS_MODULE,  };  static struct miscdevice pkt_misc = { diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 0fa2e4a0835..c1ab303455c 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -879,8 +879,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)  	if (tport == NULL)  		return -ENODEV;  	port = container_of(tport, struct isi_port, port); -	card = &isi_card[BOARD(tty->index)]; +	tty->driver_data = port;  	return tty_port_open(tport, tty, filp);  } @@ -936,7 +936,12 @@ static void isicom_shutdown(struct tty_port *port)  static void isicom_close(struct tty_struct *tty, struct file *filp)  {  	struct isi_port *ip = tty->driver_data; -	struct tty_port *port = &ip->port; +	struct tty_port *port; + +	if (ip == NULL) +		return; + +	port = &ip->port;  	if (isicom_paranoia_check(ip, tty->name, "isicom_close"))  		return;  	tty_port_close(port, tty, filp); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 4cd6c527ee4..4e395c956a0 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -827,6 +827,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp)  		return -ENODEV;  	if (portp->devnr < 1)  		return -ENODEV; + +	tty->driver_data = portp;  	return tty_port_open(&portp->port, tty, filp);  } diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 47023053ee8..d2692d443f7 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -1011,6 +1011,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)  	if (!info->ioaddr)  		return -ENODEV; +	tty->driver_data = info;  	return tty_port_open(&info->port, tty, filp);  } @@ -1074,7 +1075,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)  	struct mxser_port *info = tty->driver_data;  	struct tty_port *port = &info->port; -	if (tty->index == MXSER_PORTS) +	if (tty->index == MXSER_PORTS || info == NULL)  		return;  	if (tty_port_close_start(port, tty, filp) == 0)  		return; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 0a8d1e56c99..b02332a5412 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -909,6 +909,7 @@ static int rc_open(struct tty_struct *tty, struct file *filp)  	if (error)  		return error; +	tty->driver_data = port;  	return tty_port_open(&port->port, tty, filp);  } diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 8dfd24721a8..78a62ebe75c 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -627,7 +627,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)  	char data;  	int char_count;  	int save_cnt; -	int len;  	/* determine the channel and change to that context */  	channel = (u_short) (base_addr[CyLICR] >> 2); @@ -1528,7 +1527,6 @@ static int  cy_ioctl(struct tty_struct *tty, struct file *file,  	 unsigned int cmd, unsigned long arg)  { -	unsigned long val;  	struct cyclades_port *info = tty->driver_data;  	int ret_val = 0;  	void __user *argp = (void __user *)arg; diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 0e511d61f54..6049fd73192 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -724,7 +724,6 @@ static int stl_open(struct tty_struct *tty, struct file *filp)  {  	struct stlport	*portp;  	struct stlbrd	*brdp; -	struct tty_port *port;  	unsigned int	minordev, brdnr, panelnr;  	int		portnr; @@ -754,7 +753,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)  	portp = brdp->panels[panelnr]->ports[portnr];  	if (portp == NULL)  		return -ENODEV; -	port = &portp->port; + +	tty->driver_data = portp;  	return tty_port_open(&portp->port, tty, filp);  } @@ -841,7 +841,8 @@ static void stl_close(struct tty_struct *tty, struct file *filp)  	pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);  	portp = tty->driver_data; -	BUG_ON(portp == NULL); +	if(portp == NULL) +		return;  	tty_port_close(&portp->port, tty, filp);  } diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 59de2525d30..d4e8b213a46 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -289,7 +289,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = {  static void sysrq_ftrace_dump(int key, struct tty_struct *tty)  { -	ftrace_dump(); +	ftrace_dump(DUMP_ALL);  }  static struct sysrq_key_op sysrq_ftrace_dump_op = {  	.handler	= sysrq_ftrace_dump, diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6da962c9b21..d71f0fc34b4 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1875,6 +1875,7 @@ got_driver:  		 */  		if (filp->f_op == &hung_up_tty_fops)  			filp->f_op = &tty_fops; +		unlock_kernel();  		goto retry_open;  	}  	unlock_kernel(); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 75d293eeb3e..063b2184caf 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -662,32 +662,20 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)  	return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);  } -#define define_one_ro(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0444, show_##_name, NULL) - -#define define_one_ro0400(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0400, show_##_name, NULL) - -#define define_one_rw(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -define_one_ro0400(cpuinfo_cur_freq); -define_one_ro(cpuinfo_min_freq); -define_one_ro(cpuinfo_max_freq); -define_one_ro(cpuinfo_transition_latency); -define_one_ro(scaling_available_governors); -define_one_ro(scaling_driver); -define_one_ro(scaling_cur_freq); -define_one_ro(bios_limit); -define_one_ro(related_cpus); -define_one_ro(affected_cpus); -define_one_rw(scaling_min_freq); -define_one_rw(scaling_max_freq); -define_one_rw(scaling_governor); -define_one_rw(scaling_setspeed); +cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); +cpufreq_freq_attr_ro(cpuinfo_min_freq); +cpufreq_freq_attr_ro(cpuinfo_max_freq); +cpufreq_freq_attr_ro(cpuinfo_transition_latency); +cpufreq_freq_attr_ro(scaling_available_governors); +cpufreq_freq_attr_ro(scaling_driver); +cpufreq_freq_attr_ro(scaling_cur_freq); +cpufreq_freq_attr_ro(bios_limit); +cpufreq_freq_attr_ro(related_cpus); +cpufreq_freq_attr_ro(affected_cpus); +cpufreq_freq_attr_rw(scaling_min_freq); +cpufreq_freq_attr_rw(scaling_max_freq); +cpufreq_freq_attr_rw(scaling_governor); +cpufreq_freq_attr_rw(scaling_setspeed);  static struct attribute *default_attrs[] = {  	&cpuinfo_min_freq.attr, diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 3a147874a46..526bfbf6961 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -178,12 +178,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj,  	return sprintf(buf, "%u\n", min_sampling_rate);  } -#define define_one_ro(_name)		\ -static struct global_attr _name =	\ -__ATTR(_name, 0444, show_##_name, NULL) - -define_one_ro(sampling_rate_max); -define_one_ro(sampling_rate_min); +define_one_global_ro(sampling_rate_max); +define_one_global_ro(sampling_rate_min);  /* cpufreq_conservative Governor Tunables */  #define show_one(file_name, object)					\ @@ -221,12 +217,8 @@ show_one_old(freq_step);  show_one_old(sampling_rate_min);  show_one_old(sampling_rate_max); -#define define_one_ro_old(object, _name)	\ -static struct freq_attr object =		\ -__ATTR(_name, 0444, show_##_name##_old, NULL) - -define_one_ro_old(sampling_rate_min_old, sampling_rate_min); -define_one_ro_old(sampling_rate_max_old, sampling_rate_max); +cpufreq_freq_attr_ro_old(sampling_rate_min); +cpufreq_freq_attr_ro_old(sampling_rate_max);  /*** delete after deprecation time ***/ @@ -364,16 +356,12 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b,  	return count;  } -#define define_one_rw(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -define_one_rw(sampling_rate); -define_one_rw(sampling_down_factor); -define_one_rw(up_threshold); -define_one_rw(down_threshold); -define_one_rw(ignore_nice_load); -define_one_rw(freq_step); +define_one_global_rw(sampling_rate); +define_one_global_rw(sampling_down_factor); +define_one_global_rw(up_threshold); +define_one_global_rw(down_threshold); +define_one_global_rw(ignore_nice_load); +define_one_global_rw(freq_step);  static struct attribute *dbs_attributes[] = {  	&sampling_rate_max.attr, @@ -409,16 +397,12 @@ write_one_old(down_threshold);  write_one_old(ignore_nice_load);  write_one_old(freq_step); -#define define_one_rw_old(object, _name)	\ -static struct freq_attr object =		\ -__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) - -define_one_rw_old(sampling_rate_old, sampling_rate); -define_one_rw_old(sampling_down_factor_old, sampling_down_factor); -define_one_rw_old(up_threshold_old, up_threshold); -define_one_rw_old(down_threshold_old, down_threshold); -define_one_rw_old(ignore_nice_load_old, ignore_nice_load); -define_one_rw_old(freq_step_old, freq_step); +cpufreq_freq_attr_rw_old(sampling_rate); +cpufreq_freq_attr_rw_old(sampling_down_factor); +cpufreq_freq_attr_rw_old(up_threshold); +cpufreq_freq_attr_rw_old(down_threshold); +cpufreq_freq_attr_rw_old(ignore_nice_load); +cpufreq_freq_attr_rw_old(freq_step);  static struct attribute *dbs_attributes_old[] = {  	&sampling_rate_max_old.attr, diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd444dc93cf..e1314212d8d 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -73,6 +73,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};  struct cpu_dbs_info_s {  	cputime64_t prev_cpu_idle; +	cputime64_t prev_cpu_iowait;  	cputime64_t prev_cpu_wall;  	cputime64_t prev_cpu_nice;  	struct cpufreq_policy *cur_policy; @@ -108,6 +109,7 @@ static struct dbs_tuners {  	unsigned int down_differential;  	unsigned int ignore_nice;  	unsigned int powersave_bias; +	unsigned int io_is_busy;  } dbs_tuners_ins = {  	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,  	.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, @@ -148,6 +150,16 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)  	return idle_time;  } +static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) +{ +	u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); + +	if (iowait_time == -1ULL) +		return 0; + +	return iowait_time; +} +  /*   * Find right freq to be set now with powersave_bias on.   * Returns the freq_hi to be used right now and will set freq_hi_jiffies, @@ -234,12 +246,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj,  	return sprintf(buf, "%u\n", min_sampling_rate);  } -#define define_one_ro(_name)		\ -static struct global_attr _name =	\ -__ATTR(_name, 0444, show_##_name, NULL) - -define_one_ro(sampling_rate_max); -define_one_ro(sampling_rate_min); +define_one_global_ro(sampling_rate_max); +define_one_global_ro(sampling_rate_min);  /* cpufreq_ondemand Governor Tunables */  #define show_one(file_name, object)					\ @@ -249,6 +257,7 @@ static ssize_t show_##file_name						\  	return sprintf(buf, "%u\n", dbs_tuners_ins.object);		\  }  show_one(sampling_rate, sampling_rate); +show_one(io_is_busy, io_is_busy);  show_one(up_threshold, up_threshold);  show_one(ignore_nice_load, ignore_nice);  show_one(powersave_bias, powersave_bias); @@ -274,12 +283,8 @@ show_one_old(powersave_bias);  show_one_old(sampling_rate_min);  show_one_old(sampling_rate_max); -#define define_one_ro_old(object, _name)       \ -static struct freq_attr object =               \ -__ATTR(_name, 0444, show_##_name##_old, NULL) - -define_one_ro_old(sampling_rate_min_old, sampling_rate_min); -define_one_ro_old(sampling_rate_max_old, sampling_rate_max); +cpufreq_freq_attr_ro_old(sampling_rate_min); +cpufreq_freq_attr_ro_old(sampling_rate_max);  /*** delete after deprecation time ***/ @@ -299,6 +304,23 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,  	return count;  } +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, +				   const char *buf, size_t count) +{ +	unsigned int input; +	int ret; + +	ret = sscanf(buf, "%u", &input); +	if (ret != 1) +		return -EINVAL; + +	mutex_lock(&dbs_mutex); +	dbs_tuners_ins.io_is_busy = !!input; +	mutex_unlock(&dbs_mutex); + +	return count; +} +  static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,  				  const char *buf, size_t count)  { @@ -376,14 +398,11 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,  	return count;  } -#define define_one_rw(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -define_one_rw(sampling_rate); -define_one_rw(up_threshold); -define_one_rw(ignore_nice_load); -define_one_rw(powersave_bias); +define_one_global_rw(sampling_rate); +define_one_global_rw(io_is_busy); +define_one_global_rw(up_threshold); +define_one_global_rw(ignore_nice_load); +define_one_global_rw(powersave_bias);  static struct attribute *dbs_attributes[] = {  	&sampling_rate_max.attr, @@ -392,6 +411,7 @@ static struct attribute *dbs_attributes[] = {  	&up_threshold.attr,  	&ignore_nice_load.attr,  	&powersave_bias.attr, +	&io_is_busy.attr,  	NULL  }; @@ -415,14 +435,10 @@ write_one_old(up_threshold);  write_one_old(ignore_nice_load);  write_one_old(powersave_bias); -#define define_one_rw_old(object, _name)       \ -static struct freq_attr object =               \ -__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) - -define_one_rw_old(sampling_rate_old, sampling_rate); -define_one_rw_old(up_threshold_old, up_threshold); -define_one_rw_old(ignore_nice_load_old, ignore_nice_load); -define_one_rw_old(powersave_bias_old, powersave_bias); +cpufreq_freq_attr_rw_old(sampling_rate); +cpufreq_freq_attr_rw_old(up_threshold); +cpufreq_freq_attr_rw_old(ignore_nice_load); +cpufreq_freq_attr_rw_old(powersave_bias);  static struct attribute *dbs_attributes_old[] = {         &sampling_rate_max_old.attr, @@ -470,14 +486,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)  	for_each_cpu(j, policy->cpus) {  		struct cpu_dbs_info_s *j_dbs_info; -		cputime64_t cur_wall_time, cur_idle_time; -		unsigned int idle_time, wall_time; +		cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; +		unsigned int idle_time, wall_time, iowait_time;  		unsigned int load, load_freq;  		int freq_avg;  		j_dbs_info = &per_cpu(od_cpu_dbs_info, j);  		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); +		cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time);  		wall_time = (unsigned int) cputime64_sub(cur_wall_time,  				j_dbs_info->prev_cpu_wall); @@ -487,6 +504,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)  				j_dbs_info->prev_cpu_idle);  		j_dbs_info->prev_cpu_idle = cur_idle_time; +		iowait_time = (unsigned int) cputime64_sub(cur_iowait_time, +				j_dbs_info->prev_cpu_iowait); +		j_dbs_info->prev_cpu_iowait = cur_iowait_time; +  		if (dbs_tuners_ins.ignore_nice) {  			cputime64_t cur_nice;  			unsigned long cur_nice_jiffies; @@ -504,6 +525,16 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)  			idle_time += jiffies_to_usecs(cur_nice_jiffies);  		} +		/* +		 * For the purpose of ondemand, waiting for disk IO is an +		 * indication that you're performance critical, and not that +		 * the system is actually idle. So subtract the iowait time +		 * from the cpu idle time. +		 */ + +		if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) +			idle_time -= iowait_time; +  		if (unlikely(!wall_time || wall_time < idle_time))  			continue; @@ -617,6 +648,29 @@ static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)  	cancel_delayed_work_sync(&dbs_info->work);  } +/* + * Not all CPUs want IO time to be accounted as busy; this dependson how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (androidlcom) calis this is also not true for ARM. + * Because of this, whitelist specific known (series) of CPUs by default, and + * leave all others up to the user. + */ +static int should_io_be_busy(void) +{ +#if defined(CONFIG_X86) +	/* +	 * For Intel, Core 2 (model 15) andl later have an efficient idle. +	 */ +	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && +	    boot_cpu_data.x86 == 6 && +	    boot_cpu_data.x86_model >= 15) +		return 1; +#endif +	return 0; +} +  static int cpufreq_governor_dbs(struct cpufreq_policy *policy,  				   unsigned int event)  { @@ -679,6 +733,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,  			dbs_tuners_ins.sampling_rate =  				max(min_sampling_rate,  				    latency * LATENCY_MULTIPLIER); +			dbs_tuners_ins.io_is_busy = should_io_be_busy();  		}  		mutex_unlock(&dbs_mutex); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 1aea7157d8f..f8e57c6303f 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -100,7 +100,6 @@ struct menu_device {  	int             needs_update;  	unsigned int	expected_us; -	unsigned int	measured_us;  	u64		predicted_us;  	unsigned int	exit_us;  	unsigned int	bucket; @@ -187,14 +186,14 @@ static int menu_select(struct cpuidle_device *dev)  	int i;  	int multiplier; -	data->last_state_idx = 0; -	data->exit_us = 0; -  	if (data->needs_update) {  		menu_update(dev);  		data->needs_update = 0;  	} +	data->last_state_idx = 0; +	data->exit_us = 0; +  	/* Special case when user has set very strict latency requirement */  	if (unlikely(latency_req == 0))  		return 0; @@ -294,7 +293,7 @@ static void menu_update(struct cpuidle_device *dev)  	new_factor = data->correction_factor[data->bucket]  			* (DECAY - 1) / DECAY; -	if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING) +	if (data->expected_us > 0 && measured_us < MAX_INTERESTING)  		new_factor += RESOLUTION * measured_us / data->expected_us;  	else  		/* diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index 3ebc61067e5..75fcf1ac8bb 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -1359,3 +1359,5 @@ module_exit(txx9dmac_exit);  MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("TXx9 DMA Controller driver");  MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); +MODULE_ALIAS("platform:txx9dmac"); +MODULE_ALIAS("platform:txx9dmac-chan"); diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c index f5b6d9fe4de..97e64bcdbc0 100644 --- a/drivers/edac/edac_mce_amd.c +++ b/drivers/edac/edac_mce_amd.c @@ -294,7 +294,6 @@ wrong_ls_mce:  void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)  {  	u32 ec  = ERROR_CODE(regs->nbsl); -	u32 xec = EXT_ERROR_CODE(regs->nbsl);  	if (!handle_errors)  		return; @@ -324,7 +323,7 @@ void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)  		pr_cont("\n");  	} -	pr_emerg("%s.\n", EXT_ERR_MSG(xec)); +	pr_emerg("%s.\n", EXT_ERR_MSG(regs->nbsl));  	if (BUS_ERROR(ec) && nb_bus_decoder)  		nb_bus_decoder(node_id, regs); @@ -374,7 +373,7 @@ static int amd_decode_mce(struct notifier_block *nb, unsigned long val,  		 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));  	/* do the two bits[14:13] together */ -	ecc = m->status & (3ULL << 45); +	ecc = (m->status >> 45) & 0x3;  	if (ecc)  		pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U")); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 76be229c814..eb0c3fe44b2 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -416,7 +416,8 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,  	return 0;  free_sd: -	sysfs_put(pdesc->value_sd); +	if (pdesc) +		sysfs_put(pdesc->value_sd);  free_id:  	idr_remove(&pdesc_idr, id);  	desc->flags &= GPIO_FLAGS_MASK; diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c index 753219cf993..41a9388f2fd 100644 --- a/drivers/gpio/it8761e_gpio.c +++ b/drivers/gpio/it8761e_gpio.c @@ -80,8 +80,8 @@ static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)  	u16 reg;  	u8 bit; -	bit = gpio_num % 7; -	reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; +	bit = gpio_num % 8; +	reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;  	return !!(inb(reg) & (1 << bit));  } @@ -91,8 +91,8 @@ static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)  	u8 curr_dirs;  	u8 io_reg, bit; -	bit = gpio_num % 7; -	io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; +	bit = gpio_num % 8; +	io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;  	spin_lock(&sio_lock); @@ -116,8 +116,8 @@ static void it8761e_gpio_set(struct gpio_chip *gc,  	u8 curr_vals, bit;  	u16 reg; -	bit = gpio_num % 7; -	reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; +	bit = gpio_num % 8; +	reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;  	spin_lock(&sio_lock); @@ -135,8 +135,8 @@ static int it8761e_gpio_direction_out(struct gpio_chip *gc,  {  	u8 curr_dirs, io_reg, bit; -	bit = gpio_num % 7; -	io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; +	bit = gpio_num % 8; +	io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;  	it8761e_gpio_set(gc, gpio_num, val); @@ -200,7 +200,7 @@ static int __init it8761e_gpio_init(void)  		return -EBUSY;  	it8761e_gpio_chip.base = -1; -	it8761e_gpio_chip.ngpio = 14; +	it8761e_gpio_chip.ngpio = 16;  	err = gpiochip_add(&it8761e_gpio_chip);  	if (err < 0) diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 7d521e1d17e..b827c976dc6 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -252,6 +252,18 @@ static void pca953x_irq_bus_lock(unsigned int irq)  static void pca953x_irq_bus_sync_unlock(unsigned int irq)  {  	struct pca953x_chip *chip = get_irq_chip_data(irq); +	uint16_t new_irqs; +	uint16_t level; + +	/* Look for any newly setup interrupt */ +	new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; +	new_irqs &= ~chip->reg_direction; + +	while (new_irqs) { +		level = __ffs(new_irqs); +		pca953x_gpio_direction_input(&chip->gpio_chip, level); +		new_irqs &= ~(1 << level); +	}  	mutex_unlock(&chip->irq_lock);  } @@ -278,7 +290,7 @@ static int pca953x_irq_set_type(unsigned int irq, unsigned int type)  	else  		chip->irq_trig_raise &= ~mask; -	return pca953x_gpio_direction_input(&chip->gpio_chip, level); +	return 0;  }  static struct irq_chip pca953x_irq_chip = { diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 5ad8f778ced..105701a1f05 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c @@ -91,6 +91,12 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,  	gpiodir = readb(chip->base + GPIODIR);  	gpiodir |= 1 << offset;  	writeb(gpiodir, chip->base + GPIODIR); + +	/* +	 * gpio value is set again, because pl061 doesn't allow to set value of +	 * a gpio pin before configuring it in OUT mode. +	 */ +	writeb(!!value << offset, chip->base + (1 << (offset + 2)));  	spin_unlock_irqrestore(&chip->lock, flags);  	return 0; @@ -183,7 +189,7 @@ static int pl061_irq_type(unsigned irq, unsigned trigger)  		gpioibe &= ~(1 << offset);  		if (trigger & IRQ_TYPE_EDGE_RISING)  			gpioiev |= 1 << offset; -		else +		else if (trigger & IRQ_TYPE_EDGE_FALLING)  			gpioiev &= ~(1 << offset);  	}  	writeb(gpioibe, chip->base + GPIOIBE); @@ -204,7 +210,7 @@ static struct irq_chip pl061_irqchip = {  static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)  { -	struct list_head *chip_list = get_irq_chip_data(irq); +	struct list_head *chip_list = get_irq_data(irq);  	struct list_head *ptr;  	struct pl061_gpio *chip; @@ -297,9 +303,9 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)  			goto iounmap;  		}  		INIT_LIST_HEAD(chip_list); -		set_irq_chip_data(irq, chip_list); +		set_irq_data(irq, chip_list);  	} else -		chip_list = get_irq_chip_data(irq); +		chip_list = get_irq_data(irq);  	list_add(&chip->list, chip_list);  	for (i = 0; i < PL061_GPIO_NR; i++) { diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3bd87276156..a263b7070fc 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -476,6 +476,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc)  	unsigned long irqflags;  	spin_lock_irqsave(&dev->vbl_lock, irqflags); +	dev->driver->disable_vblank(dev, crtc);  	DRM_WAKEUP(&dev->vbl_queue[crtc]);  	dev->vblank_enabled[crtc] = 0;  	dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index e4865f99989..7732268eced 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c @@ -77,7 +77,7 @@ static void *agp_remap(unsigned long offset, unsigned long size,  		    && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=  		    (offset + size))  			break; -	if (!agpmem) +	if (&agpmem->head == &dev->agp->memory)  		return NULL;  	/* diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 1a1825b29f5..25bbd30ed7a 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -354,7 +354,10 @@ static struct bin_attribute edid_attr = {  int drm_sysfs_connector_add(struct drm_connector *connector)  {  	struct drm_device *dev = connector->dev; -	int ret = 0, i, j; +	int attr_cnt = 0; +	int opt_cnt = 0; +	int i; +	int ret = 0;  	/* We shouldn't get called more than once for the same connector */  	BUG_ON(device_is_registered(&connector->kdev)); @@ -377,8 +380,8 @@ int drm_sysfs_connector_add(struct drm_connector *connector)  	/* Standard attributes */ -	for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) { -		ret = device_create_file(&connector->kdev, &connector_attrs[i]); +	for (attr_cnt = 0; attr_cnt < ARRAY_SIZE(connector_attrs); attr_cnt++) { +		ret = device_create_file(&connector->kdev, &connector_attrs[attr_cnt]);  		if (ret)  			goto err_out_files;  	} @@ -394,8 +397,8 @@ int drm_sysfs_connector_add(struct drm_connector *connector)  		case DRM_MODE_CONNECTOR_SVIDEO:  		case DRM_MODE_CONNECTOR_Component:  		case DRM_MODE_CONNECTOR_TV: -			for (i = 0; i < ARRAY_SIZE(connector_attrs_opt1); i++) { -				ret = device_create_file(&connector->kdev, &connector_attrs_opt1[i]); +			for (opt_cnt = 0; opt_cnt < ARRAY_SIZE(connector_attrs_opt1); opt_cnt++) { +				ret = device_create_file(&connector->kdev, &connector_attrs_opt1[opt_cnt]);  				if (ret)  					goto err_out_files;  			} @@ -414,10 +417,10 @@ int drm_sysfs_connector_add(struct drm_connector *connector)  	return 0;  err_out_files: -	if (i > 0) -		for (j = 0; j < i; j++) -			device_remove_file(&connector->kdev, -					   &connector_attrs[i]); +	for (i = 0; i < opt_cnt; i++) +		device_remove_file(&connector->kdev, &connector_attrs_opt1[i]); +	for (i = 0; i < attr_cnt; i++) +		device_remove_file(&connector->kdev, &connector_attrs[i]);  	device_unregister(&connector->kdev);  out: diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2b8b969d0c1..df6a9cd82c4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -456,11 +456,15 @@ i915_error_object_create(struct drm_device *dev,  	for (page = 0; page < page_count; page++) {  		void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC); +		unsigned long flags; +  		if (d == NULL)  			goto unwind; -		s = kmap_atomic(src_priv->pages[page], KM_USER0); +		local_irq_save(flags); +		s = kmap_atomic(src_priv->pages[page], KM_IRQ0);  		memcpy(d, s, PAGE_SIZE); -		kunmap_atomic(s, KM_USER0); +		kunmap_atomic(s, KM_IRQ0); +		local_irq_restore(flags);  		dst->pages[page] = d;  	}  	dst->page_count = page_count; diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 6732b5dd8ff..27e2c715be1 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -2912,7 +2912,7 @@ typedef struct _ATOM_ANALOG_TV_INFO_V1_2    UCHAR                    ucTV_BootUpDefaultStandard;     UCHAR                    ucExt_TV_ASIC_ID;    UCHAR                    ucExt_TV_ASIC_SlaveAddr; -  ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING]; +  ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING_V1_2];  }ATOM_ANALOG_TV_INFO_V1_2;  typedef struct _ATOM_DPCD_INFO diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index d7388fdb6d0..cf60c0b3ef1 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2975,7 +2975,7 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track)  	for (i = 0; i < track->num_cb; i++) {  		if (track->cb[i].robj == NULL) { -			if (!(track->fastfill || track->color_channel_mask || +			if (!(track->zb_cb_clear || track->color_channel_mask ||  			      track->blend_read_enable)) {  				continue;  			} diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index fadfe68de9c..f47cdca1c00 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -75,7 +75,7 @@ struct r100_cs_track {  	struct r100_cs_track_texture	textures[R300_TRACK_MAX_TEXTURE];  	bool				z_enabled;  	bool                            separate_cube; -	bool				fastfill; +	bool				zb_cb_clear;  	bool				blend_read_enable;  }; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index bd75f99bd65..a5ff8076b42 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -324,13 +324,12 @@ void r300_gpu_init(struct radeon_device *rdev)  	uint32_t gb_tile_config, tmp;  	r100_hdp_reset(rdev); -	/* FIXME: rv380 one pipes ? */  	if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) || -	    (rdev->family == CHIP_R350)) { +	    (rdev->family == CHIP_R350 && rdev->pdev->device != 0x4148)) {  		/* r300,r350 */  		rdev->num_gb_pipes = 2;  	} else { -		/* rv350,rv370,rv380,r300 AD */ +		/* rv350,rv370,rv380,r300 AD, r350 AH */  		rdev->num_gb_pipes = 1;  	}  	rdev->num_z_pipes = 1; @@ -1045,7 +1044,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,  		break;  	case 0x4d1c:  		/* ZB_BW_CNTL */ -		track->fastfill = !!(idx_value & (1 << 2)); +		track->zb_cb_clear = !!(idx_value & (1 << 5));  		break;  	case 0x4e04:  		/* RB3D_BLENDCNTL */ diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index ea46d558e8f..c5c2742e414 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -921,7 +921,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,  	ptr_addr = drm_buffer_read_object(cmdbuf->buffer,  			sizeof(stack_ptr_addr), &stack_ptr_addr); -	ref_age_base = (u32 *)(unsigned long)*ptr_addr; +	ref_age_base = (u32 *)(unsigned long)get_unaligned(ptr_addr);  	for (i=0; i < header.scratch.n_bufs; i++) {  		buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 3dc968c9f5a..c2bda4ad62e 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -59,6 +59,12 @@ void r420_pipes_init(struct radeon_device *rdev)  	/* get max number of pipes */  	gb_pipe_select = RREG32(0x402C);  	num_pipes = ((gb_pipe_select >> 12) & 3) + 1; + +	/* SE chips have 1 pipe */ +	if ((rdev->pdev->device == 0x5e4c) || +	    (rdev->pdev->device == 0x5e4f)) +		num_pipes = 1; +  	rdev->num_gb_pipes = num_pipes;  	tmp = 0;  	switch (num_pipes) { diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index c4457791dff..28e473f1f56 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -134,12 +134,10 @@ int radeon_agp_init(struct radeon_device *rdev)  	int ret;  	/* Acquire AGP. */ -	if (!rdev->ddev->agp->acquired) { -		ret = drm_agp_acquire(rdev->ddev); -		if (ret) { -			DRM_ERROR("Unable to acquire AGP: %d\n", ret); -			return ret; -		} +	ret = drm_agp_acquire(rdev->ddev); +	if (ret) { +		DRM_ERROR("Unable to acquire AGP: %d\n", ret); +		return ret;  	}  	ret = drm_agp_info(rdev->ddev, &info); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 5673665ff21..9916d825401 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1264,7 +1264,7 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,  	switch (crev) {  	case 1:  		tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset); -		if (index > MAX_SUPPORTED_TV_TIMING) +		if (index >= MAX_SUPPORTED_TV_TIMING)  			return false;  		mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); @@ -1302,7 +1302,7 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,  		break;  	case 2:  		tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset); -		if (index > MAX_SUPPORTED_TV_TIMING_V1_2) +		if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)  			return false;  		dtd_timings = &tv_info_v1_2->aModeTimings[index]; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 1331351c517..4559a53d5e5 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1316,6 +1316,8 @@ radeon_add_legacy_connector(struct drm_device *dev,  			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");  			if (!radeon_connector->ddc_bus)  				goto failed; +		} +		if (connector_type == DRM_MODE_CONNECTOR_DVII) {  			radeon_connector->dac_load_detect = true;  			drm_connector_attach_property(&radeon_connector->base,  						      rdev->mode_info.load_detect_property, diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 419630dd207..2f042a3c0e6 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -435,14 +435,19 @@ static void radeon_init_pipes(struct drm_device *dev)  	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {  		gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);  		dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; +		/* SE cards have 1 pipe */ +		if ((dev->pdev->device == 0x5e4c) || +		    (dev->pdev->device == 0x5e4f)) +			dev_priv->num_gb_pipes = 1;  	} else {  		/* R3xx */  		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 &&  		     dev->pdev->device != 0x4144) || -		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) { +		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350 && +		     dev->pdev->device != 0x4148)) {  			dev_priv->num_gb_pipes = 2;  		} else { -			/* RV3xx/R300 AD */ +			/* RV3xx/R300 AD/R350 AH */  			dev_priv->num_gb_pipes = 1;  		}  	} diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b8d67282824..bb1c122cad2 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -86,12 +86,12 @@ static void evergreen_crtc_load_lut(struct drm_crtc *crtc)  	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);  	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff); -	WREG32(EVERGREEN_DC_LUT_RW_MODE, radeon_crtc->crtc_id); -	WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK, 0x00000007); +	WREG32(EVERGREEN_DC_LUT_RW_MODE + radeon_crtc->crtc_offset, 0); +	WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x00000007); -	WREG32(EVERGREEN_DC_LUT_RW_INDEX, 0); +	WREG32(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, 0);  	for (i = 0; i < 256; i++) { -		WREG32(EVERGREEN_DC_LUT_30_COLOR, +		WREG32(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset,  		       (radeon_crtc->lut_r[i] << 20) |  		       (radeon_crtc->lut_g[i] << 10) |  		       (radeon_crtc->lut_b[i] << 0)); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4b05563d99e..b3749d47be7 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -216,6 +216,7 @@ static struct drm_driver driver_old = {  		 .mmap = drm_mmap,  		 .poll = drm_poll,  		 .fasync = drm_fasync, +		 .read = drm_read,  #ifdef CONFIG_COMPAT  		 .compat_ioctl = radeon_compat_ioctl,  #endif @@ -304,6 +305,7 @@ static struct drm_driver kms_driver = {  		 .mmap = radeon_mmap,  		 .poll = drm_poll,  		 .fasync = drm_fasync, +		 .read = drm_read,  #ifdef CONFIG_COMPAT  		 .compat_ioctl = radeon_kms_compat_ioctl,  #endif diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 30293bec080..c5ddaf58563 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -254,6 +254,53 @@ radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder)  	return dig_connector;  } +void radeon_panel_mode_fixup(struct drm_encoder *encoder, +			     struct drm_display_mode *adjusted_mode) +{ +	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); +	struct drm_device *dev = encoder->dev; +	struct radeon_device *rdev = dev->dev_private; +	struct drm_display_mode *native_mode = &radeon_encoder->native_mode; +	unsigned hblank = native_mode->htotal - native_mode->hdisplay; +	unsigned vblank = native_mode->vtotal - native_mode->vdisplay; +	unsigned hover = native_mode->hsync_start - native_mode->hdisplay; +	unsigned vover = native_mode->vsync_start - native_mode->vdisplay; +	unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start; +	unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start; + +	adjusted_mode->clock = native_mode->clock; +	adjusted_mode->flags = native_mode->flags; + +	if (ASIC_IS_AVIVO(rdev)) { +		adjusted_mode->hdisplay = native_mode->hdisplay; +		adjusted_mode->vdisplay = native_mode->vdisplay; +	} + +	adjusted_mode->htotal = native_mode->hdisplay + hblank; +	adjusted_mode->hsync_start = native_mode->hdisplay + hover; +	adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width; + +	adjusted_mode->vtotal = native_mode->vdisplay + vblank; +	adjusted_mode->vsync_start = native_mode->vdisplay + vover; +	adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width; + +	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); + +	if (ASIC_IS_AVIVO(rdev)) { +		adjusted_mode->crtc_hdisplay = native_mode->hdisplay; +		adjusted_mode->crtc_vdisplay = native_mode->vdisplay; +	} + +	adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank; +	adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover; +	adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width; + +	adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank; +	adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover; +	adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width; + +} +  static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,  				   struct drm_display_mode *mode,  				   struct drm_display_mode *adjusted_mode) @@ -275,18 +322,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,  		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;  	/* get the native mode for LVDS */ -	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { -		struct drm_display_mode *native_mode = &radeon_encoder->native_mode; -		int mode_id = adjusted_mode->base.id; -		*adjusted_mode = *native_mode; -		if (!ASIC_IS_AVIVO(rdev)) { -			adjusted_mode->hdisplay = mode->hdisplay; -			adjusted_mode->vdisplay = mode->vdisplay; -			adjusted_mode->crtc_hdisplay = mode->hdisplay; -			adjusted_mode->crtc_vdisplay = mode->vdisplay; -		} -		adjusted_mode->base.id = mode_id; -	} +	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) +		radeon_panel_mode_fixup(encoder, adjusted_mode);  	/* get the native mode for TV */  	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { @@ -1326,7 +1363,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,  	radeon_encoder->pixel_clock = adjusted_mode->clock; -	if (ASIC_IS_AVIVO(rdev)) { +	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {  		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))  			atombios_yuv_setup(encoder, true);  		else diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index d3657dcfdd2..c633319f98e 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -165,7 +165,7 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)  {  	struct radeon_device *rdev = dev->dev_private; -	if (crtc < 0 || crtc > 1) { +	if (crtc < 0 || crtc >= rdev->num_crtc) {  		DRM_ERROR("Invalid crtc %d\n", crtc);  		return -EINVAL;  	} @@ -177,7 +177,7 @@ int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)  {  	struct radeon_device *rdev = dev->dev_private; -	if (crtc < 0 || crtc > 1) { +	if (crtc < 0 || crtc >= rdev->num_crtc) {  		DRM_ERROR("Invalid crtc %d\n", crtc);  		return -EINVAL;  	} @@ -191,7 +191,7 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)  {  	struct radeon_device *rdev = dev->dev_private; -	if (crtc < 0 || crtc > 1) { +	if (crtc < 0 || crtc >= rdev->num_crtc) {  		DRM_ERROR("Invalid crtc %d\n", crtc);  		return;  	} diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 2441cca7d77..0274abe17ad 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -228,16 +228,8 @@ static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,  	drm_mode_set_crtcinfo(adjusted_mode, 0);  	/* get the native mode for LVDS */ -	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { -		struct drm_display_mode *native_mode = &radeon_encoder->native_mode; -		int mode_id = adjusted_mode->base.id; -		*adjusted_mode = *native_mode; -		adjusted_mode->hdisplay = mode->hdisplay; -		adjusted_mode->vdisplay = mode->vdisplay; -		adjusted_mode->crtc_hdisplay = mode->hdisplay; -		adjusted_mode->crtc_vdisplay = mode->vdisplay; -		adjusted_mode->base.id = mode_id; -	} +	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) +		radeon_panel_mode_fixup(encoder, adjusted_mode);  	return true;  } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 0b8e32776b1..5413fcd6308 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -558,6 +558,8 @@ extern int radeon_static_clocks_init(struct drm_device *dev);  bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,  					struct drm_display_mode *mode,  					struct drm_display_mode *adjusted_mode); +void radeon_panel_mode_fixup(struct drm_encoder *encoder, +			     struct drm_display_mode *adjusted_mode);  void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc);  /* legacy tv */ diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 40ab6d9c373..cc5316dcf58 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -424,7 +424,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *  		if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&  		    (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {  			u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); -			offset = *cmd << 10; +			offset = *cmd3 << 10;  			if (radeon_check_and_fixup_offset  			    (dev_priv, file_priv, &offset)) {  				DRM_ERROR("Invalid second packet offset\n"); @@ -2895,9 +2895,12 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,  			return rv;  		rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,  						cmdbuf->bufsz); -		if (rv) +		if (rv) { +			drm_buffer_free(cmdbuf->buffer);  			return rv; -	} +		} +	} else +		goto done;  	orig_nbox = cmdbuf->nbox; @@ -2905,8 +2908,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,  		int temp;  		temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); -		if (cmdbuf->bufsz != 0) -			drm_buffer_free(cmdbuf->buffer); +		drm_buffer_free(cmdbuf->buffer);  		return temp;  	} @@ -3012,16 +3014,15 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,  		}  	} -	if (cmdbuf->bufsz != 0) -		drm_buffer_free(cmdbuf->buffer); +	drm_buffer_free(cmdbuf->buffer); +      done:  	DRM_DEBUG("DONE\n");  	COMMIT_RING();  	return 0;        err: -	if (cmdbuf->bufsz != 0) -		drm_buffer_free(cmdbuf->buffer); +	drm_buffer_free(cmdbuf->buffer);  	return -EINVAL;  } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index dd47b2a9a79..0e3754a3a30 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1716,40 +1716,12 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,  }  EXPORT_SYMBOL(ttm_bo_wait); -void ttm_bo_unblock_reservation(struct ttm_buffer_object *bo) -{ -	atomic_set(&bo->reserved, 0); -	wake_up_all(&bo->event_queue); -} - -int ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible, -			     bool no_wait) -{ -	int ret; - -	while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { -		if (no_wait) -			return -EBUSY; -		else if (interruptible) { -			ret = wait_event_interruptible -			    (bo->event_queue, atomic_read(&bo->reserved) == 0); -			if (unlikely(ret != 0)) -				return ret; -		} else { -			wait_event(bo->event_queue, -				   atomic_read(&bo->reserved) == 0); -		} -	} -	return 0; -} -  int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait)  {  	int ret = 0;  	/* -	 * Using ttm_bo_reserve instead of ttm_bo_block_reservation -	 * makes sure the lru lists are updated. +	 * Using ttm_bo_reserve makes sure the lru lists are updated.  	 */  	ret = ttm_bo_reserve(bo, true, no_wait, false, 0); diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c index 3d172ef04ee..de41e55a944 100644 --- a/drivers/gpu/drm/ttm/ttm_lock.c +++ b/drivers/gpu/drm/ttm/ttm_lock.c @@ -204,7 +204,6 @@ static int __ttm_vt_unlock(struct ttm_lock *lock)  	lock->flags &= ~TTM_VT_LOCK;  	wake_up_all(&lock->queue);  	spin_unlock(&lock->lock); -	printk(KERN_INFO TTM_PFX "vt unlock.\n");  	return ret;  } @@ -265,10 +264,8 @@ int ttm_vt_lock(struct ttm_lock *lock,  				   ttm_lock_type, &ttm_vt_lock_remove, NULL);  	if (ret)  		(void)__ttm_vt_unlock(lock); -	else { +	else  		lock->vt_holder = tfile; -		printk(KERN_INFO TTM_PFX "vt lock.\n"); -	}  	return ret;  } diff --git a/drivers/gpu/drm/via/via_video.c b/drivers/gpu/drm/via/via_video.c index 6ec04ac1245..6efac8117c9 100644 --- a/drivers/gpu/drm/via/via_video.c +++ b/drivers/gpu/drm/via/via_video.c @@ -75,7 +75,7 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_  	DRM_DEBUG("\n"); -	if (fx->lock > VIA_NR_XVMC_LOCKS) +	if (fx->lock >= VIA_NR_XVMC_LOCKS)  		return -EFAULT;  	lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock); diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index d6d1149d525..c8768f38511 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -276,8 +276,10 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,  	mutex_lock(&vgasr_mutex); -	if (!vgasr_priv.active) -		return -EINVAL; +	if (!vgasr_priv.active) { +		cnt = -EINVAL; +		goto out; +	}  	/* pwr off the device not in use */  	if (strncmp(usercmd, "OFF", 3) == 0) { diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 7e597d7f770..24663a8717b 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c @@ -59,6 +59,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,  static const struct hid_device_id ch_devices[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },  	{ }  };  MODULE_DEVICE_TABLE(hid, ch_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2e2aa759d23..143e788b729 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1043,13 +1043,8 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,  	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)  		hid->hiddev_report_event(hid, report); -	if (hid->claimed & HID_CLAIMED_HIDRAW) { -		/* numbered reports need to be passed with the report num */ -		if (report_enum->numbered) -			hidraw_report_event(hid, data - 1, size + 1); -		else -			hidraw_report_event(hid, data, size); -	} +	if (hid->claimed & HID_CLAIMED_HIDRAW) +		hidraw_report_event(hid, data, size);  	for (a = 0; a < report->maxfield; a++)  		hid_input_field(hid, report->field[a], cdata, interrupt); @@ -1296,6 +1291,7 @@ static const struct hid_device_id hid_blacklist[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 797e0647035..09d27649a0f 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -131,6 +131,7 @@  #define USB_VENDOR_ID_CHERRY		0x046a  #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023 +#define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR	0x0027  #define USB_VENDOR_ID_CHIC		0x05fe  #define USB_DEVICE_ID_CHIC_GAMEPAD	0x0014 diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 9b24fc51071..4777bbfa1cc 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -1,8 +1,8 @@  /*   *  HID driver for N-Trig touchscreens   * - *  Copyright (c) 2008 Rafi Rubin - *  Copyright (c) 2009 Stephane Chatty + *  Copyright (c) 2008-2010 Rafi Rubin + *  Copyright (c) 2009-2010 Stephane Chatty   *   */ @@ -15,6 +15,8 @@  #include <linux/device.h>  #include <linux/hid.h> +#include <linux/usb.h> +#include "usbhid/usbhid.h"  #include <linux/module.h>  #include <linux/slab.h> @@ -22,17 +24,16 @@  #define NTRIG_DUPLICATE_USAGES	0x001 -#define nt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \ -					EV_KEY, (c)) -  struct ntrig_data {  	/* Incoming raw values for a single contact */  	__u16 x, y, w, h;  	__u16 id; -	__u8 confidence; + +	bool tipswitch; +	bool confidence; +	bool first_contact_touch;  	bool reading_mt; -	__u8 first_contact_confidence;  	__u8 mt_footer[4];  	__u8 mt_foot_count; @@ -139,9 +140,10 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,  		case 0xff000001:  			/* Tag indicating the start of a multitouch group */  			nd->reading_mt = 1; -			nd->first_contact_confidence = 0; +			nd->first_contact_touch = 0;  			break;  		case HID_DG_TIPSWITCH: +			nd->tipswitch = value;  			/* Prevent emission of touch until validated */  			return 1;  		case HID_DG_CONFIDENCE: @@ -169,8 +171,14 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,  			 * to emit a normal (X, Y) position  			 */  			if (!nd->reading_mt) { +				/* +				 * TipSwitch indicates the presence of a +				 * finger in single touch mode. +				 */ +				input_report_key(input, BTN_TOUCH, +						 nd->tipswitch);  				input_report_key(input, BTN_TOOL_DOUBLETAP, -						 (nd->confidence != 0)); +						 nd->tipswitch);  				input_event(input, EV_ABS, ABS_X, nd->x);  				input_event(input, EV_ABS, ABS_Y, nd->y);  			} @@ -209,7 +217,13 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,  			/* emit a normal (X, Y) for the first point only */  			if (nd->id == 0) { -				nd->first_contact_confidence = nd->confidence; +				/* +				 * TipSwitch is superfluous in multitouch +				 * mode.  The footer events tell us +				 * if there is a finger on the screen or +				 * not. +				 */ +				nd->first_contact_touch = nd->confidence;  				input_event(input, EV_ABS, ABS_X, nd->x);  				input_event(input, EV_ABS, ABS_Y, nd->y);  			} @@ -239,30 +253,11 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,  			nd->reading_mt = 0; -			if (nd->first_contact_confidence) { -				switch (value) { -				case 0:	/* for single touch devices */ -				case 1: -					input_report_key(input, -							BTN_TOOL_DOUBLETAP, 1); -					break; -				case 2: -					input_report_key(input, -							BTN_TOOL_TRIPLETAP, 1); -					break; -				case 3: -				default: -					input_report_key(input, -							BTN_TOOL_QUADTAP, 1); -				} +			if (nd->first_contact_touch) { +				input_report_key(input, BTN_TOOL_DOUBLETAP, 1);  				input_report_key(input, BTN_TOUCH, 1);  			} else { -				input_report_key(input, -						BTN_TOOL_DOUBLETAP, 0); -				input_report_key(input, -						BTN_TOOL_TRIPLETAP, 0); -				input_report_key(input, -						BTN_TOOL_QUADTAP, 0); +				input_report_key(input, BTN_TOOL_DOUBLETAP, 0);  				input_report_key(input, BTN_TOUCH, 0);  			}  			break; @@ -286,6 +281,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)  	struct ntrig_data *nd;  	struct hid_input *hidinput;  	struct input_dev *input; +	struct hid_report *report;  	if (id->driver_data)  		hdev->quirks |= HID_QUIRK_MULTI_INPUT; @@ -327,13 +323,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)  			__clear_bit(BTN_TOOL_PEN, input->keybit);  			__clear_bit(BTN_TOOL_FINGER, input->keybit);  			__clear_bit(BTN_0, input->keybit); -			/* -			 * A little something special to enable -			 * two and three finger taps. -			 */  			__set_bit(BTN_TOOL_DOUBLETAP, input->keybit); -			__set_bit(BTN_TOOL_TRIPLETAP, input->keybit); -			__set_bit(BTN_TOOL_QUADTAP, input->keybit);  			/*  			 * The physical touchscreen (single touch)  			 * input has a value for physical, whereas @@ -349,6 +339,12 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)  		}  	} +	/* This is needed for devices with more recent firmware versions */ +	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; +	if (report) +		usbhid_submit_report(hdev, report, USB_DIR_OUT); + +  	return 0;  err_free:  	kfree(nd); diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 7502a4b2fa8..402d5574b57 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -76,7 +76,7 @@ static int sony_set_operational_usb(struct hid_device *hdev)  static int sony_set_operational_bt(struct hid_device *hdev)  { -	unsigned char buf[] = { 0x53, 0xf4,  0x42, 0x03, 0x00, 0x00 }; +	unsigned char buf[] = { 0xf4,  0x42, 0x03, 0x00, 0x00 };  	return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);  } diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index f7700cf4972..f947d8337e2 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -277,7 +277,6 @@ static int __init wacom_init(void)  	ret = hid_register_driver(&wacom_driver);  	if (ret)  		printk(KERN_ERR "can't register wacom driver\n"); -	printk(KERN_ERR "wacom driver registered\n");  	return ret;  } diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 56d06cd8075..7b85b696fda 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -999,13 +999,6 @@ static int usbhid_start(struct hid_device *hid)  		}  	} -	init_waitqueue_head(&usbhid->wait); -	INIT_WORK(&usbhid->reset_work, hid_reset); -	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); -	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); - -	spin_lock_init(&usbhid->lock); -  	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);  	if (!usbhid->urbctrl) {  		ret = -ENOMEM; @@ -1179,6 +1172,12 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *  	usbhid->intf = intf;  	usbhid->ifnum = interface->desc.bInterfaceNumber; +	init_waitqueue_head(&usbhid->wait); +	INIT_WORK(&usbhid->reset_work, hid_reset); +	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); +	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); +	spin_lock_init(&usbhid->lock); +  	ret = hid_add_device(hid);  	if (ret) {  		if (ret != -ENODEV) diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 0f28d91f29d..f085c18d290 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -195,6 +195,9 @@ static unsigned int applesmc_accelerometer;  /* Indicates whether this computer has light sensors and keyboard backlight. */  static unsigned int applesmc_light; +/* The number of fans handled by the driver */ +static unsigned int fans_handled; +  /* Indicates which temperature sensors set to use. */  static unsigned int applesmc_temperature_set; @@ -1492,39 +1495,24 @@ static int __init applesmc_init(void)  	/* create fan files */  	count = applesmc_get_fan_count(); -	if (count < 0) { +	if (count < 0)  		printk(KERN_ERR "applesmc: Cannot get the number of fans.\n"); -	} else { +	else  		printk(KERN_INFO "applesmc: %d fans found.\n", count); -		switch (count) { -		default: -			printk(KERN_WARNING "applesmc: More than 4 fans found," -					" but at most 4 fans are supported" -						" by the driver.\n"); -		case 4: -			ret = sysfs_create_group(&pdev->dev.kobj, -						 &fan_attribute_groups[3]); -			if (ret) -				goto out_key_enumeration; -		case 3: -			ret = sysfs_create_group(&pdev->dev.kobj, -						 &fan_attribute_groups[2]); -			if (ret) -				goto out_key_enumeration; -		case 2: -			ret = sysfs_create_group(&pdev->dev.kobj, -						 &fan_attribute_groups[1]); -			if (ret) -				goto out_key_enumeration; -		case 1: -			ret = sysfs_create_group(&pdev->dev.kobj, -						 &fan_attribute_groups[0]); -			if (ret) -				goto out_fan_1; -		case 0: -			; -		} +	if (count > 4) { +		count = 4; +		printk(KERN_WARNING "applesmc: More than 4 fans found," +		       " but at most 4 fans are supported" +		       " by the driver.\n"); +	} + +	while (fans_handled < count) { +		ret = sysfs_create_group(&pdev->dev.kobj, +					 &fan_attribute_groups[fans_handled]); +		if (ret) +			goto out_fans; +		fans_handled++;  	}  	for (i = 0; @@ -1593,10 +1581,10 @@ out_accelerometer:  		applesmc_release_accelerometer();  out_temperature:  	sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); -	sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]); -out_fan_1: -	sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]); -out_key_enumeration: +out_fans: +	while (fans_handled) +		sysfs_remove_group(&pdev->dev.kobj, +				   &fan_attribute_groups[--fans_handled]);  	sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);  out_name:  	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); @@ -1622,8 +1610,9 @@ static void __exit applesmc_exit(void)  	if (applesmc_accelerometer)  		applesmc_release_accelerometer();  	sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); -	sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]); -	sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]); +	while (fans_handled) +		sysfs_remove_group(&pdev->dev.kobj, +				   &fan_attribute_groups[--fans_handled]);  	sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);  	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);  	platform_device_unregister(pdev); diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 7f948105d8a..0f388adc618 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c @@ -268,8 +268,11 @@ static ssize_t store_fan16(struct device *dev,  	if (strict_strtol(buf, 10, &reqval))  		return -EINVAL; +	/* If a minimum RPM of zero is requested, then we set the register to +	   0xffff. This value allows the fan to be stopped completely without +	   generating an alarm. */  	reqval = -	    (SENSORS_LIMIT((reqval) <= 0 ? 0 : 5400000 / (reqval), 0, 65534)); +	    (reqval <= 0 ? 0xffff : SENSORS_LIMIT(5400000 / reqval, 0, 0xfffe));  	mutex_lock(&data->update_lock);  	data->reg[param->msb[0]] = (reqval >> 8) & 0xff; @@ -285,8 +288,9 @@ static ssize_t store_fan16(struct device *dev,   * Voltages are scaled in the device so that the nominal voltage   * is 3/4ths of the 0-255 range (i.e. 192).   * If all voltages are 'normal' then all voltage registers will - * read 0xC0.  This doesn't help us if we don't have a point of refernce. - * The data sheet however provides us with the full scale value for each + * read 0xC0. + * + * The data sheet provides us with the 3/4 scale value for each voltage   * which is stored in in_scaling.  The sda->index parameter value provides   * the index into in_scaling.   * @@ -295,7 +299,7 @@ static ssize_t store_fan16(struct device *dev,   */  static int asc7621_in_scaling[] = { -	3320, 3000, 4380, 6640, 16000 +	2500, 2250, 3300, 5000, 12000  };  static ssize_t show_in10(struct device *dev, struct device_attribute *attr, @@ -306,19 +310,12 @@ static ssize_t show_in10(struct device *dev, struct device_attribute *attr,  	u8 nr = sda->index;  	mutex_lock(&data->update_lock); -	regval = (data->reg[param->msb[0]] * asc7621_in_scaling[nr]) / 256; - -	/* The LSB value is a 2-bit scaling of the MSB's LSbit value. -	 * I.E.  If the maximim voltage for this input is 6640 millivolts then -	 * a MSB register value of 0 = 0mv and 255 = 6640mv. -	 * A 1 step change therefore represents 25.9mv (6640 / 256). -	 * The extra 2-bits therefore represent increments of 6.48mv. -	 */ -	regval += ((asc7621_in_scaling[nr] / 256) / 4) * -	    (data->reg[param->lsb[0]] >> 6); - +	regval = (data->reg[param->msb[0]] << 8) | (data->reg[param->lsb[0]]);  	mutex_unlock(&data->update_lock); +	/* The LSB value is a 2-bit scaling of the MSB's LSbit value. */ +	regval = (regval >> 6) * asc7621_in_scaling[nr] / (0xc0 << 2); +  	return sprintf(buf, "%u\n", regval);  } @@ -331,7 +328,7 @@ static ssize_t show_in8(struct device *dev, struct device_attribute *attr,  	return sprintf(buf, "%u\n",  		       ((data->reg[param->msb[0]] * -			 asc7621_in_scaling[nr]) / 256)); +			 asc7621_in_scaling[nr]) / 0xc0));  }  static ssize_t store_in8(struct device *dev, struct device_attribute *attr, @@ -344,9 +341,11 @@ static ssize_t store_in8(struct device *dev, struct device_attribute *attr,  	if (strict_strtol(buf, 10, &reqval))  		return -EINVAL; -	reqval = SENSORS_LIMIT(reqval, 0, asc7621_in_scaling[nr]); +	reqval = SENSORS_LIMIT(reqval, 0, 0xffff); + +	reqval = reqval * 0xc0 / asc7621_in_scaling[nr]; -	reqval = (reqval * 255 + 128) / asc7621_in_scaling[nr]; +	reqval = SENSORS_LIMIT(reqval, 0, 0xff);  	mutex_lock(&data->update_lock);  	data->reg[param->msb[0]] = reqval; @@ -846,11 +845,11 @@ static struct asc7621_param asc7621_params[] = {  	PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8),  	PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), -	PREAD(in0_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 0, bitmask), -	PREAD(in1_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 1, bitmask), -	PREAD(in2_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 2, bitmask), -	PREAD(in3_alarm, 3, PRI_LOW, 0x41, 0, 0x01, 3, bitmask), -	PREAD(in4_alarm, 4, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), +	PREAD(in0_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 0, bitmask), +	PREAD(in1_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 1, bitmask), +	PREAD(in2_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 2, bitmask), +	PREAD(in3_alarm, 3, PRI_HIGH, 0x41, 0, 0x01, 3, bitmask), +	PREAD(in4_alarm, 4, PRI_HIGH, 0x42, 0, 0x01, 0, bitmask),  	PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16),  	PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), @@ -862,10 +861,10 @@ static struct asc7621_param asc7621_params[] = {  	PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16),  	PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), -	PREAD(fan1_alarm, 0, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), -	PREAD(fan2_alarm, 1, PRI_LOW, 0x42, 0, 0x01, 1, bitmask), -	PREAD(fan3_alarm, 2, PRI_LOW, 0x42, 0, 0x01, 2, bitmask), -	PREAD(fan4_alarm, 3, PRI_LOW, 0x42, 0, 0x01, 3, bitmask), +	PREAD(fan1_alarm, 0, PRI_HIGH, 0x42, 0, 0x01, 2, bitmask), +	PREAD(fan2_alarm, 1, PRI_HIGH, 0x42, 0, 0x01, 3, bitmask), +	PREAD(fan3_alarm, 2, PRI_HIGH, 0x42, 0, 0x01, 4, bitmask), +	PREAD(fan4_alarm, 3, PRI_HIGH, 0x42, 0, 0x01, 5, bitmask),  	PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10),  	PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), @@ -886,10 +885,10 @@ static struct asc7621_param asc7621_params[] = {  	PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8),  	PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), -	PREAD(temp1_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 4, bitmask), -	PREAD(temp2_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 5, bitmask), -	PREAD(temp3_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 6, bitmask), -	PREAD(temp4_alarm, 3, PRI_LOW, 0x43, 0, 0x01, 0, bitmask), +	PREAD(temp1_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 4, bitmask), +	PREAD(temp2_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 5, bitmask), +	PREAD(temp3_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 6, bitmask), +	PREAD(temp4_alarm, 3, PRI_HIGH, 0x43, 0, 0x01, 0, bitmask),  	PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask),  	PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), @@ -898,7 +897,7 @@ static struct asc7621_param asc7621_params[] = {  	PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask),  	PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), -	PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x64, 0, 0x01, 3, bitmask), +	PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x63, 0, 0x01, 3, bitmask),  	PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask),  	PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index c8ab5051667..7580f55e67e 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -328,8 +328,8 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)  	lis3lv02d_joystick_disable();  	lis3lv02d_poweroff(&lis3_dev); -	flush_work(&hpled_led.work);  	led_classdev_unregister(&hpled_led.led_classdev); +	flush_work(&hpled_led.work);  	return lis3lv02d_remove_fs(&lis3_dev);  } diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index a2481f40ea1..0e9f85d0a83 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -447,7 +447,7 @@ static struct i2c_adapter octeon_i2c_ops = {  /**   * octeon_i2c_setclock - Calculate and set clock divisors.   */ -static int __init octeon_i2c_setclock(struct octeon_i2c *i2c) +static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c)  {  	int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;  	int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; @@ -490,7 +490,7 @@ static int __init octeon_i2c_setclock(struct octeon_i2c *i2c)  	return 0;  } -static int __init octeon_i2c_initlowlevel(struct octeon_i2c *i2c) +static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c)  {  	u8 status;  	int tries; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 3202a86f420..c2258a51fe0 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -40,12 +40,11 @@  #include "i2c-core.h" -/* core_lock protects i2c_adapter_idr, userspace_devices, and guarantees +/* core_lock protects i2c_adapter_idr, and guarantees     that device detection, deletion of detected devices, and attach_adapter     and detach_adapter calls are serialized */  static DEFINE_MUTEX(core_lock);  static DEFINE_IDR(i2c_adapter_idr); -static LIST_HEAD(userspace_devices);  static struct device_type i2c_client_type;  static int i2c_check_addr(struct i2c_adapter *adapter, int addr); @@ -117,8 +116,10 @@ static int i2c_device_probe(struct device *dev)  	dev_dbg(dev, "probe\n");  	status = driver->probe(client, i2c_match_id(driver->id_table, client)); -	if (status) +	if (status) {  		client->driver = NULL; +		i2c_set_clientdata(client, NULL); +	}  	return status;  } @@ -139,8 +140,10 @@ static int i2c_device_remove(struct device *dev)  		dev->driver = NULL;  		status = 0;  	} -	if (status == 0) +	if (status == 0) {  		client->driver = NULL; +		i2c_set_clientdata(client, NULL); +	}  	return status;  } @@ -538,9 +541,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,  		return -EEXIST;  	/* Keep track of the added device */ -	mutex_lock(&core_lock); -	list_add_tail(&client->detected, &userspace_devices); -	mutex_unlock(&core_lock); +	i2c_lock_adapter(adap); +	list_add_tail(&client->detected, &adap->userspace_clients); +	i2c_unlock_adapter(adap);  	dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",  		 info.type, info.addr); @@ -579,9 +582,10 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,  	/* Make sure the device was added through sysfs */  	res = -ENOENT; -	mutex_lock(&core_lock); -	list_for_each_entry_safe(client, next, &userspace_devices, detected) { -		if (client->addr == addr && client->adapter == adap) { +	i2c_lock_adapter(adap); +	list_for_each_entry_safe(client, next, &adap->userspace_clients, +				 detected) { +		if (client->addr == addr) {  			dev_info(dev, "%s: Deleting device %s at 0x%02hx\n",  				 "delete_device", client->name, client->addr); @@ -591,7 +595,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,  			break;  		}  	} -	mutex_unlock(&core_lock); +	i2c_unlock_adapter(adap);  	if (res < 0)  		dev_err(dev, "%s: Can't find device in list\n", @@ -673,6 +677,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)  	}  	rt_mutex_init(&adap->bus_lock); +	INIT_LIST_HEAD(&adap->userspace_clients);  	/* Set default timeout to 1 second if not already set */  	if (adap->timeout == 0) @@ -875,14 +880,15 @@ int i2c_del_adapter(struct i2c_adapter *adap)  		return res;  	/* Remove devices instantiated from sysfs */ -	list_for_each_entry_safe(client, next, &userspace_devices, detected) { -		if (client->adapter == adap) { -			dev_dbg(&adap->dev, "Removing %s at 0x%x\n", -				client->name, client->addr); -			list_del(&client->detected); -			i2c_unregister_device(client); -		} +	i2c_lock_adapter(adap); +	list_for_each_entry_safe(client, next, &adap->userspace_clients, +				 detected) { +		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, +			client->addr); +		list_del(&client->detected); +		i2c_unregister_device(client);  	} +	i2c_unlock_adapter(adap);  	/* Detach any active clients. This can't fail, thus we do not  	   checking the returned value. */ @@ -1260,12 +1266,23 @@ static int i2c_detect_address(struct i2c_client *temp_client,  		return 0;  	/* Make sure there is something at this address */ -	if (i2c_smbus_xfer(adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) < 0) -		return 0; +	if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) { +		/* Special probe for FSC hwmon chips */ +		union i2c_smbus_data dummy; + +		if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0, +				   I2C_SMBUS_BYTE_DATA, &dummy) < 0) +			return 0; +	} else { +		if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0, +				   I2C_SMBUS_QUICK, NULL) < 0) +			return 0; -	/* Prevent 24RF08 corruption */ -	if ((addr & ~0x0f) == 0x50) -		i2c_smbus_xfer(adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL); +		/* Prevent 24RF08 corruption */ +		if ((addr & ~0x0f) == 0x50) +			i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0, +				       I2C_SMBUS_QUICK, NULL); +	}  	/* Finally call the custom detection function */  	memset(&info, 0, sizeof(struct i2c_board_info)); diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index defce2877ee..b85450865ff 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c @@ -409,7 +409,7 @@ static struct pcmcia_device_id ide_ids[] = {  	PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),  	PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),  	PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), -	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x3e520e17), +	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),  	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),  	PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),  	PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b), @@ -431,7 +431,7 @@ static struct pcmcia_device_id ide_ids[] = {  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), -	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x9351e59d), +	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),  	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),  	PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),  	PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 7e18bcf05a6..46239e47a26 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -59,11 +59,11 @@ static unsigned int get_time_pit(void)  	unsigned long flags;  	unsigned int count; -	spin_lock_irqsave(&i8253_lock, flags); +	raw_spin_lock_irqsave(&i8253_lock, flags);  	outb_p(0x00, 0x43);  	count = inb_p(0x40);  	count |= inb_p(0x40) << 8; -	spin_unlock_irqrestore(&i8253_lock, flags); +	raw_spin_unlock_irqrestore(&i8253_lock, flags);  	return count;  } diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index c52bec4d053..423e0e6031a 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -929,6 +929,24 @@ static const struct input_device_id joydev_ids[] = {  		.evbit = { BIT_MASK(EV_ABS) },  		.absbit = { BIT_MASK(ABS_THROTTLE) },  	}, +	{ +		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | +				INPUT_DEVICE_ID_MATCH_KEYBIT, +		.evbit = { BIT_MASK(EV_KEY) }, +		.keybit = {[BIT_WORD(BTN_JOYSTICK)] = BIT_MASK(BTN_JOYSTICK) }, +	}, +	{ +		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | +				INPUT_DEVICE_ID_MATCH_KEYBIT, +		.evbit = { BIT_MASK(EV_KEY) }, +		.keybit = { [BIT_WORD(BTN_GAMEPAD)] = BIT_MASK(BTN_GAMEPAD) }, +	}, +	{ +		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | +				INPUT_DEVICE_ID_MATCH_KEYBIT, +		.evbit = { BIT_MASK(EV_KEY) }, +		.keybit = { [BIT_WORD(BTN_TRIGGER_HAPPY)] = BIT_MASK(BTN_TRIGGER_HAPPY) }, +	},  	{ }	/* Terminating entry */  }; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 1c0b529c06a..4afe0a3b488 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -146,11 +146,11 @@ static unsigned int get_time_pit(void)          unsigned long flags;          unsigned int count; -        spin_lock_irqsave(&i8253_lock, flags); +        raw_spin_lock_irqsave(&i8253_lock, flags);          outb_p(0x00, 0x43);          count = inb_p(0x40);          count |= inb_p(0x40) << 8; -        spin_unlock_irqrestore(&i8253_lock, flags); +        raw_spin_unlock_irqrestore(&i8253_lock, flags);          return count;  } diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b1edd778639..405febd94f2 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -54,6 +54,9 @@ static signed short btn_avb_wheel[] =  static signed short abs_joystick[] =  { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; +static signed short abs_joystick_rudder[] = +{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, -1 }; +  static signed short abs_avb_pegasus[] =  { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y,    ABS_HAT1X, ABS_HAT1Y, -1 }; @@ -76,8 +79,9 @@ static struct iforce_device iforce_device[] = {  	{ 0x061c, 0xc0a4, "ACT LABS Force RS",                          btn_wheel, abs_wheel, ff_iforce }, //?  	{ 0x061c, 0xc084, "ACT LABS Force RS",				btn_wheel, abs_wheel, ff_iforce },  	{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback",	btn_wheel, abs_wheel, ff_iforce }, //? +	{ 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback",	btn_joystick, abs_joystick_rudder, ff_iforce },  	{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel",	btn_wheel, abs_wheel, ff_iforce }, //? -	{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D",			btn_joystick, abs_joystick, ff_iforce }, //? +	{ 0x06f8, 0xa302, "Guillemot Jet Leader 3D",			btn_joystick, abs_joystick, ff_iforce }, //?  	{ 0x06d6, 0x29bc, "Trust Force Feedback Race Master",		btn_wheel, abs_wheel, ff_iforce },  	{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]",		btn_joystick, abs_joystick, ff_iforce }  }; diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index b41303d3ec5..6c96631ae5d 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -212,6 +212,7 @@ static struct usb_device_id iforce_usb_ids [] = {  	{ USB_DEVICE(0x061c, 0xc0a4) },         /* ACT LABS Force RS */  	{ USB_DEVICE(0x061c, 0xc084) },         /* ACT LABS Force RS */  	{ USB_DEVICE(0x06f8, 0x0001) },		/* Guillemot Race Leader Force Feedback */ +	{ USB_DEVICE(0x06f8, 0x0003) },		/* Guillemot Jet Leader Force Feedback */  	{ USB_DEVICE(0x06f8, 0x0004) },		/* Guillemot Force Feedback Racing Wheel */  	{ USB_DEVICE(0x06f8, 0xa302) },		/* Guillemot Jet Leader 3D */  	{ }					/* Terminating entry */ diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index 614b65d78fe..e8bbc619f6d 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c @@ -98,10 +98,12 @@   * Module and Version Information, Module Parameters   */ -#define ATI_REMOTE_VENDOR_ID	0x0bc7 -#define ATI_REMOTE_PRODUCT_ID	0x004 -#define LOLA_REMOTE_PRODUCT_ID	0x002 -#define MEDION_REMOTE_PRODUCT_ID 0x006 +#define ATI_REMOTE_VENDOR_ID		0x0bc7 +#define LOLA_REMOTE_PRODUCT_ID		0x0002 +#define LOLA2_REMOTE_PRODUCT_ID		0x0003 +#define ATI_REMOTE_PRODUCT_ID		0x0004 +#define NVIDIA_REMOTE_PRODUCT_ID	0x0005 +#define MEDION_REMOTE_PRODUCT_ID	0x0006  #define DRIVER_VERSION	        "2.2.1"  #define DRIVER_AUTHOR           "Torrey Hoffman <thoffman@arnor.net>" @@ -142,8 +144,10 @@ MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec  #define err(format, arg...) printk(KERN_ERR format , ## arg)  static struct usb_device_id ati_remote_table[] = { -	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },  	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, +	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) }, +	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, +	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) },  	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) },  	{}	/* Terminating entry */  }; diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index ea4e1fd1265..f080dd31499 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -30,7 +30,7 @@ MODULE_ALIAS("platform:pcspkr");  #include <asm/i8253.h>  #else  #include <asm/8253pit.h> -static DEFINE_SPINLOCK(i8253_lock); +static DEFINE_RAW_SPINLOCK(i8253_lock);  #endif  static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) @@ -50,7 +50,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c  	if (value > 20 && value < 32767)  		count = PIT_TICK_RATE / value; -	spin_lock_irqsave(&i8253_lock, flags); +	raw_spin_lock_irqsave(&i8253_lock, flags);  	if (count) {  		/* set command for counter 2, 2 byte write */ @@ -65,7 +65,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c  		outb(inb_p(0x61) & 0xFC, 0x61);  	} -	spin_unlock_irqrestore(&i8253_lock, flags); +	raw_spin_unlock_irqrestore(&i8253_lock, flags);  	return 0;  } diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 0d22cb9ce42..99d58764ef0 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -64,7 +64,6 @@ static const struct alps_model_info alps_model_data[] = {  	{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf,  		ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },  	{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS },	  /* Dell Vostro 1400 */ -	{ { 0x73, 0x02, 0x64 }, 0xf8, 0xf8, 0 },			  /* HP Pavilion dm3 */  	{ { 0x52, 0x01, 0x14 }, 0xff, 0xff,  		ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },	  /* Toshiba Tecra A11-11L */  }; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index a138b5da79f..112b4ee52ff 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -25,6 +25,10 @@  			printk(KERN_DEBUG format, ##arg);	\  	} while (0) +static bool force_elantech; +module_param_named(force_elantech, force_elantech, bool, 0644); +MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); +  /*   * Send a Synaptics style sliced query command   */ @@ -181,14 +185,18 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)  	int fingers;  	static int old_fingers; -	if (etd->fw_version_maj == 0x01) { -		/* byte 0:  D   U  p1  p2   1  p3   R   L -		   byte 1:  f   0  th  tw  x9  x8  y9  y8 */ +	if (etd->fw_version < 0x020000) { +		/* +		 * byte 0:  D   U  p1  p2   1  p3   R   L +		 * byte 1:  f   0  th  tw  x9  x8  y9  y8 +		 */  		fingers = ((packet[1] & 0x80) >> 7) +  				((packet[1] & 0x30) >> 4);  	} else { -		/* byte 0: n1  n0  p2  p1   1  p3   R   L -		   byte 1:  0   0   0   0  x9  x8  y9  y8 */ +		/* +		 * byte 0: n1  n0  p2  p1   1  p3   R   L +		 * byte 1:  0   0   0   0  x9  x8  y9  y8 +		 */  		fingers = (packet[0] & 0xc0) >> 6;  	} @@ -202,13 +210,15 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)  	input_report_key(dev, BTN_TOUCH, fingers != 0); -	/* byte 2: x7  x6  x5  x4  x3  x2  x1  x0 -	   byte 3: y7  y6  y5  y4  y3  y2  y1  y0 */ +	/* +	 * byte 2: x7  x6  x5  x4  x3  x2  x1  x0 +	 * byte 3: y7  y6  y5  y4  y3  y2  y1  y0 +	 */  	if (fingers) {  		input_report_abs(dev, ABS_X,  			((packet[1] & 0x0c) << 6) | packet[2]); -		input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - -			(((packet[1] & 0x03) << 8) | packet[3])); +		input_report_abs(dev, ABS_Y, +			ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));  	}  	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); @@ -217,7 +227,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)  	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);  	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); -	if ((etd->fw_version_maj == 0x01) && +	if (etd->fw_version < 0x020000 &&  	    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {  		/* rocker up */  		input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); @@ -247,34 +257,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)  	switch (fingers) {  	case 1: -		/* byte 1: x15 x14 x13 x12 x11 x10 x9  x8 -		   byte 2: x7  x6  x5  x4  x4  x2  x1  x0 */ -		input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); -		/* byte 4: y15 y14 y13 y12 y11 y10 y8  y8 -		   byte 5: y7  y6  y5  y4  y3  y2  y1  y0 */ -		input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - -			((packet[4] << 8) | packet[5])); +		/* +		 * byte 1:  .   .   .   .   .  x10 x9  x8 +		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0 +		 */ +		input_report_abs(dev, ABS_X, +			((packet[1] & 0x07) << 8) | packet[2]); +		/* +		 * byte 4:  .   .   .   .   .   .  y9  y8 +		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0 +		 */ +		input_report_abs(dev, ABS_Y, +			ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]));  		break;  	case 2: -		/* The coordinate of each finger is reported separately with -		   a lower resolution for two finger touches */ -		/* byte 0:  .   .  ay8 ax8  .   .   .   . -		   byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ +		/* +		 * The coordinate of each finger is reported separately +		 * with a lower resolution for two finger touches: +		 * byte 0:  .   .  ay8 ax8  .   .   .   . +		 * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 +		 */  		x1 = ((packet[0] & 0x10) << 4) | packet[1];  		/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */  		y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); -		/* byte 3:  .   .  by8 bx8  .   .   .   . -		   byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ +		/* +		 * byte 3:  .   .  by8 bx8  .   .   .   . +		 * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 +		 */  		x2 = ((packet[3] & 0x10) << 4) | packet[4];  		/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */  		y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); -		/* For compatibility with the X Synaptics driver scale up one -		   coordinate and report as ordinary mouse movent */ +		/* +		 * For compatibility with the X Synaptics driver scale up +		 * one coordinate and report as ordinary mouse movent +		 */  		input_report_abs(dev, ABS_X, x1 << 2);  		input_report_abs(dev, ABS_Y, y1 << 2); -		/* For compatibility with the proprietary X Elantech driver -		   report both coordinates as hat coordinates */ +		/* +		 * For compatibility with the proprietary X Elantech driver +		 * report both coordinates as hat coordinates +		 */  		input_report_abs(dev, ABS_HAT0X, x1);  		input_report_abs(dev, ABS_HAT0Y, y1);  		input_report_abs(dev, ABS_HAT1X, x2); @@ -298,7 +321,7 @@ static int elantech_check_parity_v1(struct psmouse *psmouse)  	unsigned char p1, p2, p3;  	/* Parity bits are placed differently */ -	if (etd->fw_version_maj == 0x01) { +	if (etd->fw_version < 0x020000) {  		/* byte 0:  D   U  p1  p2   1  p3   R   L */  		p1 = (packet[0] & 0x20) >> 5;  		p2 = (packet[0] & 0x10) >> 4; @@ -434,7 +457,7 @@ static void elantech_set_input_params(struct psmouse *psmouse)  	switch (etd->hw_version) {  	case 1:  		/* Rocker button */ -		if ((etd->fw_version_maj == 0x01) && +		if (etd->fw_version < 0x020000 &&  		    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {  			__set_bit(BTN_FORWARD, dev->keybit);  			__set_bit(BTN_BACK, dev->keybit); @@ -596,8 +619,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)  		 param[0], param[1], param[2]);  	if (param[0] == 0 || param[1] != 0) { -		pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); -		return -1; +		if (!force_elantech) { +			pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); +			return -1; +		} + +		pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");  	}  	if (set_properties) { @@ -659,14 +686,14 @@ int elantech_init(struct psmouse *psmouse)  		pr_err("elantech.c: failed to query firmware version.\n");  		goto init_fail;  	} -	etd->fw_version_maj = param[0]; -	etd->fw_version_min = param[2]; + +	etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];  	/*  	 * Assume every version greater than this is new EeePC style  	 * hardware with 6 byte packets  	 */ -	if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { +	if (etd->fw_version >= 0x020030) {  		etd->hw_version = 2;  		/* For now show extra debug information */  		etd->debug = 1; @@ -676,8 +703,9 @@ int elantech_init(struct psmouse *psmouse)  		etd->hw_version = 1;  		etd->paritycheck = 1;  	} -	pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n", -		etd->hw_version, etd->fw_version_maj, etd->fw_version_min); + +	pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n", +		etd->hw_version, param[0], param[1], param[2]);  	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {  		pr_err("elantech.c: failed to query capabilities.\n"); @@ -692,8 +720,8 @@ int elantech_init(struct psmouse *psmouse)  	 * a touch action starts causing the mouse cursor or scrolled page  	 * to jump. Enable a workaround.  	 */ -	if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { -		pr_info("elantech.c: firmware version 2.34 detected, " +	if (etd->fw_version == 0x020022) { +		pr_info("elantech.c: firmware version 2.0.34 detected, "  			"enabling jumpy cursor workaround\n");  		etd->jumpy_cursor = 1;  	} diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index feac5f7af96..ac57bde1bb9 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -100,11 +100,10 @@ struct elantech_data {  	unsigned char reg_26;  	unsigned char debug;  	unsigned char capabilities; -	unsigned char fw_version_maj; -	unsigned char fw_version_min; -	unsigned char hw_version;  	unsigned char paritycheck;  	unsigned char jumpy_cursor; +	unsigned char hw_version; +	unsigned int  fw_version;  	unsigned char parity[256];  }; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d8c0c8d6992..a3c97315a47 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq;  struct psmouse_protocol {  	enum psmouse_type type;  	bool maxproto; +	bool ignore_parity; /* Protocol should ignore parity errors from KBC */  	const char *name;  	const char *alias;  	int (*detect)(struct psmouse *, bool); @@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,  	if (psmouse->state == PSMOUSE_IGNORE)  		goto out; -	if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { +	if (unlikely((flags & SERIO_TIMEOUT) || +		     ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { +  		if (psmouse->state == PSMOUSE_ACTIVATED)  			printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",  				flags & SERIO_TIMEOUT ? " timeout" : "", @@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {  		.name		= "PS/2",  		.alias		= "bare",  		.maxproto	= true, +		.ignore_parity	= true,  		.detect		= ps2bare_detect,  	},  #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP @@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {  		.name		= "ImPS/2",  		.alias		= "imps",  		.maxproto	= true, +		.ignore_parity	= true,  		.detect		= intellimouse_detect,  	},  	{ @@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {  		.name		= "ImExPS/2",  		.alias		= "exps",  		.maxproto	= true, +		.ignore_parity	= true,  		.detect		= im_explorer_detect,  	},  #ifdef CONFIG_MOUSE_PS2_SYNAPTICS @@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio)  static int psmouse_switch_protocol(struct psmouse *psmouse,  				   const struct psmouse_protocol *proto)  { +	const struct psmouse_protocol *selected_proto;  	struct input_dev *input_dev = psmouse->dev;  	input_dev->dev.parent = &psmouse->ps2dev.serio->dev; @@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,  			return -1;  		psmouse->type = proto->type; -	} else +		selected_proto = proto; +	} else {  		psmouse->type = psmouse_extensions(psmouse,  						   psmouse_max_proto, true); +		selected_proto = psmouse_protocol_by_type(psmouse->type); +	} + +	psmouse->ignore_parity = selected_proto->ignore_parity;  	/*  	 * If mouse's packet size is 3 there is no point in polling the @@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,  		psmouse->resync_time = 0;  	snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", -		 psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); +		 selected_proto->name, psmouse->vendor, psmouse->name);  	input_dev->name = psmouse->devname;  	input_dev->phys = psmouse->phys; @@ -1382,6 +1394,7 @@ static int psmouse_reconnect(struct serio *serio)  	struct psmouse *psmouse = serio_get_drvdata(serio);  	struct psmouse *parent = NULL;  	struct serio_driver *drv = serio->drv; +	unsigned char type;  	int rc = -1;  	if (!drv || !psmouse) { @@ -1401,10 +1414,15 @@ static int psmouse_reconnect(struct serio *serio)  	if (psmouse->reconnect) {  		if (psmouse->reconnect(psmouse))  			goto out; -	} else if (psmouse_probe(psmouse) < 0 || -		   psmouse->type != psmouse_extensions(psmouse, -						psmouse_max_proto, false)) { -		goto out; +	} else { +		psmouse_reset(psmouse); + +		if (psmouse_probe(psmouse) < 0) +			goto out; + +		type = psmouse_extensions(psmouse, psmouse_max_proto, false); +		if (psmouse->type != type) +			goto out;  	}  	/* ok, the device type (and capabilities) match the old one, diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index e053bdd137f..593e910bfc7 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -47,6 +47,7 @@ struct psmouse {  	unsigned char pktcnt;  	unsigned char pktsize;  	unsigned char type; +	bool ignore_parity;  	bool acks_disable_command;  	unsigned int model;  	unsigned long last; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 026df601016..ebd7a99efea 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -137,7 +137,8 @@ static int synaptics_capability(struct psmouse *psmouse)  	if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))  		return -1;  	priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; -	priv->ext_cap = 0; +	priv->ext_cap = priv->ext_cap_0c = 0; +  	if (!SYN_CAP_VALID(priv->capabilities))  		return -1; @@ -150,7 +151,7 @@ static int synaptics_capability(struct psmouse *psmouse)  	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {  		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {  			printk(KERN_ERR "Synaptics claims to have extended capabilities," -			       " but I'm not able to read them."); +			       " but I'm not able to read them.\n");  		} else {  			priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; @@ -162,6 +163,16 @@ static int synaptics_capability(struct psmouse *psmouse)  				priv->ext_cap &= 0xff0fff;  		}  	} + +	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { +		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { +			printk(KERN_ERR "Synaptics claims to have extended capability 0x0c," +			       " but I'm not able to read it.\n"); +		} else { +			priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; +		} +	} +  	return 0;  } @@ -348,7 +359,15 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data  		hw->left  = (buf[0] & 0x01) ? 1 : 0;  		hw->right = (buf[0] & 0x02) ? 1 : 0; -		if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { +		if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { +			/* +			 * Clickpad's button is transmitted as middle button, +			 * however, since it is primary button, we will report +			 * it as BTN_LEFT. +			 */ +			hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; + +		} else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {  			hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;  			if (hw->w == 2)  				hw->scroll = (signed char)(buf[1]); @@ -593,6 +612,12 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)  	dev->absres[ABS_X] = priv->x_res;  	dev->absres[ABS_Y] = priv->y_res; + +	if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { +		/* Clickpads report only left button */ +		__clear_bit(BTN_RIGHT, dev->keybit); +		__clear_bit(BTN_MIDDLE, dev->keybit); +	}  }  static void synaptics_disconnect(struct psmouse *psmouse) @@ -697,10 +722,10 @@ int synaptics_init(struct psmouse *psmouse)  	priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; -	printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n", +	printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",  		SYN_ID_MODEL(priv->identity),  		SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), -		priv->model_id, priv->capabilities, priv->ext_cap); +		priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);  	set_input_params(psmouse->dev, priv); diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index f0f40a331dc..ae37c5d162a 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -18,6 +18,7 @@  #define SYN_QUE_SERIAL_NUMBER_SUFFIX	0x07  #define SYN_QUE_RESOLUTION		0x08  #define SYN_QUE_EXT_CAPAB		0x09 +#define SYN_QUE_EXT_CAPAB_0C		0x0c  /* synatics modes */  #define SYN_BIT_ABSOLUTE_MODE		(1 << 7) @@ -48,6 +49,8 @@  #define SYN_CAP_VALID(c)		((((c) & 0x00ff00) >> 8) == 0x47)  #define SYN_EXT_CAP_REQUESTS(c)		(((c) & 0x700000) >> 20)  #define SYN_CAP_MULTI_BUTTON_NO(ec)	(((ec) & 0x00f000) >> 12) +#define SYN_CAP_PRODUCT_ID(ec)		(((ec) & 0xff0000) >> 16) +#define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100100)  /* synaptics modes query bits */  #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7)) @@ -96,6 +99,7 @@ struct synaptics_data {  	unsigned long int model_id;		/* Model-ID */  	unsigned long int capabilities;		/* Capabilities */  	unsigned long int ext_cap;		/* Extended Capabilities */ +	unsigned long int ext_cap_0c;		/* Ext Caps from 0x0c query */  	unsigned long int identity;		/* Identification */  	int x_res;				/* X resolution in units/mm */  	int y_res;				/* Y resolution in units/mm */ diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index e019d53d1ab..0d2d7e54b46 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -156,9 +156,14 @@ struct ser_req {  	u16			reset;  	u16			ref_on;  	u16			command; -	u16			sample;  	struct spi_message	msg;  	struct spi_transfer	xfer[6]; + +	/* +	 * DMA (thus cache coherency maintenance) requires the +	 * transfer buffers to live in their own cache lines. +	 */ +	u16 sample ____cacheline_aligned;  };  struct ad7877 { @@ -182,8 +187,6 @@ struct ad7877 {  	u8			averaging;  	u8			pen_down_acc_interval; -	u16			conversion_data[AD7877_NR_SENSE]; -  	struct spi_transfer	xfer[AD7877_NR_SENSE + 2];  	struct spi_message	msg; @@ -195,6 +198,12 @@ struct ad7877 {  	spinlock_t		lock;  	struct timer_list	timer;		/* P: lock */  	unsigned		pending:1;	/* P: lock */ + +	/* +	 * DMA (thus cache coherency maintenance) requires the +	 * transfer buffers to live in their own cache lines. +	 */ +	u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;  };  static int gpio3; diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 204b8a1a601..75f8b73010f 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -124,14 +124,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static int eeti_ts_open(struct input_dev *dev) +static void eeti_ts_start(struct eeti_ts_priv *priv)  { -	struct eeti_ts_priv *priv = input_get_drvdata(dev); -  	enable_irq(priv->irq);  	/* Read the events once to arm the IRQ */  	eeti_ts_read(&priv->work); +} + +static void eeti_ts_stop(struct eeti_ts_priv *priv) +{ +	disable_irq(priv->irq); +	cancel_work_sync(&priv->work); +} + +static int eeti_ts_open(struct input_dev *dev) +{ +	struct eeti_ts_priv *priv = input_get_drvdata(dev); + +	eeti_ts_start(priv);  	return 0;  } @@ -140,8 +151,7 @@ static void eeti_ts_close(struct input_dev *dev)  {  	struct eeti_ts_priv *priv = input_get_drvdata(dev); -	disable_irq(priv->irq); -	cancel_work_sync(&priv->work); +	eeti_ts_stop(priv);  }  static int __devinit eeti_ts_probe(struct i2c_client *client, @@ -153,10 +163,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,  	unsigned int irq_flags;  	int err = -ENOMEM; -	/* In contrast to what's described in the datasheet, there seems +	/* +	 * In contrast to what's described in the datasheet, there seems  	 * to be no way of probing the presence of that device using I2C  	 * commands. So we need to blindly believe it is there, and wait -	 * for interrupts to occur. */ +	 * for interrupts to occur. +	 */  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (!priv) { @@ -212,9 +224,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,  		goto err2;  	} -	/* Disable the irq for now. It will be enabled once the input device -	 * is opened. */ -	disable_irq(priv->irq); +	/* +	 * Disable the device for now. It will be enabled once the +	 * input device is opened. +	 */ +	eeti_ts_stop(priv);  	device_init_wakeup(&client->dev, 0);  	return 0; @@ -235,6 +249,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)  	struct eeti_ts_priv *priv = i2c_get_clientdata(client);  	free_irq(priv->irq, priv); +	/* +	 * eeti_ts_stop() leaves IRQ disabled. We need to re-enable it +	 * so that device still works if we reload the driver. +	 */ +	enable_irq(priv->irq); +  	input_unregister_device(priv->input);  	i2c_set_clientdata(client, NULL);  	kfree(priv); @@ -246,6 +266,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)  static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)  {  	struct eeti_ts_priv *priv = i2c_get_clientdata(client); +	struct input_dev *input_dev = priv->input; + +	mutex_lock(&input_dev->mutex); + +	if (input_dev->users) +		eeti_ts_stop(priv); + +	mutex_unlock(&input_dev->mutex);  	if (device_may_wakeup(&client->dev))  		enable_irq_wake(priv->irq); @@ -256,10 +284,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)  static int eeti_ts_resume(struct i2c_client *client)  {  	struct eeti_ts_priv *priv = i2c_get_clientdata(client); +	struct input_dev *input_dev = priv->input;  	if (device_may_wakeup(&client->dev))  		disable_irq_wake(priv->irq); +	mutex_lock(&input_dev->mutex); + +	if (input_dev->users) +		eeti_ts_start(priv); + +	mutex_unlock(&input_dev->mutex); +  	return 0;  }  #else diff --git a/drivers/md/md.c b/drivers/md/md.c index 9712b2e97be..cefd63daff3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2109,12 +2109,18 @@ repeat:  		if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */  			/* .. if the array isn't clean, an 'even' event must also go  			 * to spares. */ -			if ((mddev->events&1)==0) +			if ((mddev->events&1)==0) {  				nospares = 0; +				sync_req = 2; /* force a second update to get the +					       * even/odd in sync */ +			}  		} else {  			/* otherwise an 'odd' event must go to spares */ -			if ((mddev->events&1)) +			if ((mddev->events&1)) {  				nospares = 0; +				sync_req = 2; /* force a second update to get the +					       * even/odd in sync */ +			}  		}  	} diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 58ea0ecae7c..15348c393b5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1527,7 +1527,7 @@ static void raid5_end_read_request(struct bio * bi, int error)  		clear_bit(R5_UPTODATE, &sh->dev[i].flags);  		atomic_inc(&rdev->read_errors); -		if (conf->mddev->degraded) +		if (conf->mddev->degraded >= conf->max_degraded)  			printk_rl(KERN_WARNING  				  "raid5:%s: read error not correctable "  				  "(sector %llu on %s).\n", diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index fd8e1f45be3..7364b9642d0 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -423,15 +423,14 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)  	}  } -int saa7146_vv_devinit(struct saa7146_dev *dev) -{ -	return v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); -} -EXPORT_SYMBOL_GPL(saa7146_vv_devinit); -  int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)  {  	struct saa7146_vv *vv; +	int err; + +	err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); +	if (err) +		return err;  	vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);  	if (vv == NULL) { diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 5ed75263340..b8b2c551a1e 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -558,9 +558,11 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f  	/* ok, accept it */  	vv->ov_fb = *fb;  	vv->ov_fmt = fmt; -	if (0 == vv->ov_fb.fmt.bytesperline) -		vv->ov_fb.fmt.bytesperline = -			vv->ov_fb.fmt.width * fmt->depth / 8; + +	if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) { +		vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; +		DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline)); +	}  	mutex_unlock(&dev->lock);  	return 0; diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index a3c07fe0e6c..96972804f4a 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -4470,6 +4470,10 @@ static int stv090x_setup(struct dvb_frontend *fe)  	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)  		goto err; +	/* workaround for stuck DiSEqC output */ +	if (config->diseqc_envelope_mode) +		stv090x_send_diseqc_burst(fe, SEC_MINI_A); +  	return 0;  err:  	dprintk(FE_ERROR, 1, "I/O error"); diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 9fdf26cc699..1500210c06c 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -643,9 +643,6 @@ static void frontend_init(struct budget *budget)  					&budget->i2c_adap,  					&tt1600_isl6423_config); -			} else { -				dvb_frontend_detach(budget->dvb_frontend); -				budget->dvb_frontend = NULL;  			}  		}  		break; diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f8fc8654693..9644cf760aa 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -361,7 +361,7 @@ config VIDEO_SAA717X  config VIDEO_SAA7191  	tristate "Philips SAA7191 video decoder" -	depends on VIDEO_V4L1 && I2C +	depends on VIDEO_V4L2 && I2C  	---help---  	  Support for the Philips SAA7191 video decoder. @@ -756,7 +756,7 @@ source "drivers/media/video/saa7134/Kconfig"  config VIDEO_MXB  	tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" -	depends on PCI && VIDEO_V4L1 && I2C +	depends on PCI && VIDEO_V4L2 && I2C  	select VIDEO_SAA7146_VV  	select VIDEO_TUNER  	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index b88b6174a33..c51c386559f 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -160,8 +160,6 @@ obj-$(CONFIG_VIDEO_MX3)			+= mx3_camera.o  obj-$(CONFIG_VIDEO_PXA27x)		+= pxa_camera.o  obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o -obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/ -  obj-$(CONFIG_VIDEO_AU0828) += au0828/  obj-$(CONFIG_USB_VIDEO_CLASS)	+= uvc/ diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 7cf042f9b37..398dbe71cb8 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -223,7 +223,6 @@ int vpfe_register_ccdc_device(struct ccdc_hw_device *dev)  	BUG_ON(!dev->hw_ops.get_frame_format);  	BUG_ON(!dev->hw_ops.get_pixel_format);  	BUG_ON(!dev->hw_ops.set_pixel_format); -	BUG_ON(!dev->hw_ops.set_params);  	BUG_ON(!dev->hw_ops.set_image_window);  	BUG_ON(!dev->hw_ops.get_image_window);  	BUG_ON(!dev->hw_ops.get_line_length); @@ -1689,11 +1688,12 @@ static long vpfe_param_handler(struct file *file, void *priv,  	struct vpfe_device *vpfe_dev = video_drvdata(file);  	int ret = 0; -	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); +	v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");  	if (vpfe_dev->started) {  		/* only allowed if streaming is not started */ -		v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n"); +		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, +			"device already started\n");  		return -EBUSY;  	} @@ -1705,16 +1705,23 @@ static long vpfe_param_handler(struct file *file, void *priv,  	case VPFE_CMD_S_CCDC_RAW_PARAMS:  		v4l2_warn(&vpfe_dev->v4l2_dev,  			  "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); -		ret = ccdc_dev->hw_ops.set_params(param); -		if (ret) { -			v4l2_err(&vpfe_dev->v4l2_dev, -				"Error in setting parameters in CCDC\n"); -			goto unlock_out; -		} -		if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) { -			v4l2_err(&vpfe_dev->v4l2_dev, -				"Invalid image format at CCDC\n"); -			goto unlock_out; +		if (ccdc_dev->hw_ops.set_params) { +			ret = ccdc_dev->hw_ops.set_params(param); +			if (ret) { +				v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, +					"Error setting parameters in CCDC\n"); +				goto unlock_out; +			} +			if (vpfe_get_ccdc_image_format(vpfe_dev, +						       &vpfe_dev->fmt) < 0) { +				v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, +					"Invalid image format at CCDC\n"); +				goto unlock_out; +			} +		} else { +			ret = -EINVAL; +			v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, +				"VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n");  		}  		break;  	default: @@ -1830,7 +1837,7 @@ static __init int vpfe_probe(struct platform_device *pdev)  	if (NULL == ccdc_cfg) {  		v4l2_err(pdev->dev.driver,  			 "Memory allocation failed for ccdc_cfg\n"); -		goto probe_free_dev_mem; +		goto probe_free_lock;  	}  	strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); @@ -1982,8 +1989,9 @@ probe_out_video_release:  probe_out_release_irq:  	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);  probe_free_ccdc_cfg_mem: -	mutex_unlock(&ccdc_lock);  	kfree(ccdc_cfg); +probe_free_lock: +	mutex_unlock(&ccdc_lock);  probe_free_dev_mem:  	kfree(vpfe_dev);  	return ret; diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 38a6e15e096..3dee3e5844b 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -1427,7 +1427,7 @@ static int input_kthread(void *data)  	struct gspca_dev *gspca_dev = (struct gspca_dev *)data;  	struct sd *sd = (struct sd *) gspca_dev; -	DECLARE_WAIT_QUEUE_HEAD(wait); +	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait);  	set_freezable();  	for (;;) {  		if (kthread_should_stop()) diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 15b2eef8a3f..edf0fe15750 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1513,7 +1513,6 @@ static const struct sd_desc sd_desc = {  static const __devinitdata struct usb_device_id device_table[] = {  	{USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},  	{USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista}, -	{USB_DEVICE(0x0461, 0x0815), .driver_info = MicroInnovationIC200},  	{USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},  	{USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},  	{USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2}, diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index dc7f2b0fbc7..b9c80e2103b 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1053,6 +1053,7 @@ static const __devinitdata struct usb_device_id device_table[] = {  	{USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},  	{USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},  	{USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A}, +	{USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},  	{USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},  	{USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},  	{USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A}, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index af73da34c83..14f179a1948 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -524,8 +524,6 @@ static const __devinitdata struct usb_device_id device_table[] = {  	{USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },  	/* QuickCam Messenger (new) */  	{USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, -	/* QuickCam Messenger (new) */ -	{USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 },  	{}  };  MODULE_DEVICE_TABLE(usb, device_table); diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index e620a3a92f2..ad2c232baa6 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -356,9 +356,6 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d  	DEB_EE((".\n")); -	ret = saa7146_vv_devinit(dev); -	if (ret) -		return ret;  	hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);  	if (NULL == hexium) {  		printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index fe596a1c12a..938a1f8f880 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -216,10 +216,6 @@ static int hexium_probe(struct saa7146_dev *dev)  		return -EFAULT;  	} -	err = saa7146_vv_devinit(dev); -	if (err) -		return err; -  	hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);  	if (NULL == hexium) {  		printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 3c8ebfcb742..34a66019190 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -49,8 +49,6 @@  /*   * CSI registers   */ -#define DMA_CCR(x)	(0x8c + ((x) << 6))	/* Control Registers */ -#define DMA_DIMR	0x08			/* Interrupt mask Register */  #define CSICR1		0x00			/* CSI Control Register 1 */  #define CSISR		0x08			/* CSI Status Register */  #define CSIRXR		0x10			/* CSI RxFIFO Register */ @@ -784,7 +782,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev)  			       pcdev);  	imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO, -			       IMX_DMA_MEMSIZE_32, DMA_REQ_CSI_R, 0); +			       IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0);  	/* burst length : 16 words = 64 bytes */  	imx_dma_config_burstlen(pcdev->dma_chan, 0); @@ -798,8 +796,8 @@ static int __init mx1_camera_probe(struct platform_device *pdev)  	set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end -  						   &mx1_camera_sof_fiq_start); -	regs.ARM_r8 = DMA_BASE + DMA_DIMR; -	regs.ARM_r9 = DMA_BASE + DMA_CCR(pcdev->dma_chan); +	regs.ARM_r8 = (long)MX1_DMA_DIMR; +	regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan);  	regs.ARM_r10 = (long)pcdev->base + CSICR1;  	regs.ARM_fp = (long)pcdev->base + CSISR;  	regs.ARM_sp = 1 << pcdev->dma_chan; diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 9f01f14e4aa..ef0c8178f25 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -169,11 +169,7 @@ static struct saa7146_extension extension;  static int mxb_probe(struct saa7146_dev *dev)  {  	struct mxb *mxb = NULL; -	int err; -	err = saa7146_vv_devinit(dev); -	if (err) -		return err;  	mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);  	if (mxb == NULL) {  		DEB_D(("not enough kernel memory.\n")); @@ -699,14 +695,17 @@ static struct saa7146_ext_vv vv_data;  /* this function only gets called when the probing was successful */  static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)  { -	struct mxb *mxb = (struct mxb *)dev->ext_priv; +	struct mxb *mxb;  	DEB_EE(("dev:%p\n", dev)); -	/* checking for i2c-devices can be omitted here, because we -	   already did this in "mxb_vl42_probe" */ -  	saa7146_vv_init(dev, &vv_data); +	if (mxb_probe(dev)) { +		saa7146_vv_release(dev); +		return -1; +	} +	mxb = (struct mxb *)dev->ext_priv; +  	vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;  	vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;  	vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; @@ -726,6 +725,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data  	vv_data.ops.vidioc_default = vidioc_default;  	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {  		ERR(("cannot register capture v4l2 device. skipping.\n")); +		saa7146_vv_release(dev);  		return -1;  	} @@ -846,7 +846,6 @@ static struct saa7146_extension extension = {  	.pci_tbl	= &pci_tbl[0],  	.module		= THIS_MODULE, -	.probe		= mxb_probe,  	.attach		= mxb_attach,  	.detach		= mxb_detach, diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index b189fe63394..ce76d952e16 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1405,7 +1405,7 @@ static int omap24xxcam_mmap_buffers(struct file *file,  	}  	size = 0; -	for (i = first; i <= last; i++) { +	for (i = first; i <= last && i < VIDEO_MAX_FRAME; i++) {  		struct videobuf_dmabuf *dma = videobuf_to_dma(vbq->bufs[i]);  		for (j = 0; j < dma->sglen; j++) { diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 5ecc30daef2..04bf5c11308 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -609,12 +609,9 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev,   */  static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev)  { -	unsigned long cicr0, cifr; +	unsigned long cicr0;  	dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); -	/* Reset the FIFOs */ -	cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; -	__raw_writel(cifr, pcdev->base + CIFR);  	/* Enable End-Of-Frame Interrupt */  	cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB;  	cicr0 &= ~CICR0_EOFM; @@ -935,7 +932,7 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)  static irqreturn_t pxa_camera_irq(int irq, void *data)  {  	struct pxa_camera_dev *pcdev = data; -	unsigned long status, cicr0; +	unsigned long status, cifr, cicr0;  	struct pxa_buffer *buf;  	struct videobuf_buffer *vb; @@ -949,6 +946,10 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)  	__raw_writel(status, pcdev->base + CISR);  	if (status & CISR_EOF) { +		/* Reset the FIFOs */ +		cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; +		__raw_writel(cifr, pcdev->base + CIFR); +  		pcdev->active = list_first_entry(&pcdev->capture,  					   struct pxa_buffer, vb.queue);  		vb = &pcdev->active->vb; diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 6e16b397932..1ad980f8e77 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1633,7 +1633,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,  	height = pix->height;  	pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt); -	if (pix->bytesperline < 0) +	if ((int)pix->bytesperline < 0)  		return pix->bytesperline;  	pix->sizeimage = height * pix->bytesperline; diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index a3d5728b644..f2ab025ad97 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -349,6 +349,9 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)  		goto disable;  	} +	/* If an interrupt arrived late clean up after it */ +	try_wait_for_completion(&wm831x->auxadc_done); +  	/* Ignore the result to allow us to soldier on without IRQ hookup */  	wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index e400a3bed06..b5807484b4c 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -363,6 +363,10 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)  	reg |= 1 << channel | WM8350_AUXADC_POLL;  	wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); +	/* If a late IRQ left the completion signalled then consume +	 * the completion. */ +	try_wait_for_completion(&wm8350->auxadc_done); +  	/* We ignore the result of the completion and just check for a  	 * conversion result, allowing us to soldier on if the IRQ  	 * infrastructure is not set up for the chip. */ diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmware_balloon.c index e7161c4e379..db9cd0240c6 100644 --- a/drivers/misc/vmware_balloon.c +++ b/drivers/misc/vmware_balloon.c @@ -41,7 +41,7 @@  #include <linux/workqueue.h>  #include <linux/debugfs.h>  #include <linux/seq_file.h> -#include <asm/vmware.h> +#include <asm/hypervisor.h>  MODULE_AUTHOR("VMware, Inc.");  MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver"); @@ -767,7 +767,7 @@ static int __init vmballoon_init(void)  	 * Check if we are running on VMware's hypervisor and bail out  	 * if we are not.  	 */ -	if (!vmware_platform()) +	if (x86_hyper != &x86_hyper_vmware)  		return -ENODEV;  	vmballoon_wq = create_freezeable_workqueue("vmmemctl"); diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index a6dd7da3735..336d9f553f3 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -314,8 +314,8 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)  			dmabuf = (unsigned *)tmpv;  		} +		flush_kernel_dcache_page(sg_page(sg));  		kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); -		dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount);  		data->bytes_xfered += amount;  		if (size == 0)  			break; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 88be37d9e9a..fb279f4ed8b 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -266,7 +266,7 @@ static int atmci_req_show(struct seq_file *s, void *v)  				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",  				cmd->opcode, cmd->arg, cmd->flags,  				cmd->resp[0], cmd->resp[1], cmd->resp[2], -				cmd->resp[2], cmd->error); +				cmd->resp[3], cmd->error);  		if (data)  			seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",  				data->bytes_xfered, data->blocks, @@ -276,7 +276,7 @@ static int atmci_req_show(struct seq_file *s, void *v)  				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",  				stop->opcode, stop->arg, stop->flags,  				stop->resp[0], stop->resp[1], stop->resp[2], -				stop->resp[2], stop->error); +				stop->resp[3], stop->error);  	}  	spin_unlock_bh(&slot->host->lock); @@ -569,9 +569,10 @@ static void atmci_dma_cleanup(struct atmel_mci *host)  {  	struct mmc_data			*data = host->data; -	dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, -		     ((data->flags & MMC_DATA_WRITE) -		      ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); +	if (data) +		dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, +			     ((data->flags & MMC_DATA_WRITE) +			      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));  }  static void atmci_stop_dma(struct atmel_mci *host) @@ -1099,8 +1100,8 @@ static void atmci_command_complete(struct atmel_mci *host,  			"command error: status=0x%08x\n", status);  		if (cmd->data) { -			host->data = NULL;  			atmci_stop_dma(host); +			host->data = NULL;  			mci_writel(host, IDR, MCI_NOTBUSY  					| MCI_TXRDY | MCI_RXRDY  					| ATMCI_DATA_ERROR_FLAGS); @@ -1293,6 +1294,7 @@ static void atmci_tasklet_func(unsigned long priv)  			} else {  				data->bytes_xfered = data->blocks * data->blksz;  				data->error = 0; +				mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS);  			}  			if (!data->stop) { @@ -1751,13 +1753,13 @@ static int __init atmci_probe(struct platform_device *pdev)  	ret = -ENODEV;  	if (pdata->slot[0].bus_width) {  		ret = atmci_init_slot(host, &pdata->slot[0], -				MCI_SDCSEL_SLOT_A, 0); +				0, MCI_SDCSEL_SLOT_A);  		if (!ret)  			nr_slots++;  	}  	if (pdata->slot[1].bus_width) {  		ret = atmci_init_slot(host, &pdata->slot[1], -				MCI_SDCSEL_SLOT_B, 1); +				1, MCI_SDCSEL_SLOT_B);  		if (!ret)  			nr_slots++;  	} diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 82d1e4de475..4521b1ecce4 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -4,7 +4,7 @@  # Core functionality.  obj-$(CONFIG_MTD)		+= mtd.o -mtd-y				:= mtdcore.o mtdsuper.o mtdbdi.o +mtd-y				:= mtdcore.o mtdsuper.o  mtd-$(CONFIG_MTD_PARTITIONS)	+= mtdpart.o  obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o diff --git a/drivers/mtd/internal.h b/drivers/mtd/internal.h deleted file mode 100644 index c658fe7216b..00000000000 --- a/drivers/mtd/internal.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Internal MTD definitions - * - * Copyright © 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -/* - * mtdbdi.c - */ -extern struct backing_dev_info mtd_bdi_unmappable; -extern struct backing_dev_info mtd_bdi_ro_mappable; -extern struct backing_dev_info mtd_bdi_rw_mappable; diff --git a/drivers/mtd/mtdbdi.c b/drivers/mtd/mtdbdi.c deleted file mode 100644 index 5ca5aed0b22..00000000000 --- a/drivers/mtd/mtdbdi.c +++ /dev/null @@ -1,43 +0,0 @@ -/* MTD backing device capabilities - * - * Copyright © 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/backing-dev.h> -#include <linux/mtd/mtd.h> -#include "internal.h" - -/* - * backing device capabilities for non-mappable devices (such as NAND flash) - * - permits private mappings, copies are taken of the data - */ -struct backing_dev_info mtd_bdi_unmappable = { -	.capabilities	= BDI_CAP_MAP_COPY, -}; - -/* - * backing device capabilities for R/O mappable devices (such as ROM) - * - permits private mappings, copies are taken of the data - * - permits non-writable shared mappings - */ -struct backing_dev_info mtd_bdi_ro_mappable = { -	.capabilities	= (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | -			   BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP), -}; - -/* - * backing device capabilities for writable mappable devices (such as RAM) - * - permits private mappings, copies are taken of the data - * - permits non-writable shared mappings - */ -struct backing_dev_info mtd_bdi_rw_mappable = { -	.capabilities	= (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | -			   BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP | -			   BDI_CAP_WRITE_MAP), -}; diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 5b38b17d222..b177e750efc 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -2,6 +2,9 @@   * Core registration and callback routines for MTD   * drivers and users.   * + * bdi bits are: + * Copyright © 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com)   */  #include <linux/module.h> @@ -16,11 +19,39 @@  #include <linux/init.h>  #include <linux/mtd/compatmac.h>  #include <linux/proc_fs.h> +#include <linux/backing-dev.h>  #include <linux/mtd/mtd.h> -#include "internal.h"  #include "mtdcore.h" +/* + * backing device capabilities for non-mappable devices (such as NAND flash) + * - permits private mappings, copies are taken of the data + */ +struct backing_dev_info mtd_bdi_unmappable = { +	.capabilities	= BDI_CAP_MAP_COPY, +}; + +/* + * backing device capabilities for R/O mappable devices (such as ROM) + * - permits private mappings, copies are taken of the data + * - permits non-writable shared mappings + */ +struct backing_dev_info mtd_bdi_ro_mappable = { +	.capabilities	= (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | +			   BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP), +}; + +/* + * backing device capabilities for writable mappable devices (such as RAM) + * - permits private mappings, copies are taken of the data + * - permits non-writable shared mappings + */ +struct backing_dev_info mtd_bdi_rw_mappable = { +	.capabilities	= (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | +			   BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP | +			   BDI_CAP_WRITE_MAP), +};  static int mtd_cls_suspend(struct device *dev, pm_message_t state);  static int mtd_cls_resume(struct device *dev); @@ -628,20 +659,55 @@ done:  /*====================================================================*/  /* Init code */ +static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name) +{ +	int ret; + +	ret = bdi_init(bdi); +	if (!ret) +		ret = bdi_register(bdi, NULL, name); + +	if (ret) +		bdi_destroy(bdi); + +	return ret; +} +  static int __init init_mtd(void)  {  	int ret; +  	ret = class_register(&mtd_class); +	if (ret) +		goto err_reg; + +	ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap"); +	if (ret) +		goto err_bdi1; + +	ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap"); +	if (ret) +		goto err_bdi2; + +	ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap"); +	if (ret) +		goto err_bdi3; -	if (ret) { -		pr_err("Error registering mtd class: %d\n", ret); -		return ret; -	}  #ifdef CONFIG_PROC_FS  	if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))  		proc_mtd->read_proc = mtd_read_proc;  #endif /* CONFIG_PROC_FS */  	return 0; + +err_bdi3: +	bdi_destroy(&mtd_bdi_ro_mappable); +err_bdi2: +	bdi_destroy(&mtd_bdi_unmappable); +err_bdi1: +	class_unregister(&mtd_class); +err_reg: +	pr_err("Error registering mtd class or bdi: %d\n", ret); +	return ret;  }  static void __exit cleanup_mtd(void) @@ -651,6 +717,9 @@ static void __exit cleanup_mtd(void)  		remove_proc_entry( "mtd", NULL);  #endif /* CONFIG_PROC_FS */  	class_unregister(&mtd_class); +	bdi_destroy(&mtd_bdi_unmappable); +	bdi_destroy(&mtd_bdi_ro_mappable); +	bdi_destroy(&mtd_bdi_rw_mappable);  }  module_init(init_mtd); diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index af8b42e0a55..7c003191fca 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c @@ -13,6 +13,7 @@  #include <linux/mtd/super.h>  #include <linux/namei.h>  #include <linux/ctype.h> +#include <linux/slab.h>  /*   * compare superblocks to see if they're equivalent @@ -44,6 +45,7 @@ static int get_sb_mtd_set(struct super_block *sb, void *_mtd)  	sb->s_mtd = mtd;  	sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index); +	sb->s_bdi = mtd->backing_dev_info;  	return 0;  } diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index ed5e9742be2..a8f0512bad3 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -674,6 +674,7 @@ static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = {  	{ ZORRO_PROD_AMERISTAR_A2065 },  	{ 0 }  }; +MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl);  static struct zorro_driver a2065_driver = {  	.name		= "a2065", diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index fa1a2354f5f..4b30a46486e 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -145,6 +145,7 @@ static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {      { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },      { 0 }  }; +MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);  static struct zorro_driver ariadne_driver = {      .name	= "ariadne", diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 6995169d285..cd17d09f385 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -311,11 +311,6 @@ err:  		processed++;  	} -	if (processed) { -		wrw(ep, REG_RXDENQ, processed); -		wrw(ep, REG_RXSTSENQ, processed); -	} -  	return processed;  } @@ -350,6 +345,11 @@ poll_some_more:  			goto poll_some_more;  	} +	if (rx) { +		wrw(ep, REG_RXDENQ, rx); +		wrw(ep, REG_RXSTSENQ, rx); +	} +  	return rx;  } diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a257babd1bb..ac90a3828f6 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -58,8 +58,8 @@  #include "bnx2_fw.h"  #define DRV_MODULE_NAME		"bnx2" -#define DRV_MODULE_VERSION	"2.0.8" -#define DRV_MODULE_RELDATE	"Feb 15, 2010" +#define DRV_MODULE_VERSION	"2.0.9" +#define DRV_MODULE_RELDATE	"April 27, 2010"  #define FW_MIPS_FILE_06		"bnx2/bnx2-mips-06-5.0.0.j6.fw"  #define FW_RV2P_FILE_06		"bnx2/bnx2-rv2p-06-5.0.0.j3.fw"  #define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-5.0.0.j9.fw" @@ -651,9 +651,10 @@ bnx2_napi_enable(struct bnx2 *bp)  }  static void -bnx2_netif_stop(struct bnx2 *bp) +bnx2_netif_stop(struct bnx2 *bp, bool stop_cnic)  { -	bnx2_cnic_stop(bp); +	if (stop_cnic) +		bnx2_cnic_stop(bp);  	if (netif_running(bp->dev)) {  		int i; @@ -671,14 +672,15 @@ bnx2_netif_stop(struct bnx2 *bp)  }  static void -bnx2_netif_start(struct bnx2 *bp) +bnx2_netif_start(struct bnx2 *bp, bool start_cnic)  {  	if (atomic_dec_and_test(&bp->intr_sem)) {  		if (netif_running(bp->dev)) {  			netif_tx_wake_all_queues(bp->dev);  			bnx2_napi_enable(bp);  			bnx2_enable_int(bp); -			bnx2_cnic_start(bp); +			if (start_cnic) +				bnx2_cnic_start(bp);  		}  	}  } @@ -4759,8 +4761,12 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)  		rc = bnx2_alloc_bad_rbuf(bp);  	} -	if (bp->flags & BNX2_FLAG_USING_MSIX) +	if (bp->flags & BNX2_FLAG_USING_MSIX) {  		bnx2_setup_msix_tbl(bp); +		/* Prevent MSIX table reads and write from timing out */ +		REG_WR(bp, BNX2_MISC_ECO_HW_CTL, +			BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN); +	}  	return rc;  } @@ -6273,12 +6279,12 @@ bnx2_reset_task(struct work_struct *work)  		return;  	} -	bnx2_netif_stop(bp); +	bnx2_netif_stop(bp, true);  	bnx2_init_nic(bp, 1);  	atomic_set(&bp->intr_sem, 1); -	bnx2_netif_start(bp); +	bnx2_netif_start(bp, true);  	rtnl_unlock();  } @@ -6320,7 +6326,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)  	struct bnx2 *bp = netdev_priv(dev);  	if (netif_running(dev)) -		bnx2_netif_stop(bp); +		bnx2_netif_stop(bp, false);  	bp->vlgrp = vlgrp; @@ -6331,7 +6337,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)  	if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)  		bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1); -	bnx2_netif_start(bp); +	bnx2_netif_start(bp, false);  }  #endif @@ -7051,9 +7057,9 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)  	bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS;  	if (netif_running(bp->dev)) { -		bnx2_netif_stop(bp); +		bnx2_netif_stop(bp, true);  		bnx2_init_nic(bp, 0); -		bnx2_netif_start(bp); +		bnx2_netif_start(bp, true);  	}  	return 0; @@ -7083,7 +7089,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)  		/* Reset will erase chipset stats; save them */  		bnx2_save_stats(bp); -		bnx2_netif_stop(bp); +		bnx2_netif_stop(bp, true);  		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);  		bnx2_free_skbs(bp);  		bnx2_free_mem(bp); @@ -7111,7 +7117,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)  			bnx2_setup_cnic_irq_info(bp);  		mutex_unlock(&bp->cnic_lock);  #endif -		bnx2_netif_start(bp); +		bnx2_netif_start(bp, true);  	}  	return 0;  } @@ -7364,7 +7370,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)  	if (etest->flags & ETH_TEST_FL_OFFLINE) {  		int i; -		bnx2_netif_stop(bp); +		bnx2_netif_stop(bp, true);  		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG);  		bnx2_free_skbs(bp); @@ -7383,7 +7389,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)  			bnx2_shutdown_chip(bp);  		else {  			bnx2_init_nic(bp, 1); -			bnx2_netif_start(bp); +			bnx2_netif_start(bp, true);  		}  		/* wait for link up */ @@ -8377,7 +8383,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)  		return 0;  	flush_scheduled_work(); -	bnx2_netif_stop(bp); +	bnx2_netif_stop(bp, true);  	netif_device_detach(dev);  	del_timer_sync(&bp->timer);  	bnx2_shutdown_chip(bp); @@ -8399,7 +8405,7 @@ bnx2_resume(struct pci_dev *pdev)  	bnx2_set_power_state(bp, PCI_D0);  	netif_device_attach(dev);  	bnx2_init_nic(bp, 1); -	bnx2_netif_start(bp); +	bnx2_netif_start(bp, true);  	return 0;  } @@ -8426,7 +8432,7 @@ static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,  	}  	if (netif_running(dev)) { -		bnx2_netif_stop(bp); +		bnx2_netif_stop(bp, true);  		del_timer_sync(&bp->timer);  		bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);  	} @@ -8483,7 +8489,7 @@ static void bnx2_io_resume(struct pci_dev *pdev)  	rtnl_lock();  	if (netif_running(dev)) -		bnx2_netif_start(bp); +		bnx2_netif_start(bp, true);  	netif_device_attach(dev);  	rtnl_unlock(); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index aced6c5e635..e3f1b856649 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -439,7 +439,7 @@ static void free_irq_resources(struct adapter *adapter)  static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt,  			      unsigned long n)  { -	int attempts = 5; +	int attempts = 10;  	while (adap->sge.qs[0].rspq.offload_pkts < init_cnt + n) {  		if (!--attempts) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 712ccc66ba2..90155552ea0 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -336,7 +336,6 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)  	struct e1000_hw *hw = &adapter->hw;  	static int global_quad_port_a; /* global port a indication */  	struct pci_dev *pdev = adapter->pdev; -	u16 eeprom_data = 0;  	int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;  	s32 rc; @@ -387,16 +386,15 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)  		if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)  			adapter->flags &= ~FLAG_HAS_WOL;  		break; -  	case e1000_82573: +	case e1000_82574: +	case e1000_82583: +		/* Disable ASPM L0s due to hardware errata */ +		e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L0S); +  		if (pdev->device == E1000_DEV_ID_82573L) { -			if (e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1, -				       &eeprom_data) < 0) -				break; -			if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) { -				adapter->flags |= FLAG_HAS_JUMBO_FRAMES; -				adapter->max_hw_frame_size = DEFAULT_JUMBO; -			} +			adapter->flags |= FLAG_HAS_JUMBO_FRAMES; +			adapter->max_hw_frame_size = DEFAULT_JUMBO;  		}  		break;  	default: @@ -1792,6 +1790,7 @@ struct e1000_info e1000_82571_info = {  				  | FLAG_RESET_OVERWRITES_LAA /* errata */  				  | FLAG_TARC_SPEED_MODE_BIT /* errata */  				  | FLAG_APME_CHECK_PORT_B, +	.flags2			= FLAG2_DISABLE_ASPM_L1, /* errata 13 */  	.pba			= 38,  	.max_hw_frame_size	= DEFAULT_JUMBO,  	.get_variants		= e1000_get_variants_82571, @@ -1809,6 +1808,7 @@ struct e1000_info e1000_82572_info = {  				  | FLAG_RX_CSUM_ENABLED  				  | FLAG_HAS_CTRLEXT_ON_LOAD  				  | FLAG_TARC_SPEED_MODE_BIT, /* errata */ +	.flags2			= FLAG2_DISABLE_ASPM_L1, /* errata 13 */  	.pba			= 38,  	.max_hw_frame_size	= DEFAULT_JUMBO,  	.get_variants		= e1000_get_variants_82571, @@ -1820,13 +1820,11 @@ struct e1000_info e1000_82572_info = {  struct e1000_info e1000_82573_info = {  	.mac			= e1000_82573,  	.flags			= FLAG_HAS_HW_VLAN_FILTER -				  | FLAG_HAS_JUMBO_FRAMES  				  | FLAG_HAS_WOL  				  | FLAG_APME_IN_CTRL3  				  | FLAG_RX_CSUM_ENABLED  				  | FLAG_HAS_SMART_POWER_DOWN  				  | FLAG_HAS_AMT -				  | FLAG_HAS_ERT  				  | FLAG_HAS_SWSM_ON_LOAD,  	.pba			= 20,  	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN, diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 118bdf48359..ee32b9b27a9 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -37,6 +37,7 @@  #include <linux/io.h>  #include <linux/netdevice.h>  #include <linux/pci.h> +#include <linux/pci-aspm.h>  #include "hw.h" @@ -374,7 +375,7 @@ struct e1000_adapter {  struct e1000_info {  	enum e1000_mac_type	mac;  	unsigned int		flags; -	unsigned int            flags2; +	unsigned int		flags2;  	u32			pba;  	u32			max_hw_frame_size;  	s32			(*get_variants)(struct e1000_adapter *); @@ -421,6 +422,7 @@ struct e1000_info {  #define FLAG2_CRC_STRIPPING               (1 << 0)  #define FLAG2_HAS_PHY_WAKEUP              (1 << 1)  #define FLAG2_IS_DISCARDING               (1 << 2) +#define FLAG2_DISABLE_ASPM_L1             (1 << 3)  #define E1000_RX_DESC_PS(R, i)	    \  	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) @@ -461,6 +463,7 @@ extern void e1000e_update_stats(struct e1000_adapter *adapter);  extern bool e1000e_has_link(struct e1000_adapter *adapter);  extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);  extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); +extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);  extern unsigned int copybreak; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 73d43c53015..dbf81788bb4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4283,6 +4283,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)  		return -EINVAL;  	} +	/* 82573 Errata 17 */ +	if (((adapter->hw.mac.type == e1000_82573) || +	     (adapter->hw.mac.type == e1000_82574)) && +	    (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) { +		adapter->flags2 |= FLAG2_DISABLE_ASPM_L1; +		e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1); +	} +  	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))  		msleep(1);  	/* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ @@ -4605,29 +4613,42 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,  	}  } -static void e1000e_disable_l1aspm(struct pci_dev *pdev) +#ifdef CONFIG_PCIEASPM +static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) +{ +	pci_disable_link_state(pdev, state); +} +#else +static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)  {  	int pos; -	u16 val; +	u16 reg16;  	/* -	 * 82573 workaround - disable L1 ASPM on mobile chipsets -	 * -	 * L1 ASPM on various mobile (ich7) chipsets do not behave properly -	 * resulting in lost data or garbage information on the pci-e link -	 * level. This could result in (false) bad EEPROM checksum errors, -	 * long ping times (up to 2s) or even a system freeze/hang. -	 * -	 * Unfortunately this feature saves about 1W power consumption when -	 * active. +	 * Both device and parent should have the same ASPM setting. +	 * Disable ASPM in downstream component first and then upstream.  	 */ -	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); -	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val); -	if (val & 0x2) { -		dev_warn(&pdev->dev, "Disabling L1 ASPM\n"); -		val &= ~0x2; -		pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val); -	} +	pos = pci_pcie_cap(pdev); +	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); +	reg16 &= ~state; +	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); + +	if (!pdev->bus->self) +		return; + +	pos = pci_pcie_cap(pdev->bus->self); +	pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); +	reg16 &= ~state; +	pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16); +} +#endif +void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) +{ +	dev_info(&pdev->dev, "Disabling ASPM %s %s\n", +		 (state & PCIE_LINK_STATE_L0S) ? "L0s" : "", +		 (state & PCIE_LINK_STATE_L1) ? "L1" : ""); + +	__e1000e_disable_aspm(pdev, state);  }  #ifdef CONFIG_PM @@ -4653,7 +4674,8 @@ static int e1000_resume(struct pci_dev *pdev)  	pci_set_power_state(pdev, PCI_D0);  	pci_restore_state(pdev);  	pci_save_state(pdev); -	e1000e_disable_l1aspm(pdev); +	if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) +		e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);  	err = pci_enable_device_mem(pdev);  	if (err) { @@ -4795,7 +4817,8 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)  	int err;  	pci_ers_result_t result; -	e1000e_disable_l1aspm(pdev); +	if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) +		e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);  	err = pci_enable_device_mem(pdev);  	if (err) {  		dev_err(&pdev->dev, @@ -4889,13 +4912,6 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)  		dev_warn(&adapter->pdev->dev,  			 "Warning: detected DSPD enabled in EEPROM\n");  	} - -	ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf); -	if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) { -		/* ASPM enable */ -		dev_warn(&adapter->pdev->dev, -			 "Warning: detected ASPM enabled in EEPROM\n"); -	}  }  static const struct net_device_ops e1000e_netdev_ops = { @@ -4944,7 +4960,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,  	u16 eeprom_data = 0;  	u16 eeprom_apme_mask = E1000_EEPROM_APME; -	e1000e_disable_l1aspm(pdev); +	if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) +		e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);  	err = pci_enable_device_mem(pdev);  	if (err) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 9f98c1c4a34..9b4e8f797a7 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1653,7 +1653,7 @@ fec_set_mac_address(struct net_device *dev, void *p)  		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),  		fep->hwp + FEC_ADDR_LOW);  	writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), -		fep + FEC_ADDR_HIGH); +		fep->hwp + FEC_ADDR_HIGH);  	return 0;  } diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index df49af38215..5d3763fb347 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1511,9 +1511,9 @@ static void gfar_halt_nodisable(struct net_device *dev)  		tempval |= (DMACTRL_GRS | DMACTRL_GTS);  		gfar_write(®s->dmactrl, tempval); -		while (!(gfar_read(®s->ievent) & -			 (IEVENT_GRSC | IEVENT_GTSC))) -			cpu_relax(); +		spin_event_timeout(((gfar_read(®s->ievent) & +			 (IEVENT_GRSC | IEVENT_GTSC)) == +			 (IEVENT_GRSC | IEVENT_GTSC)), -1, 0);  	}  } @@ -1649,6 +1649,7 @@ static void free_skb_resources(struct gfar_private *priv)  			sizeof(struct rxbd8) * priv->total_rx_ring_size,  			priv->tx_queue[0]->tx_bd_base,  			priv->tx_queue[0]->tx_bd_dma_base); +	skb_queue_purge(&priv->rx_recycle);  }  void gfar_start(struct net_device *dev) @@ -2088,7 +2089,6 @@ static int gfar_close(struct net_device *dev)  	disable_napi(priv); -	skb_queue_purge(&priv->rx_recycle);  	cancel_work_sync(&priv->reset_task);  	stop_gfar(dev); diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 24724b4ad70..07d8e5b634f 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -71,6 +71,7 @@ static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {      { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },      { 0 }  }; +MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);  static struct zorro_driver hydra_driver = {      .name	= "hydra", diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index b405a00817c..12fc0e7ba2c 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -39,6 +39,8 @@  #define IXGBE_82599_MC_TBL_SIZE   128  #define IXGBE_82599_VFT_TBL_SIZE  128 +void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); +void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);  void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);  s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,                                            ixgbe_link_speed speed, @@ -69,8 +71,14 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)  	if (hw->phy.multispeed_fiber) {  		/* Set up dual speed SFP+ support */  		mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; +		mac->ops.disable_tx_laser = +		                       &ixgbe_disable_tx_laser_multispeed_fiber; +		mac->ops.enable_tx_laser = +		                        &ixgbe_enable_tx_laser_multispeed_fiber;  		mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;  	} else { +		mac->ops.disable_tx_laser = NULL; +		mac->ops.enable_tx_laser = NULL;  		mac->ops.flap_tx_laser = NULL;  		if ((mac->ops.get_media_type(hw) ==  		     ixgbe_media_type_backplane) && @@ -415,6 +423,44 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,  	return status;  } + /** +  *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser +  *  @hw: pointer to hardware structure +  * +  *  The base drivers may require better control over SFP+ module +  *  PHY states.  This includes selectively shutting down the Tx +  *  laser on the PHY, effectively halting physical link. +  **/ +void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) +{ +	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); + +	/* Disable tx laser; allow 100us to go dark per spec */ +	esdp_reg |= IXGBE_ESDP_SDP3; +	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); +	IXGBE_WRITE_FLUSH(hw); +	udelay(100); +} + +/** + *  ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser + *  @hw: pointer to hardware structure + * + *  The base drivers may require better control over SFP+ module + *  PHY states.  This includes selectively turning on the Tx + *  laser on the PHY, effectively starting physical link. + **/ +void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) +{ +	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); + +	/* Enable tx laser; allow 100ms to light up */ +	esdp_reg &= ~IXGBE_ESDP_SDP3; +	IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); +	IXGBE_WRITE_FLUSH(hw); +	msleep(100); +} +  /**   *  ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser   *  @hw: pointer to hardware structure @@ -429,23 +475,11 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,   **/  void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)  { -	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); -  	hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n");  	if (hw->mac.autotry_restart) { -		/* Disable tx laser; allow 100us to go dark per spec */ -		esdp_reg |= IXGBE_ESDP_SDP3; -		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); -		IXGBE_WRITE_FLUSH(hw); -		udelay(100); - -		/* Enable tx laser; allow 100ms to light up */ -		esdp_reg &= ~IXGBE_ESDP_SDP3; -		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); -		IXGBE_WRITE_FLUSH(hw); -		msleep(100); - +		ixgbe_disable_tx_laser_multispeed_fiber(hw); +		ixgbe_enable_tx_laser_multispeed_fiber(hw);  		hw->mac.autotry_restart = false;  	}  } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 8f677cb8629..6c00ee493a3 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2982,6 +2982,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)  	else  		ixgbe_configure_msi_and_legacy(adapter); +	/* enable the optics */ +	if (hw->phy.multispeed_fiber) +		hw->mac.ops.enable_tx_laser(hw); +  	clear_bit(__IXGBE_DOWN, &adapter->state);  	ixgbe_napi_enable_all(adapter); @@ -3243,6 +3247,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)  	/* signal that we are down to the interrupt handler */  	set_bit(__IXGBE_DOWN, &adapter->state); +	/* power down the optics */ +	if (hw->phy.multispeed_fiber) +		hw->mac.ops.disable_tx_laser(hw); +  	/* disable receive for all VFs and wait one second */  	if (adapter->num_vfs) {  		/* ping all the active vfs to let them know we are going down */ @@ -6253,6 +6261,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,  		goto err_eeprom;  	} +	/* power down the optics */ +	if (hw->phy.multispeed_fiber) +		hw->mac.ops.disable_tx_laser(hw); +  	init_timer(&adapter->watchdog_timer);  	adapter->watchdog_timer.function = &ixgbe_watchdog;  	adapter->watchdog_timer.data = (unsigned long)adapter; @@ -6400,16 +6412,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)  	del_timer_sync(&adapter->sfp_timer);  	cancel_work_sync(&adapter->watchdog_task);  	cancel_work_sync(&adapter->sfp_task); -	if (adapter->hw.phy.multispeed_fiber) { -		struct ixgbe_hw *hw = &adapter->hw; -		/* -		 * Restart clause 37 autoneg, disable and re-enable -		 * the tx laser, to clear & alert the link partner -		 * that it needs to restart autotry -		 */ -		hw->mac.autotry_restart = true; -		hw->mac.ops.flap_tx_laser(hw); -	}  	cancel_work_sync(&adapter->multispeed_fiber_task);  	cancel_work_sync(&adapter->sfp_config_module_task);  	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 4ec6dc1a5b7..534affcc38c 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -2398,6 +2398,8 @@ struct ixgbe_mac_operations {  	s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);  	/* Link */ +	void (*disable_tx_laser)(struct ixgbe_hw *); +	void (*enable_tx_laser)(struct ixgbe_hw *);  	void (*flap_tx_laser)(struct ixgbe_hw *);  	s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool);  	s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index fd9d6e34fda..ccc553782a0 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1804,23 +1804,30 @@ static void media_check(u_long arg)      SMC_SELECT_BANK(1);      media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1; +    SMC_SELECT_BANK(saved_bank); +    spin_unlock_irqrestore(&smc->lock, flags); +      /* Check for pending interrupt with watchdog flag set: with         this, we can limp along even if the interrupt is blocked */      if (smc->watchdog++ && ((i>>8) & i)) {  	if (!smc->fast_poll)  	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); +	local_irq_save(flags);  	smc_interrupt(dev->irq, dev); +	local_irq_restore(flags);  	smc->fast_poll = HZ;      }      if (smc->fast_poll) {  	smc->fast_poll--;  	smc->media.expires = jiffies + HZ/100;  	add_timer(&smc->media); -	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irqrestore(&smc->lock, flags);  	return;      } +    spin_lock_irqsave(&smc->lock, flags); + +    saved_bank = inw(ioaddr + BANK_SELECT); +      if (smc->cfg & CFG_MII_SELECT) {  	if (smc->mii_if.phy_id < 0)  	    goto reschedule; @@ -1978,15 +1985,16 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  	unsigned int ioaddr = dev->base_addr;  	u16 saved_bank = inw(ioaddr + BANK_SELECT);  	int ret; +	unsigned long flags; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	SMC_SELECT_BANK(3);  	if (smc->cfg & CFG_MII_SELECT)  		ret = mii_ethtool_gset(&smc->mii_if, ecmd);  	else  		ret = smc_netdev_get_ecmd(dev, ecmd);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return ret;  } @@ -1996,15 +2004,16 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  	unsigned int ioaddr = dev->base_addr;  	u16 saved_bank = inw(ioaddr + BANK_SELECT);  	int ret; +	unsigned long flags; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	SMC_SELECT_BANK(3);  	if (smc->cfg & CFG_MII_SELECT)  		ret = mii_ethtool_sset(&smc->mii_if, ecmd);  	else  		ret = smc_netdev_set_ecmd(dev, ecmd);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return ret;  } @@ -2014,12 +2023,13 @@ static u32 smc_get_link(struct net_device *dev)  	unsigned int ioaddr = dev->base_addr;  	u16 saved_bank = inw(ioaddr + BANK_SELECT);  	u32 ret; +	unsigned long flags; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	SMC_SELECT_BANK(3);  	ret = smc_link_ok(dev);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return ret;  } @@ -2056,16 +2066,17 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)  	int rc = 0;  	u16 saved_bank;  	unsigned int ioaddr = dev->base_addr; +	unsigned long flags;  	if (!netif_running(dev))  		return -EINVAL; -	spin_lock_irq(&smc->lock); +	spin_lock_irqsave(&smc->lock, flags);  	saved_bank = inw(ioaddr + BANK_SELECT);  	SMC_SELECT_BANK(3);  	rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);  	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irq(&smc->lock); +	spin_unlock_irqrestore(&smc->lock, flags);  	return rc;  } diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index fc5938ba3d7..a527e37728c 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -88,6 +88,11 @@ config LSI_ET1011C_PHY  	---help---  	  Supports the LSI ET1011C PHY. +config MICREL_PHY +	tristate "Driver for Micrel PHYs" +	---help--- +	  Supports the KSZ9021, VSC8201, KS8001 PHYs. +  config FIXED_PHY  	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"  	depends on PHYLIB=y diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1342585af38..13bebab65d0 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o  obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o  obj-$(CONFIG_NATIONAL_PHY)	+= national.o  obj-$(CONFIG_STE10XP)		+= ste10Xp.o +obj-$(CONFIG_MICREL_PHY)	+= micrel.o  obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c index a872aea4ed7..f443d43edd8 100644 --- a/drivers/net/phy/mdio-octeon.c +++ b/drivers/net/phy/mdio-octeon.c @@ -88,6 +88,7 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,  static int __init octeon_mdiobus_probe(struct platform_device *pdev)  {  	struct octeon_mdiobus *bus; +	union cvmx_smix_en smi_en;  	int i;  	int err = -ENOENT; @@ -103,6 +104,10 @@ static int __init octeon_mdiobus_probe(struct platform_device *pdev)  	if (!bus->mii_bus)  		goto err; +	smi_en.u64 = 0; +	smi_en.s.en = 1; +	cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); +  	/*  	 * Standard Octeon evaluation boards don't support phy  	 * interrupts, we need to poll. @@ -133,17 +138,22 @@ err_register:  err:  	devm_kfree(&pdev->dev, bus); +	smi_en.u64 = 0; +	cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);  	return err;  }  static int __exit octeon_mdiobus_remove(struct platform_device *pdev)  {  	struct octeon_mdiobus *bus; +	union cvmx_smix_en smi_en;  	bus = dev_get_drvdata(&pdev->dev);  	mdiobus_unregister(bus->mii_bus);  	mdiobus_free(bus->mii_bus); +	smi_en.u64 = 0; +	cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);  	return 0;  } diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c new file mode 100644 index 00000000000..e67691dca4a --- /dev/null +++ b/drivers/net/phy/micrel.c @@ -0,0 +1,105 @@ +/* + * drivers/net/phy/micrel.c + * + * Driver for Micrel PHYs + * + * Author: David J. Choi + * + * Copyright (c) 2010 Micrel, Inc. + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + * + * Support : ksz9021 , vsc8201, ks8001 + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/phy.h> + +#define	PHY_ID_KSZ9021			0x00221611 +#define	PHY_ID_VSC8201			0x000FC413 +#define	PHY_ID_KS8001			0x0022161A + + +static int kszphy_config_init(struct phy_device *phydev) +{ +	return 0; +} + + +static struct phy_driver ks8001_driver = { +	.phy_id		= PHY_ID_KS8001, +	.name		= "Micrel KS8001", +	.phy_id_mask	= 0x00fffff0, +	.features	= PHY_BASIC_FEATURES, +	.flags		= PHY_POLL, +	.config_init	= kszphy_config_init, +	.config_aneg	= genphy_config_aneg, +	.read_status	= genphy_read_status, +	.driver		= { .owner = THIS_MODULE,}, +}; + +static struct phy_driver vsc8201_driver = { +	.phy_id		= PHY_ID_VSC8201, +	.name		= "Micrel VSC8201", +	.phy_id_mask	= 0x00fffff0, +	.features	= PHY_BASIC_FEATURES, +	.flags		= PHY_POLL, +	.config_init	= kszphy_config_init, +	.config_aneg	= genphy_config_aneg, +	.read_status	= genphy_read_status, +	.driver		= { .owner = THIS_MODULE,}, +}; + +static struct phy_driver ksz9021_driver = { +	.phy_id		= PHY_ID_KSZ9021, +	.phy_id_mask	= 0x000fff10, +	.name		= "Micrel KSZ9021 Gigabit PHY", +	.features	= PHY_GBIT_FEATURES | SUPPORTED_Pause, +	.flags		= PHY_POLL, +	.config_init	= kszphy_config_init, +	.config_aneg	= genphy_config_aneg, +	.read_status	= genphy_read_status, +	.driver		= { .owner = THIS_MODULE, }, +}; + +static int __init ksphy_init(void) +{ +	int ret; + +	ret = phy_driver_register(&ks8001_driver); +	if (ret) +		goto err1; +	ret = phy_driver_register(&vsc8201_driver); +	if (ret) +		goto err2; + +	ret = phy_driver_register(&ksz9021_driver); +	if (ret) +		goto err3; +	return 0; + +err3: +	phy_driver_unregister(&vsc8201_driver); +err2: +	phy_driver_unregister(&ks8001_driver); +err1: +	return ret; +} + +static void __exit ksphy_exit(void) +{ +	phy_driver_unregister(&ks8001_driver); +	phy_driver_unregister(&vsc8201_driver); +	phy_driver_unregister(&ksz9021_driver); +} + +module_init(ksphy_init); +module_exit(ksphy_exit); + +MODULE_DESCRIPTION("Micrel PHY driver"); +MODULE_AUTHOR("David J. Choi"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6e281bc825e..8518a2e58e5 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -405,6 +405,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,  	DECLARE_WAITQUEUE(wait, current);  	ssize_t ret;  	struct sk_buff *skb = NULL; +	struct iovec iov;  	ret = count; @@ -448,7 +449,9 @@ static ssize_t ppp_read(struct file *file, char __user *buf,  	if (skb->len > count)  		goto outf;  	ret = -EFAULT; -	if (copy_to_user(buf, skb->data, skb->len)) +	iov.iov_base = buf; +	iov.iov_len = count; +	if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len))  		goto outf;  	ret = skb->len; @@ -1567,13 +1570,22 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)  	struct channel *pch = chan->ppp;  	int proto; -	if (!pch || skb->len == 0) { +	if (!pch) {  		kfree_skb(skb);  		return;  	} -	proto = PPP_PROTO(skb);  	read_lock_bh(&pch->upl); +	if (!pskb_may_pull(skb, 2)) { +		kfree_skb(skb); +		if (pch->ppp) { +			++pch->ppp->dev->stats.rx_length_errors; +			ppp_receive_error(pch->ppp); +		} +		goto done; +	} + +	proto = PPP_PROTO(skb);  	if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) {  		/* put it on the channel queue */  		skb_queue_tail(&pch->file.rq, skb); @@ -1585,6 +1597,8 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)  	} else {  		ppp_do_recv(pch->ppp, skb, pch);  	} + +done:  	read_unlock_bh(&pch->upl);  } @@ -1617,7 +1631,8 @@ ppp_input_error(struct ppp_channel *chan, int code)  static void  ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)  { -	if (pskb_may_pull(skb, 2)) { +	/* note: a 0-length skb is used as an error indication */ +	if (skb->len > 0) {  #ifdef CONFIG_PPP_MULTILINK  		/* XXX do channel-level decompression here */  		if (PPP_PROTO(skb) == PPP_MP) @@ -1625,15 +1640,10 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)  		else  #endif /* CONFIG_PPP_MULTILINK */  			ppp_receive_nonmp_frame(ppp, skb); -		return; +	} else { +		kfree_skb(skb); +		ppp_receive_error(ppp);  	} - -	if (skb->len > 0) -		/* note: a 0-length skb is used as an error indication */ -		++ppp->dev->stats.rx_length_errors; - -	kfree_skb(skb); -	ppp_receive_error(ppp);  }  static void diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index dbb1f5a1824..dd8106ff35a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1042,14 +1042,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev,  }  static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, -			       struct sk_buff *skb) +			       struct sk_buff *skb, int polling)  {  	u32 opts2 = le32_to_cpu(desc->opts2);  	struct vlan_group *vlgrp = tp->vlgrp;  	int ret;  	if (vlgrp && (opts2 & RxVlanTag)) { -		vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); +		__vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling);  		ret = 0;  	} else  		ret = -1; @@ -1066,7 +1066,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,  }  static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, -			       struct sk_buff *skb) +			       struct sk_buff *skb, int polling)  {  	return -1;  } @@ -2759,6 +2759,7 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,  {  	iounmap(ioaddr);  	pci_release_regions(pdev); +	pci_clear_mwi(pdev);  	pci_disable_device(pdev);  	free_netdev(dev);  } @@ -2825,8 +2826,13 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)  	spin_lock_irq(&tp->lock);  	RTL_W8(Cfg9346, Cfg9346_Unlock); +  	RTL_W32(MAC4, high); +	RTL_R32(MAC4); +  	RTL_W32(MAC0, low); +	RTL_R32(MAC0); +  	RTL_W8(Cfg9346, Cfg9346_Lock);  	spin_unlock_irq(&tp->lock); @@ -3014,9 +3020,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		goto err_out_free_dev_1;  	} -	rc = pci_set_mwi(pdev); -	if (rc < 0) -		goto err_out_disable_2; +	if (pci_set_mwi(pdev) < 0) +		netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");  	/* make sure PCI base addr 1 is MMIO */  	if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { @@ -3024,7 +3029,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  			  "region #%d not an MMIO resource, aborting\n",  			  region);  		rc = -ENODEV; -		goto err_out_mwi_3; +		goto err_out_mwi_2;  	}  	/* check for weird/broken PCI region reporting */ @@ -3032,13 +3037,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		netif_err(tp, probe, dev,  			  "Invalid PCI region size(s), aborting\n");  		rc = -ENODEV; -		goto err_out_mwi_3; +		goto err_out_mwi_2;  	}  	rc = pci_request_regions(pdev, MODULENAME);  	if (rc < 0) {  		netif_err(tp, probe, dev, "could not request regions\n"); -		goto err_out_mwi_3; +		goto err_out_mwi_2;  	}  	tp->cp_cmd = PCIMulRW | RxChkSum; @@ -3051,7 +3056,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc < 0) {  			netif_err(tp, probe, dev, "DMA configuration failed\n"); -			goto err_out_free_res_4; +			goto err_out_free_res_3;  		}  	} @@ -3060,7 +3065,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (!ioaddr) {  		netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");  		rc = -EIO; -		goto err_out_free_res_4; +		goto err_out_free_res_3;  	}  	tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); @@ -3102,7 +3107,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (i == ARRAY_SIZE(rtl_chip_info)) {  		dev_err(&pdev->dev,  			"driver bug, MAC version not found in rtl_chip_info\n"); -		goto err_out_msi_5; +		goto err_out_msi_4;  	}  	tp->chipset = i; @@ -3167,7 +3172,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	rc = register_netdev(dev);  	if (rc < 0) -		goto err_out_msi_5; +		goto err_out_msi_4;  	pci_set_drvdata(pdev, dev); @@ -3190,14 +3195,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  out:  	return rc; -err_out_msi_5: +err_out_msi_4:  	rtl_disable_msi(pdev, tp);  	iounmap(ioaddr); -err_out_free_res_4: +err_out_free_res_3:  	pci_release_regions(pdev); -err_out_mwi_3: +err_out_mwi_2:  	pci_clear_mwi(pdev); -err_out_disable_2:  	pci_disable_device(pdev);  err_out_free_dev_1:  	free_netdev(dev); @@ -4441,12 +4445,20 @@ out:  	return done;  } +/* + * Warning : rtl8169_rx_interrupt() might be called : + * 1) from NAPI (softirq) context + *	(polling = 1 : we should call netif_receive_skb()) + * 2) from process context (rtl8169_reset_task()) + *	(polling = 0 : we must call netif_rx() instead) + */  static int rtl8169_rx_interrupt(struct net_device *dev,  				struct rtl8169_private *tp,  				void __iomem *ioaddr, u32 budget)  {  	unsigned int cur_rx, rx_left;  	unsigned int delta, count; +	int polling = (budget != ~(u32)0) ? 1 : 0;  	cur_rx = tp->cur_rx;  	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; @@ -4508,8 +4520,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev,  			skb_put(skb, pkt_size);  			skb->protocol = eth_type_trans(skb, dev); -			if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) -				netif_receive_skb(skb); +			if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { +				if (likely(polling)) +					netif_receive_skb(skb); +				else +					netif_rx(skb); +			}  			dev->stats.rx_bytes += pkt_size;  			dev->stats.rx_packets++; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 9944e5d662c..04efc0c1bda 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2353,17 +2353,36 @@ static int sbmac_init(struct platform_device *pldev, long long base)  	sc->mii_bus = mdiobus_alloc();  	if (sc->mii_bus == NULL) { -		sbmac_uninitctx(sc); -		return -ENOMEM; +		err = -ENOMEM; +		goto uninit_ctx;  	} +	sc->mii_bus->name = sbmac_mdio_string; +	snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); +	sc->mii_bus->priv = sc; +	sc->mii_bus->read = sbmac_mii_read; +	sc->mii_bus->write = sbmac_mii_write; +	sc->mii_bus->irq = sc->phy_irq; +	for (i = 0; i < PHY_MAX_ADDR; ++i) +		sc->mii_bus->irq[i] = SBMAC_PHY_INT; + +	sc->mii_bus->parent = &pldev->dev; +	/* +	 * Probe PHY address +	 */ +	err = mdiobus_register(sc->mii_bus); +	if (err) { +		printk(KERN_ERR "%s: unable to register MDIO bus\n", +		       dev->name); +		goto free_mdio; +	} +	dev_set_drvdata(&pldev->dev, sc->mii_bus); +  	err = register_netdev(dev);  	if (err) {  		printk(KERN_ERR "%s.%d: unable to register netdev\n",  		       sbmac_string, idx); -		mdiobus_free(sc->mii_bus); -		sbmac_uninitctx(sc); -		return err; +		goto unreg_mdio;  	}  	pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); @@ -2379,19 +2398,15 @@ static int sbmac_init(struct platform_device *pldev, long long base)  	pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n",  	       dev->name, base, eaddr); -	sc->mii_bus->name = sbmac_mdio_string; -	snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); -	sc->mii_bus->priv = sc; -	sc->mii_bus->read = sbmac_mii_read; -	sc->mii_bus->write = sbmac_mii_write; -	sc->mii_bus->irq = sc->phy_irq; -	for (i = 0; i < PHY_MAX_ADDR; ++i) -		sc->mii_bus->irq[i] = SBMAC_PHY_INT; - -	sc->mii_bus->parent = &pldev->dev; -	dev_set_drvdata(&pldev->dev, sc->mii_bus); -  	return 0; +unreg_mdio: +	mdiobus_unregister(sc->mii_bus); +	dev_set_drvdata(&pldev->dev, NULL); +free_mdio: +	mdiobus_free(sc->mii_bus); +uninit_ctx: +	sbmac_uninitctx(sc); +	return err;  } @@ -2417,16 +2432,6 @@ static int sbmac_open(struct net_device *dev)  		goto out_err;  	} -	/* -	 * Probe PHY address -	 */ -	err = mdiobus_register(sc->mii_bus); -	if (err) { -		printk(KERN_ERR "%s: unable to register MDIO bus\n", -		       dev->name); -		goto out_unirq; -	} -  	sc->sbm_speed = sbmac_speed_none;  	sc->sbm_duplex = sbmac_duplex_none;  	sc->sbm_fc = sbmac_fc_none; @@ -2457,11 +2462,7 @@ static int sbmac_open(struct net_device *dev)  	return 0;  out_unregister: -	mdiobus_unregister(sc->mii_bus); - -out_unirq:  	free_irq(dev->irq, dev); -  out_err:  	return err;  } @@ -2650,9 +2651,6 @@ static int sbmac_close(struct net_device *dev)  	phy_disconnect(sc->phy_dev);  	sc->phy_dev = NULL; - -	mdiobus_unregister(sc->mii_bus); -  	free_irq(dev->irq, dev);  	sbdma_emptyring(&(sc->sbm_txdma)); @@ -2760,6 +2758,7 @@ static int __exit sbmac_remove(struct platform_device *pldev)  	unregister_netdev(dev);  	sbmac_uninitctx(sc); +	mdiobus_unregister(sc->mii_bus);  	mdiobus_free(sc->mii_bus);  	iounmap(sc->sbm_base);  	free_netdev(dev); diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 6486657c47b..649a264d6a8 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1861,6 +1861,7 @@ out:  	}  	if (disabled) { +		dev_close(efx->net_dev);  		EFX_ERR(efx, "has been disabled\n");  		efx->state = STATE_DISABLED;  	} else { @@ -1884,8 +1885,7 @@ static void efx_reset_work(struct work_struct *data)  	}  	rtnl_lock(); -	if (efx_reset(efx, efx->reset_pending)) -		dev_close(efx->net_dev); +	(void)efx_reset(efx, efx->reset_pending);  	rtnl_unlock();  } diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d294d66fd60..08278e7302b 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1320,7 +1320,9 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)  	EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad); -	falcon_probe_board(efx, board_rev); +	rc = falcon_probe_board(efx, board_rev); +	if (rc) +		goto fail2;  	kfree(nvconfig);  	return 0; diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c index 5712fddd72f..c7a933a3292 100644 --- a/drivers/net/sfc/falcon_boards.c +++ b/drivers/net/sfc/falcon_boards.c @@ -728,15 +728,7 @@ static const struct falcon_board_type board_types[] = {  	},  }; -static const struct falcon_board_type falcon_dummy_board = { -	.init		= efx_port_dummy_op_int, -	.init_phy	= efx_port_dummy_op_void, -	.fini		= efx_port_dummy_op_void, -	.set_id_led	= efx_port_dummy_op_set_id_led, -	.monitor	= efx_port_dummy_op_int, -}; - -void falcon_probe_board(struct efx_nic *efx, u16 revision_info) +int falcon_probe_board(struct efx_nic *efx, u16 revision_info)  {  	struct falcon_board *board = falcon_board(efx);  	u8 type_id = FALCON_BOARD_TYPE(revision_info); @@ -754,8 +746,9 @@ void falcon_probe_board(struct efx_nic *efx, u16 revision_info)  			 (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)  			 ? board->type->ref_model : board->type->gen_type,  			 'A' + board->major, board->minor); +		return 0;  	} else {  		EFX_ERR(efx, "unknown board type %d\n", type_id); -		board->type = &falcon_dummy_board; +		return -ENODEV;  	}  } diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h index 9351c0331a4..3166bafdfbe 100644 --- a/drivers/net/sfc/nic.h +++ b/drivers/net/sfc/nic.h @@ -156,7 +156,7 @@ extern struct efx_nic_type siena_a0_nic_type;   **************************************************************************   */ -extern void falcon_probe_board(struct efx_nic *efx, u16 revision_info); +extern int falcon_probe_board(struct efx_nic *efx, u16 revision_info);  /* TX data path */  extern int efx_nic_probe_tx(struct efx_tx_queue *tx_queue); diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 38dcc42c4f7..e0c46f59d1f 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -456,8 +456,17 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)  static void siena_update_nic_stats(struct efx_nic *efx)  { -	while (siena_try_update_nic_stats(efx) == -EAGAIN) -		cpu_relax(); +	int retry; + +	/* If we're unlucky enough to read statistics wduring the DMA, wait +	 * up to 10ms for it to finish (typically takes <500us) */ +	for (retry = 0; retry < 100; ++retry) { +		if (siena_try_update_nic_stats(efx) == 0) +			return; +		udelay(100); +	} + +	/* Use the old values instead */  }  static void siena_start_nic_stats(struct efx_nic *efx) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 22cf1c446de..ecc41cffb47 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8633,6 +8633,7 @@ static int tg3_test_msi(struct tg3 *tp)  	pci_disable_msi(tp->pdev);  	tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; +	tp->napi[0].irq_vec = tp->pdev->irq;  	err = tg3_request_irq(tp, 0);  	if (err) diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 63be4caec70..d7b7018a1de 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -397,4 +397,13 @@ config USB_IPHETH  	  For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver +config USB_SIERRA_NET +	tristate "USB-to-WWAN Driver for Sierra Wireless modems" +	depends on USB_USBNET +	help +	  Choose this option if you have a Sierra Wireless USB-to-WWAN device. + +	  To compile this driver as a module, choose M here: the +	  module will be called sierra_net. +  endmenu diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index edb09c0ddf8..b13a279663b 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -24,4 +24,5 @@ obj-$(CONFIG_USB_USBNET)	+= usbnet.o  obj-$(CONFIG_USB_NET_INT51X1)	+= int51x1.o  obj-$(CONFIG_USB_CDC_PHONET)	+= cdc-phonet.o  obj-$(CONFIG_USB_IPHETH)	+= ipheth.o +obj-$(CONFIG_USB_SIERRA_NET)	+= sierra_net.o diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index c8cdb7f30ad..3547cf13d21 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -431,6 +431,7 @@ static const struct driver_info mbm_info = {  	.bind = 	cdc_bind,  	.unbind =	usbnet_cdc_unbind,  	.status =	cdc_status, +	.manage_power =	cdc_manage_power,  };  /*-------------------------------------------------------------------------*/ diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 04b281002a7..5dfed9297b2 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -240,7 +240,7 @@ static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 valu  		goto out;  	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); -	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14); +	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12);  	for (i = 0; i < DM_TIMEOUT; i++) {  		u8 tmp; diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index fd1033130a8..418825d26f9 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -122,25 +122,25 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)  	tx_urb = usb_alloc_urb(0, GFP_KERNEL);  	if (tx_urb == NULL) -		goto error; +		goto error_nomem;  	rx_urb = usb_alloc_urb(0, GFP_KERNEL);  	if (rx_urb == NULL) -		goto error; +		goto free_tx_urb;  	tx_buf = usb_buffer_alloc(iphone->udev,  				  IPHETH_BUF_SIZE,  				  GFP_KERNEL,  				  &tx_urb->transfer_dma);  	if (tx_buf == NULL) -		goto error; +		goto free_rx_urb;  	rx_buf = usb_buffer_alloc(iphone->udev,  				  IPHETH_BUF_SIZE,  				  GFP_KERNEL,  				  &rx_urb->transfer_dma);  	if (rx_buf == NULL) -		goto error; +		goto free_tx_buf;  	iphone->tx_urb = tx_urb; @@ -149,13 +149,14 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)  	iphone->rx_buf = rx_buf;  	return 0; -error: -	usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, rx_buf, -			rx_urb->transfer_dma); +free_tx_buf:  	usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, tx_buf,  			tx_urb->transfer_dma); +free_rx_urb:  	usb_free_urb(rx_urb); +free_tx_urb:  	usb_free_urb(tx_urb); +error_nomem:  	return -ENOMEM;  } diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 52671ea043a..c4c334d9770 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -145,6 +145,7 @@ static struct usb_device_id usb_klsi_table[] = {  	{ USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */  	{ USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */  	{ USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */ +	{ USB_DEVICE(0x07c9, 0xb010) }, /* Allied Telesyn AT-USB10 USB Ethernet Adapter */  	{ USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */  	{ USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */  	{ USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */ diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c new file mode 100644 index 00000000000..f1942d69a0d --- /dev/null +++ b/drivers/net/usb/sierra_net.c @@ -0,0 +1,1004 @@ +/* + * USB-to-WWAN Driver for Sierra Wireless modems + * + * Copyright (C) 2008, 2009, 2010 Paxton Smith, Matthew Safar, Rory Filer + *                          <linux@sierrawireless.com> + * + * Portions of this based on the cdc_ether driver by David Brownell (2003-2005) + * and Ole Andre Vadla Ravnas (ActiveSync) (2006). + * + * IMPORTANT DISCLAIMER: This driver is not commercially supported by + * Sierra Wireless. Use at your own risk. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#define DRIVER_VERSION "v.2.0" +#define DRIVER_AUTHOR "Paxton Smith, Matthew Safar, Rory Filer" +#define DRIVER_DESC "USB-to-WWAN Driver for Sierra Wireless modems" +static const char driver_name[] = "sierra_net"; + +/* if defined debug messages enabled */ +/*#define	DEBUG*/ + +#include <linux/module.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/sched.h> +#include <linux/timer.h> +#include <linux/usb.h> +#include <linux/usb/cdc.h> +#include <net/ip.h> +#include <net/udp.h> +#include <asm/unaligned.h> +#include <linux/usb/usbnet.h> + +#define SWI_USB_REQUEST_GET_FW_ATTR	0x06 +#define SWI_GET_FW_ATTR_MASK		0x08 + +/* atomic counter partially included in MAC address to make sure 2 devices + * do not end up with the same MAC - concept breaks in case of > 255 ifaces + */ +static	atomic_t iface_counter = ATOMIC_INIT(0); + +/* + * SYNC Timer Delay definition used to set the expiry time + */ +#define SIERRA_NET_SYNCDELAY (2*HZ) + +/* Max. MTU supported. The modem buffers are limited to 1500 */ +#define SIERRA_NET_MAX_SUPPORTED_MTU	1500 + +/* The SIERRA_NET_USBCTL_BUF_LEN defines a buffer size allocated for control + * message reception ... and thus the max. received packet. + * (May be the cause for parse_hip returning -EINVAL) + */ +#define SIERRA_NET_USBCTL_BUF_LEN	1024 + +/* list of interface numbers - used for constructing interface lists */ +struct sierra_net_iface_info { +	const u32 infolen;	/* number of interface numbers on list */ +	const u8  *ifaceinfo;	/* pointer to the array holding the numbers */ +}; + +struct sierra_net_info_data { +	u16 rx_urb_size; +	struct sierra_net_iface_info whitelist; +}; + +/* Private data structure */ +struct sierra_net_data { + +	u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */ + +	u16 link_up;		/* air link up or down */ +	u8 tx_hdr_template[4];	/* part of HIP hdr for tx'd packets */ + +	u8 sync_msg[4];		/* SYNC message */ +	u8 shdwn_msg[4];	/* Shutdown message */ + +	/* Backpointer to the container */ +	struct usbnet *usbnet; + +	u8 ifnum;	/* interface number */ + +/* Bit masks, must be a power of 2 */ +#define SIERRA_NET_EVENT_RESP_AVAIL    0x01 +#define SIERRA_NET_TIMER_EXPIRY        0x02 +	unsigned long kevent_flags; +	struct work_struct sierra_net_kevent; +	struct timer_list sync_timer; /* For retrying SYNC sequence */ +}; + +struct param { +	int is_present; +	union { +		void  *ptr; +		u32    dword; +		u16    word; +		u8     byte; +	}; +}; + +/* HIP message type */ +#define SIERRA_NET_HIP_EXTENDEDID	0x7F +#define SIERRA_NET_HIP_HSYNC_ID		0x60	/* Modem -> host */ +#define SIERRA_NET_HIP_RESTART_ID	0x62	/* Modem -> host */ +#define SIERRA_NET_HIP_MSYNC_ID		0x20	/* Host -> modem */ +#define SIERRA_NET_HIP_SHUTD_ID		0x26	/* Host -> modem */ + +#define SIERRA_NET_HIP_EXT_IP_IN_ID   0x0202 +#define SIERRA_NET_HIP_EXT_IP_OUT_ID  0x0002 + +/* 3G UMTS Link Sense Indication definitions */ +#define SIERRA_NET_HIP_LSI_UMTSID	0x78 + +/* Reverse Channel Grant Indication HIP message */ +#define SIERRA_NET_HIP_RCGI		0x64 + +/* LSI Protocol types */ +#define SIERRA_NET_PROTOCOL_UMTS      0x01 +/* LSI Coverage */ +#define SIERRA_NET_COVERAGE_NONE      0x00 +#define SIERRA_NET_COVERAGE_NOPACKET  0x01 + +/* LSI Session */ +#define SIERRA_NET_SESSION_IDLE       0x00 +/* LSI Link types */ +#define SIERRA_NET_AS_LINK_TYPE_IPv4  0x00 + +struct lsi_umts { +	u8 protocol; +	u8 unused1; +	__be16 length; +	/* eventually use a union for the rest - assume umts for now */ +	u8 coverage; +	u8 unused2[41]; +	u8 session_state; +	u8 unused3[33]; +	u8 link_type; +	u8 pdp_addr_len; /* NW-supplied PDP address len */ +	u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */ +	u8 unused4[23]; +	u8 dns1_addr_len; /* NW-supplied 1st DNS address len (bigendian) */ +	u8 dns1_addr[16]; /* NW-supplied 1st DNS address */ +	u8 dns2_addr_len; /* NW-supplied 2nd DNS address len */ +	u8 dns2_addr[16]; /* NW-supplied 2nd DNS address (bigendian)*/ +	u8 wins1_addr_len; /* NW-supplied 1st Wins address len */ +	u8 wins1_addr[16]; /* NW-supplied 1st Wins address (bigendian)*/ +	u8 wins2_addr_len; /* NW-supplied 2nd Wins address len */ +	u8 wins2_addr[16]; /* NW-supplied 2nd Wins address (bigendian) */ +	u8 unused5[4]; +	u8 gw_addr_len; /* NW-supplied GW address len */ +	u8 gw_addr[16]; /* NW-supplied GW address (bigendian) */ +	u8 reserved[8]; +} __attribute__ ((packed)); + +#define SIERRA_NET_LSI_COMMON_LEN      4 +#define SIERRA_NET_LSI_UMTS_LEN        (sizeof(struct lsi_umts)) +#define SIERRA_NET_LSI_UMTS_STATUS_LEN \ +	(SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN) + +/* Forward definitions */ +static void sierra_sync_timer(unsigned long syncdata); +static int sierra_net_change_mtu(struct net_device *net, int new_mtu); + +/* Our own net device operations structure */ +static const struct net_device_ops sierra_net_device_ops = { +	.ndo_open               = usbnet_open, +	.ndo_stop               = usbnet_stop, +	.ndo_start_xmit         = usbnet_start_xmit, +	.ndo_tx_timeout         = usbnet_tx_timeout, +	.ndo_change_mtu         = sierra_net_change_mtu, +	.ndo_set_mac_address    = eth_mac_addr, +	.ndo_validate_addr      = eth_validate_addr, +}; + +/* get private data associated with passed in usbnet device */ +static inline struct sierra_net_data *sierra_net_get_private(struct usbnet *dev) +{ +	return (struct sierra_net_data *)dev->data[0]; +} + +/* set private data associated with passed in usbnet device */ +static inline void sierra_net_set_private(struct usbnet *dev, +			struct sierra_net_data *priv) +{ +	dev->data[0] = (unsigned long)priv; +} + +/* is packet IPv4 */ +static inline int is_ip(struct sk_buff *skb) +{ +	return (skb->protocol == cpu_to_be16(ETH_P_IP)); +} + +/* + * check passed in packet and make sure that: + *  - it is linear (no scatter/gather) + *  - it is ethernet (mac_header properly set) + */ +static int check_ethip_packet(struct sk_buff *skb, struct usbnet *dev) +{ +	skb_reset_mac_header(skb); /* ethernet header */ + +	if (skb_is_nonlinear(skb)) { +		netdev_err(dev->net, "Non linear buffer-dropping\n"); +		return 0; +	} + +	if (!pskb_may_pull(skb, ETH_HLEN)) +		return 0; +	skb->protocol = eth_hdr(skb)->h_proto; + +	return 1; +} + +static const u8 *save16bit(struct param *p, const u8 *datap) +{ +	p->is_present = 1; +	p->word = get_unaligned_be16(datap); +	return datap + sizeof(p->word); +} + +static const u8 *save8bit(struct param *p, const u8 *datap) +{ +	p->is_present = 1; +	p->byte = *datap; +	return datap + sizeof(p->byte); +} + +/*----------------------------------------------------------------------------* + *                              BEGIN HIP                                     * + *----------------------------------------------------------------------------*/ +/* HIP header */ +#define SIERRA_NET_HIP_HDR_LEN 4 +/* Extended HIP header */ +#define SIERRA_NET_HIP_EXT_HDR_LEN 6 + +struct hip_hdr { +	int    hdrlen; +	struct param payload_len; +	struct param msgid; +	struct param msgspecific; +	struct param extmsgid; +}; + +static int parse_hip(const u8 *buf, const u32 buflen, struct hip_hdr *hh) +{ +	const u8 *curp = buf; +	int    padded; + +	if (buflen < SIERRA_NET_HIP_HDR_LEN) +		return -EPROTO; + +	curp = save16bit(&hh->payload_len, curp); +	curp = save8bit(&hh->msgid, curp); +	curp = save8bit(&hh->msgspecific, curp); + +	padded = hh->msgid.byte & 0x80; +	hh->msgid.byte &= 0x7F;			/* 7 bits */ + +	hh->extmsgid.is_present = (hh->msgid.byte == SIERRA_NET_HIP_EXTENDEDID); +	if (hh->extmsgid.is_present) { +		if (buflen < SIERRA_NET_HIP_EXT_HDR_LEN) +			return -EPROTO; + +		hh->payload_len.word &= 0x3FFF; /* 14 bits */ + +		curp = save16bit(&hh->extmsgid, curp); +		hh->extmsgid.word &= 0x03FF;	/* 10 bits */ + +		hh->hdrlen = SIERRA_NET_HIP_EXT_HDR_LEN; +	} else { +		hh->payload_len.word &= 0x07FF;	/* 11 bits */ +		hh->hdrlen = SIERRA_NET_HIP_HDR_LEN; +	} + +	if (padded) { +		hh->hdrlen++; +		hh->payload_len.word--; +	} + +	/* if real packet shorter than the claimed length */ +	if (buflen < (hh->hdrlen + hh->payload_len.word)) +		return -EINVAL; + +	return 0; +} + +static void build_hip(u8 *buf, const u16 payloadlen, +		struct sierra_net_data *priv) +{ +	/* the following doesn't have the full functionality. We +	 * currently build only one kind of header, so it is faster this way +	 */ +	put_unaligned_be16(payloadlen, buf); +	memcpy(buf+2, priv->tx_hdr_template, sizeof(priv->tx_hdr_template)); +} +/*----------------------------------------------------------------------------* + *                              END HIP                                       * + *----------------------------------------------------------------------------*/ + +static int sierra_net_send_cmd(struct usbnet *dev, +		u8 *cmd, int cmdlen, const char * cmd_name) +{ +	struct sierra_net_data *priv = sierra_net_get_private(dev); +	int  status; + +	status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), +			USB_CDC_SEND_ENCAPSULATED_COMMAND, +			USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE,	0, +			priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT); + +	if (status != cmdlen && status != -ENODEV) +		netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status); + +	return status; +} + +static int sierra_net_send_sync(struct usbnet *dev) +{ +	int  status; +	struct sierra_net_data *priv = sierra_net_get_private(dev); + +	dev_dbg(&dev->udev->dev, "%s", __func__); + +	status = sierra_net_send_cmd(dev, priv->sync_msg, +			sizeof(priv->sync_msg), "SYNC"); + +	return status; +} + +static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix) +{ +	dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix); +	priv->tx_hdr_template[0] = 0x3F; +	priv->tx_hdr_template[1] = ctx_ix; +	*((u16 *)&priv->tx_hdr_template[2]) = +		cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID); +} + +static inline int sierra_net_is_valid_addrlen(u8 len) +{ +	return (len == sizeof(struct in_addr)); +} + +static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen) +{ +	struct lsi_umts *lsi = (struct lsi_umts *)data; + +	if (datalen < sizeof(struct lsi_umts)) { +		netdev_err(dev->net, "%s: Data length %d, exp %Zu\n", +				__func__, datalen, +				sizeof(struct lsi_umts)); +		return -1; +	} + +	if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) { +		netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", +				__func__, be16_to_cpu(lsi->length), +				(u32)SIERRA_NET_LSI_UMTS_STATUS_LEN); +		return -1; +	} + +	/* Validate the protocol  - only support UMTS for now */ +	if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) { +		netdev_err(dev->net, "Protocol unsupported, 0x%02x\n", +			lsi->protocol); +		return -1; +	} + +	/* Validate the link type */ +	if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) { +		netdev_err(dev->net, "Link type unsupported: 0x%02x\n", +			lsi->link_type); +		return -1; +	} + +	/* Validate the coverage */ +	if (lsi->coverage == SIERRA_NET_COVERAGE_NONE +	   || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { +		netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage); +		return 0; +	} + +	/* Validate the session state */ +	if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { +		netdev_err(dev->net, "Session idle, 0x%02x\n", +			lsi->session_state); +		return 0; +	} + +	/* Set link_sense true */ +	return 1; +} + +static void sierra_net_handle_lsi(struct usbnet *dev, char *data, +		struct hip_hdr	*hh) +{ +	struct sierra_net_data *priv = sierra_net_get_private(dev); +	int link_up; + +	link_up = sierra_net_parse_lsi(dev, data + hh->hdrlen, +					hh->payload_len.word); +	if (link_up < 0) { +		netdev_err(dev->net, "Invalid LSI\n"); +		return; +	} +	if (link_up) { +		sierra_net_set_ctx_index(priv, hh->msgspecific.byte); +		priv->link_up = 1; +		netif_carrier_on(dev->net); +	} else { +		priv->link_up = 0; +		netif_carrier_off(dev->net); +	} +} + +static void sierra_net_dosync(struct usbnet *dev) +{ +	int status; +	struct sierra_net_data *priv = sierra_net_get_private(dev); + +	dev_dbg(&dev->udev->dev, "%s", __func__); + +	/* tell modem we are ready */ +	status = sierra_net_send_sync(dev); +	if (status < 0) +		netdev_err(dev->net, +			"Send SYNC failed, status %d\n", status); +	status = sierra_net_send_sync(dev); +	if (status < 0) +		netdev_err(dev->net, +			"Send SYNC failed, status %d\n", status); + +	/* Now, start a timer and make sure we get the Restart Indication */ +	priv->sync_timer.function = sierra_sync_timer; +	priv->sync_timer.data = (unsigned long) dev; +	priv->sync_timer.expires = jiffies + SIERRA_NET_SYNCDELAY; +	add_timer(&priv->sync_timer); +} + +static void sierra_net_kevent(struct work_struct *work) +{ +	struct sierra_net_data *priv = +		container_of(work, struct sierra_net_data, sierra_net_kevent); +	struct usbnet *dev = priv->usbnet; +	int  len; +	int  err; +	u8  *buf; +	u8   ifnum; + +	if (test_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags)) { +		clear_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags); + +		/* Query the modem for the LSI message */ +		buf = kzalloc(SIERRA_NET_USBCTL_BUF_LEN, GFP_KERNEL); +		if (!buf) { +			netdev_err(dev->net, +				"failed to allocate buf for LS msg\n"); +			return; +		} +		ifnum = priv->ifnum; +		len = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), +				USB_CDC_GET_ENCAPSULATED_RESPONSE, +				USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE, +				0, ifnum, buf, SIERRA_NET_USBCTL_BUF_LEN, +				USB_CTRL_SET_TIMEOUT); + +		if (len < 0) { +			netdev_err(dev->net, +				"usb_control_msg failed, status %d\n", len); +		} else { +			struct hip_hdr	hh; + +			dev_dbg(&dev->udev->dev, "%s: Received status message," +				" %04x bytes", __func__, len); + +			err = parse_hip(buf, len, &hh); +			if (err) { +				netdev_err(dev->net, "%s: Bad packet," +					" parse result %d\n", __func__, err); +				kfree(buf); +				return; +			} + +			/* Validate packet length */ +			if (len != hh.hdrlen + hh.payload_len.word) { +				netdev_err(dev->net, "%s: Bad packet, received" +					" %d, expected %d\n",	__func__, len, +					hh.hdrlen + hh.payload_len.word); +				kfree(buf); +				return; +			} + +			/* Switch on received message types */ +			switch (hh.msgid.byte) { +			case SIERRA_NET_HIP_LSI_UMTSID: +				dev_dbg(&dev->udev->dev, "LSI for ctx:%d", +					hh.msgspecific.byte); +				sierra_net_handle_lsi(dev, buf, &hh); +				break; +			case SIERRA_NET_HIP_RESTART_ID: +				dev_dbg(&dev->udev->dev, "Restart reported: %d," +						" stopping sync timer", +						hh.msgspecific.byte); +				/* Got sync resp - stop timer & clear mask */ +				del_timer_sync(&priv->sync_timer); +				clear_bit(SIERRA_NET_TIMER_EXPIRY, +					  &priv->kevent_flags); +				break; +			case SIERRA_NET_HIP_HSYNC_ID: +				dev_dbg(&dev->udev->dev, "SYNC received"); +				err = sierra_net_send_sync(dev); +				if (err < 0) +					netdev_err(dev->net, +						"Send SYNC failed %d\n", err); +				break; +			case SIERRA_NET_HIP_EXTENDEDID: +				netdev_err(dev->net, "Unrecognized HIP msg, " +					"extmsgid 0x%04x\n", hh.extmsgid.word); +				break; +			case SIERRA_NET_HIP_RCGI: +				/* Ignored */ +				break; +			default: +				netdev_err(dev->net, "Unrecognized HIP msg, " +					"msgid 0x%02x\n", hh.msgid.byte); +				break; +			} +		} +		kfree(buf); +	} +	/* The sync timer bit might be set */ +	if (test_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags)) { +		clear_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags); +		dev_dbg(&dev->udev->dev, "Deferred sync timer expiry"); +		sierra_net_dosync(priv->usbnet); +	} + +	if (priv->kevent_flags) +		dev_dbg(&dev->udev->dev, "sierra_net_kevent done, " +			"kevent_flags = 0x%lx", priv->kevent_flags); +} + +static void sierra_net_defer_kevent(struct usbnet *dev, int work) +{ +	struct sierra_net_data *priv = sierra_net_get_private(dev); + +	set_bit(work, &priv->kevent_flags); +	schedule_work(&priv->sierra_net_kevent); +} + +/* + * Sync Retransmit Timer Handler. On expiry, kick the work queue + */ +void sierra_sync_timer(unsigned long syncdata) +{ +	struct usbnet *dev = (struct usbnet *)syncdata; + +	dev_dbg(&dev->udev->dev, "%s", __func__); +	/* Kick the tasklet */ +	sierra_net_defer_kevent(dev, SIERRA_NET_TIMER_EXPIRY); +} + +static void sierra_net_status(struct usbnet *dev, struct urb *urb) +{ +	struct usb_cdc_notification *event; + +	dev_dbg(&dev->udev->dev, "%s", __func__); + +	if (urb->actual_length < sizeof *event) +		return; + +	/* Add cases to handle other standard notifications. */ +	event = urb->transfer_buffer; +	switch (event->bNotificationType) { +	case USB_CDC_NOTIFY_NETWORK_CONNECTION: +	case USB_CDC_NOTIFY_SPEED_CHANGE: +		/* USB 305 sends those */ +		break; +	case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: +		sierra_net_defer_kevent(dev, SIERRA_NET_EVENT_RESP_AVAIL); +		break; +	default: +		netdev_err(dev->net, ": unexpected notification %02x!\n", +				event->bNotificationType); +		break; +	} +} + +static void sierra_net_get_drvinfo(struct net_device *net, +		struct ethtool_drvinfo *info) +{ +	/* Inherit standard device info */ +	usbnet_get_drvinfo(net, info); +	strncpy(info->driver, driver_name, sizeof info->driver); +	strncpy(info->version, DRIVER_VERSION, sizeof info->version); +} + +static u32 sierra_net_get_link(struct net_device *net) +{ +	struct usbnet *dev = netdev_priv(net); +	/* Report link is down whenever the interface is down */ +	return sierra_net_get_private(dev)->link_up && netif_running(net); +} + +static struct ethtool_ops sierra_net_ethtool_ops = { +	.get_drvinfo = sierra_net_get_drvinfo, +	.get_link = sierra_net_get_link, +	.get_msglevel = usbnet_get_msglevel, +	.set_msglevel = usbnet_set_msglevel, +	.get_settings = usbnet_get_settings, +	.set_settings = usbnet_set_settings, +	.nway_reset = usbnet_nway_reset, +}; + +/* MTU can not be more than 1500 bytes, enforce it. */ +static int sierra_net_change_mtu(struct net_device *net, int new_mtu) +{ +	if (new_mtu > SIERRA_NET_MAX_SUPPORTED_MTU) +		return -EINVAL; + +	return usbnet_change_mtu(net, new_mtu); +} + +static int is_whitelisted(const u8 ifnum, +			const struct sierra_net_iface_info *whitelist) +{ +	if (whitelist) { +		const u8 *list = whitelist->ifaceinfo; +		int i; + +		for (i = 0; i < whitelist->infolen; i++) { +			if (list[i] == ifnum) +				return 1; +		} +	} +	return 0; +} + +static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) +{ +	int result = 0; +	u16 *attrdata; + +	attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL); +	if (!attrdata) +		return -ENOMEM; + +	result = usb_control_msg( +			dev->udev, +			usb_rcvctrlpipe(dev->udev, 0), +			/* _u8 vendor specific request */ +			SWI_USB_REQUEST_GET_FW_ATTR, +			USB_DIR_IN | USB_TYPE_VENDOR,	/* __u8 request type */ +			0x0000,		/* __u16 value not used */ +			0x0000,		/* __u16 index  not used */ +			attrdata,	/* char *data */ +			sizeof(*attrdata),		/* __u16 size */ +			USB_CTRL_SET_TIMEOUT);	/* int timeout */ + +	if (result < 0) { +		kfree(attrdata); +		return -EIO; +	} + +	*datap = *attrdata; + +	kfree(attrdata); +	return result; +} + +/* + * collects the bulk endpoints, the status endpoint. + */ +static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) +{ +	u8	ifacenum; +	u8	numendpoints; +	u16	fwattr = 0; +	int	status; +	struct ethhdr *eth; +	struct sierra_net_data *priv; +	static const u8 sync_tmplate[sizeof(priv->sync_msg)] = { +		0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00}; +	static const u8 shdwn_tmplate[sizeof(priv->shdwn_msg)] = { +		0x00, 0x00, SIERRA_NET_HIP_SHUTD_ID, 0x00}; + +	struct sierra_net_info_data *data = +			(struct sierra_net_info_data *)dev->driver_info->data; + +	dev_dbg(&dev->udev->dev, "%s", __func__); + +	ifacenum = intf->cur_altsetting->desc.bInterfaceNumber; +	/* We only accept certain interfaces */ +	if (!is_whitelisted(ifacenum, &data->whitelist)) { +		dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum); +		return -ENODEV; +	} +	numendpoints = intf->cur_altsetting->desc.bNumEndpoints; +	/* We have three endpoints, bulk in and out, and a status */ +	if (numendpoints != 3) { +		dev_err(&dev->udev->dev, "Expected 3 endpoints, found: %d", +			numendpoints); +		return -ENODEV; +	} +	/* Status endpoint set in usbnet_get_endpoints() */ +	dev->status = NULL; +	status = usbnet_get_endpoints(dev, intf); +	if (status < 0) { +		dev_err(&dev->udev->dev, "Error in usbnet_get_endpoints (%d)", +			status); +		return -ENODEV; +	} +	/* Initialize sierra private data */ +	priv = kzalloc(sizeof *priv, GFP_KERNEL); +	if (!priv) { +		dev_err(&dev->udev->dev, "No memory"); +		return -ENOMEM; +	} + +	priv->usbnet = dev; +	priv->ifnum = ifacenum; +	dev->net->netdev_ops = &sierra_net_device_ops; + +	/* change MAC addr to include, ifacenum, and to be unique */ +	dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter); +	dev->net->dev_addr[ETH_ALEN-1] = ifacenum; + +	/* we will have to manufacture ethernet headers, prepare template */ +	eth = (struct ethhdr *)priv->ethr_hdr_tmpl; +	memcpy(ð->h_dest, dev->net->dev_addr, ETH_ALEN); +	eth->h_proto = cpu_to_be16(ETH_P_IP); + +	/* prepare shutdown message template */ +	memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg)); +	/* set context index initially to 0 - prepares tx hdr template */ +	sierra_net_set_ctx_index(priv, 0); + +	/* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */ +	dev->rx_urb_size  = data->rx_urb_size; +	if (dev->udev->speed != USB_SPEED_HIGH) +		dev->rx_urb_size  = min_t(size_t, 4096, data->rx_urb_size); + +	dev->net->hard_header_len += SIERRA_NET_HIP_EXT_HDR_LEN; +	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; + +	/* Set up the netdev */ +	dev->net->flags |= IFF_NOARP; +	dev->net->ethtool_ops = &sierra_net_ethtool_ops; +	netif_carrier_off(dev->net); + +	sierra_net_set_private(dev, priv); + +	priv->kevent_flags = 0; + +	/* Use the shared workqueue */ +	INIT_WORK(&priv->sierra_net_kevent, sierra_net_kevent); + +	/* Only need to do this once */ +	init_timer(&priv->sync_timer); + +	/* verify fw attributes */ +	status = sierra_net_get_fw_attr(dev, &fwattr); +	dev_dbg(&dev->udev->dev, "Fw attr: %x\n", fwattr); + +	/* test whether firmware supports DHCP */ +	if (!(status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_MASK))) { +		/* found incompatible firmware version */ +		dev_err(&dev->udev->dev, "Incompatible driver and firmware" +			" versions\n"); +		kfree(priv); +		return -ENODEV; +	} +	/* prepare sync message from template */ +	memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); + +	/* initiate the sync sequence */ +	sierra_net_dosync(dev); + +	return 0; +} + +static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf) +{ +	int status; +	struct sierra_net_data *priv = sierra_net_get_private(dev); + +	dev_dbg(&dev->udev->dev, "%s", __func__); + +	/* Kill the timer then flush the work queue */ +	del_timer_sync(&priv->sync_timer); + +	flush_scheduled_work(); + +	/* tell modem we are going away */ +	status = sierra_net_send_cmd(dev, priv->shdwn_msg, +			sizeof(priv->shdwn_msg), "Shutdown"); +	if (status < 0) +		netdev_err(dev->net, +			"usb_control_msg failed, status %d\n", status); + +	sierra_net_set_private(dev, NULL); + +	kfree(priv); +} + +static struct sk_buff *sierra_net_skb_clone(struct usbnet *dev, +		struct sk_buff *skb, int len) +{ +	struct sk_buff *new_skb; + +	/* clone skb */ +	new_skb = skb_clone(skb, GFP_ATOMIC); + +	/* remove len bytes from original */ +	skb_pull(skb, len); + +	/* trim next packet to it's length */ +	if (new_skb) { +		skb_trim(new_skb, len); +	} else { +		if (netif_msg_rx_err(dev)) +			netdev_err(dev->net, "failed to get skb\n"); +		dev->net->stats.rx_dropped++; +	} + +	return new_skb; +} + +/* ---------------------------- Receive data path ----------------------*/ +static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ +	int err; +	struct hip_hdr  hh; +	struct sk_buff *new_skb; + +	dev_dbg(&dev->udev->dev, "%s", __func__); + +	/* could contain multiple packets */ +	while (likely(skb->len)) { +		err = parse_hip(skb->data, skb->len, &hh); +		if (err) { +			if (netif_msg_rx_err(dev)) +				netdev_err(dev->net, "Invalid HIP header %d\n", +					err); +			/* dev->net->stats.rx_errors incremented by caller */ +			dev->net->stats.rx_length_errors++; +			return 0; +		} + +		/* Validate Extended HIP header */ +		if (!hh.extmsgid.is_present +		    || hh.extmsgid.word != SIERRA_NET_HIP_EXT_IP_IN_ID) { +			if (netif_msg_rx_err(dev)) +				netdev_err(dev->net, "HIP/ETH: Invalid pkt\n"); + +			dev->net->stats.rx_frame_errors++; +			/* dev->net->stats.rx_errors incremented by caller */; +			return 0; +		} + +		skb_pull(skb, hh.hdrlen); + +		/* We are going to accept this packet, prepare it */ +		memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl, +			ETH_HLEN); + +		/* Last packet in batch handled by usbnet */ +		if (hh.payload_len.word == skb->len) +			return 1; + +		new_skb = sierra_net_skb_clone(dev, skb, hh.payload_len.word); +		if (new_skb) +			usbnet_skb_return(dev, new_skb); + +	} /* while */ + +	return 0; +} + +/* ---------------------------- Transmit data path ----------------------*/ +struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, +		gfp_t flags) +{ +	struct sierra_net_data *priv = sierra_net_get_private(dev); +	u16 len; +	bool need_tail; + +	dev_dbg(&dev->udev->dev, "%s", __func__); +	if (priv->link_up && check_ethip_packet(skb, dev) && is_ip(skb)) { +		/* enough head room as is? */ +		if (SIERRA_NET_HIP_EXT_HDR_LEN <= skb_headroom(skb)) { +			/* Save the Eth/IP length and set up HIP hdr */ +			len = skb->len; +			skb_push(skb, SIERRA_NET_HIP_EXT_HDR_LEN); +			/* Handle ZLP issue */ +			need_tail = ((len + SIERRA_NET_HIP_EXT_HDR_LEN) +				% dev->maxpacket == 0); +			if (need_tail) { +				if (unlikely(skb_tailroom(skb) == 0)) { +					netdev_err(dev->net, "tx_fixup:" +						"no room for packet\n"); +					dev_kfree_skb_any(skb); +					return NULL; +				} else { +					skb->data[skb->len] = 0; +					__skb_put(skb, 1); +					len = len + 1; +				} +			} +			build_hip(skb->data, len, priv); +			return skb; +		} else { +			/* +			 * compensate in the future if necessary +			 */ +			netdev_err(dev->net, "tx_fixup: no room for HIP\n"); +		} /* headroom */ +	} + +	if (!priv->link_up) +		dev->net->stats.tx_carrier_errors++; + +	/* tx_dropped incremented by usbnet */ + +	/* filter the packet out, release it  */ +	dev_kfree_skb_any(skb); +	return NULL; +} + +static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; +static const struct sierra_net_info_data sierra_net_info_data_68A3 = { +	.rx_urb_size = 8 * 1024, +	.whitelist = { +		.infolen = ARRAY_SIZE(sierra_net_ifnum_list), +		.ifaceinfo = sierra_net_ifnum_list +	} +}; + +static const struct driver_info sierra_net_info_68A3 = { +	.description = "Sierra Wireless USB-to-WWAN Modem", +	.flags = FLAG_WWAN | FLAG_SEND_ZLP, +	.bind = sierra_net_bind, +	.unbind = sierra_net_unbind, +	.status = sierra_net_status, +	.rx_fixup = sierra_net_rx_fixup, +	.tx_fixup = sierra_net_tx_fixup, +	.data = (unsigned long)&sierra_net_info_data_68A3, +}; + +static const struct usb_device_id products[] = { +	{USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ +	.driver_info = (unsigned long) &sierra_net_info_68A3}, + +	{}, /* last item */ +}; +MODULE_DEVICE_TABLE(usb, products); + +/* We are based on usbnet, so let it handle the USB driver specifics */ +static struct usb_driver sierra_net_driver = { +	.name = "sierra_net", +	.id_table = products, +	.probe = usbnet_probe, +	.disconnect = usbnet_disconnect, +	.suspend = usbnet_suspend, +	.resume = usbnet_resume, +	.no_dynamic_id = 1, +}; + +static int __init sierra_net_init(void) +{ +	BUILD_BUG_ON(FIELD_SIZEOF(struct usbnet, data) +				< sizeof(struct cdc_state)); + +	return usb_register(&sierra_net_driver); +} + +static void __exit sierra_net_exit(void) +{ +	usb_deregister(&sierra_net_driver); +} + +module_exit(sierra_net_exit); +module_init(sierra_net_init); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index f9f0730b53d..5ec542dd5b5 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -187,7 +187,6 @@ tx_drop:  	return NETDEV_TX_OK;  rx_drop: -	kfree_skb(skb);  	rcv_stats->rx_dropped++;  	return NETDEV_TX_OK;  } diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 99a6da464bd..e1c2fcaa8be 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -727,12 +727,16 @@ static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)  {  	struct device *parent = aru->udev->dev.parent; +	complete(&aru->firmware_loading_complete); +  	/* unbind anything failed */  	if (parent)  		down(&parent->sem);  	device_release_driver(&aru->udev->dev);  	if (parent)  		up(&parent->sem); + +	usb_put_dev(aru->udev);  }  static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) @@ -761,6 +765,8 @@ static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)  	if (err)  		goto err_unrx; +	complete(&aru->firmware_loading_complete); +	usb_put_dev(aru->udev);  	return;   err_unrx: @@ -858,6 +864,7 @@ static int ar9170_usb_probe(struct usb_interface *intf,  	init_usb_anchor(&aru->tx_pending);  	init_usb_anchor(&aru->tx_submitted);  	init_completion(&aru->cmd_wait); +	init_completion(&aru->firmware_loading_complete);  	spin_lock_init(&aru->tx_urb_lock);  	aru->tx_pending_urbs = 0; @@ -877,6 +884,7 @@ static int ar9170_usb_probe(struct usb_interface *intf,  	if (err)  		goto err_freehw; +	usb_get_dev(aru->udev);  	return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw",  				       &aru->udev->dev, GFP_KERNEL, aru,  				       ar9170_usb_firmware_step2); @@ -896,6 +904,9 @@ static void ar9170_usb_disconnect(struct usb_interface *intf)  		return;  	aru->common.state = AR9170_IDLE; + +	wait_for_completion(&aru->firmware_loading_complete); +  	ar9170_unregister(&aru->common);  	ar9170_usb_cancel_urbs(aru); diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index a2ce3b169ce..919b06046eb 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -71,6 +71,7 @@ struct ar9170_usb {  	unsigned int tx_pending_urbs;  	struct completion cmd_wait; +	struct completion firmware_loading_complete;  	int readlen;  	u8 *readbuf; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f8c9b..f4e59ae07f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2621,7 +2621,9 @@ struct iwl_ssid_ie {  #define PROBE_OPTION_MAX_3945		4  #define PROBE_OPTION_MAX		20  #define TX_CMD_LIFE_TIME_INFINITE	cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH			cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_DISABLED	0 +#define IWL_GOOD_CRC_TH_DEFAULT		cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_NEVER		cpu_to_le16(0xffff)  #define IWL_MAX_SCAN_SIZE 1024  #define IWL_MAX_CMD_SIZE 4096  #define IWL_MAX_PROBE_REQUEST		200 diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 12e455a4b90..741e65ec830 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -813,16 +813,29 @@ static void iwl_bg_request_scan(struct work_struct *data)  			rate = IWL_RATE_1M_PLCP;  			rate_flags = RATE_MCS_CCK_MSK;  		} -		scan->good_CRC_th = 0; +		scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;  	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {  		band = IEEE80211_BAND_5GHZ;  		rate = IWL_RATE_6M_PLCP;  		/* -		 * If active scaning is requested but a certain channel -		 * is marked passive, we can do active scanning if we -		 * detect transmissions. +		 * If active scanning is requested but a certain channel is +		 * marked passive, we can do active scanning if we detect +		 * transmissions. +		 * +		 * There is an issue with some firmware versions that triggers +		 * a sysassert on a "good CRC threshold" of zero (== disabled), +		 * on a radar channel even though this means that we should NOT +		 * send probes. +		 * +		 * The "good CRC threshold" is the number of frames that we +		 * need to receive during our dwell time on a channel before +		 * sending out probes -- setting this to a huge value will +		 * mean we never reach it, but at the same time work around +		 * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER +		 * here instead of IWL_GOOD_CRC_TH_DISABLED.  		 */ -		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; +		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : +						IWL_GOOD_CRC_TH_NEVER;  		/* Force use of chains B and C (0x6) for scan Rx for 4965  		 * Avoid A (0x1) because of its off-channel reception on A-band. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b55e4f39a9e..b74a56c48d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2967,7 +2967,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  		 * is marked passive, we can do active scanning if we  		 * detect transmissions.  		 */ -		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; +		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : +						IWL_GOOD_CRC_TH_DISABLED;  		band = IEEE80211_BAND_5GHZ;  	} else {  		IWL_WARN(priv, "Invalid scan band count\n"); diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 269fda36283..c24067f1a0c 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -246,7 +246,7 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,  	u32 idx, i;  	i = (*index) % ring_limit; -	(*index) = idx = le32_to_cpu(ring_control->device_idx[1]); +	(*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);  	idx %= ring_limit;  	while (i != idx) { diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 81c753a617a..9548cbb5012 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -102,6 +102,7 @@ static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {      { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },      { 0 }  }; +MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);  static struct zorro_driver zorro8390_driver = {      .name	= "zorro8390", diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 18ecae4a437..b4748337223 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -69,7 +69,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)  		}  		phy = get_phy_device(mdio, be32_to_cpup(addr)); -		if (!phy) { +		if (!phy || IS_ERR(phy)) {  			dev_err(&mdio->dev, "error probing PHY at address %i\n",  				*addr);  			continue; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 166b67ea622..219f79e2210 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -30,23 +30,7 @@  #define OP_BUFFER_FLAGS	0 -/* - * Read and write access is using spin locking. Thus, writing to the - * buffer by NMI handler (x86) could occur also during critical - * sections when reading the buffer. To avoid this, there are 2 - * buffers for independent read and write access. Read access is in - * process context only, write access only in the NMI handler. If the - * read buffer runs empty, both buffers are swapped atomically. There - * is potentially a small window during swapping where the buffers are - * disabled and samples could be lost. - * - * Using 2 buffers is a little bit overhead, but the solution is clear - * and does not require changes in the ring buffer implementation. It - * can be changed to a single buffer solution when the ring buffer - * access is implemented as non-locking atomic code. - */ -static struct ring_buffer *op_ring_buffer_read; -static struct ring_buffer *op_ring_buffer_write; +static struct ring_buffer *op_ring_buffer;  DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer);  static void wq_sync_buffer(struct work_struct *work); @@ -68,12 +52,9 @@ void oprofile_cpu_buffer_inc_smpl_lost(void)  void free_cpu_buffers(void)  { -	if (op_ring_buffer_read) -		ring_buffer_free(op_ring_buffer_read); -	op_ring_buffer_read = NULL; -	if (op_ring_buffer_write) -		ring_buffer_free(op_ring_buffer_write); -	op_ring_buffer_write = NULL; +	if (op_ring_buffer) +		ring_buffer_free(op_ring_buffer); +	op_ring_buffer = NULL;  }  #define RB_EVENT_HDR_SIZE 4 @@ -86,11 +67,8 @@ int alloc_cpu_buffers(void)  	unsigned long byte_size = buffer_size * (sizeof(struct op_sample) +  						 RB_EVENT_HDR_SIZE); -	op_ring_buffer_read = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); -	if (!op_ring_buffer_read) -		goto fail; -	op_ring_buffer_write = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); -	if (!op_ring_buffer_write) +	op_ring_buffer = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); +	if (!op_ring_buffer)  		goto fail;  	for_each_possible_cpu(i) { @@ -162,16 +140,11 @@ struct op_sample  *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size)  {  	entry->event = ring_buffer_lock_reserve -		(op_ring_buffer_write, sizeof(struct op_sample) + +		(op_ring_buffer, sizeof(struct op_sample) +  		 size * sizeof(entry->sample->data[0])); -	if (entry->event) -		entry->sample = ring_buffer_event_data(entry->event); -	else -		entry->sample = NULL; - -	if (!entry->sample) +	if (!entry->event)  		return NULL; - +	entry->sample = ring_buffer_event_data(entry->event);  	entry->size = size;  	entry->data = entry->sample->data; @@ -180,25 +153,16 @@ struct op_sample  int op_cpu_buffer_write_commit(struct op_entry *entry)  { -	return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event); +	return ring_buffer_unlock_commit(op_ring_buffer, entry->event);  }  struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu)  {  	struct ring_buffer_event *e; -	e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); -	if (e) -		goto event; -	if (ring_buffer_swap_cpu(op_ring_buffer_read, -				 op_ring_buffer_write, -				 cpu)) +	e = ring_buffer_consume(op_ring_buffer, cpu, NULL, NULL); +	if (!e)  		return NULL; -	e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); -	if (e) -		goto event; -	return NULL; -event:  	entry->event = e;  	entry->sample = ring_buffer_event_data(e);  	entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample)) @@ -209,8 +173,7 @@ event:  unsigned long op_cpu_buffer_entries(int cpu)  { -	return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) -		+ ring_buffer_entries_cpu(op_ring_buffer_write, cpu); +	return ring_buffer_entries_cpu(op_ring_buffer, cpu);  }  static int @@ -356,8 +319,16 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,  void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)  { -	int is_kernel = !user_mode(regs); -	unsigned long pc = profile_pc(regs); +	int is_kernel; +	unsigned long pc; + +	if (likely(regs)) { +		is_kernel = !user_mode(regs); +		pc = profile_pc(regs); +	} else { +		is_kernel = 0;    /* This value will not be used */ +		pc = ESCAPE_CODE; /* as this causes an early return. */ +	}  	__oprofile_add_ext_sample(pc, regs, event, is_kernel);  } diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index dc8a0428260..b336cd9ee7a 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -253,22 +253,26 @@ static int __init oprofile_init(void)  	int err;  	err = oprofile_arch_init(&oprofile_ops); -  	if (err < 0 || timer) {  		printk(KERN_INFO "oprofile: using timer interrupt.\n"); -		oprofile_timer_init(&oprofile_ops); +		err = oprofile_timer_init(&oprofile_ops); +		if (err) +			goto out_arch;  	} -  	err = oprofilefs_register();  	if (err) -		oprofile_arch_exit(); +		goto out_arch; +	return 0; +out_arch: +	oprofile_arch_exit();  	return err;  }  static void __exit oprofile_exit(void)  { +	oprofile_timer_exit();  	oprofilefs_unregister();  	oprofile_arch_exit();  } diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index cb92f5c98c1..47e12cb4ee8 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h @@ -34,7 +34,8 @@ struct super_block;  struct dentry;  void oprofile_create_files(struct super_block *sb, struct dentry *root); -void oprofile_timer_init(struct oprofile_operations *ops); +int oprofile_timer_init(struct oprofile_operations *ops); +void oprofile_timer_exit(void);  int oprofile_set_backtrace(unsigned long depth);  int oprofile_set_timeout(unsigned long time); diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 333f915568c..dc0ae4d14df 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -13,34 +13,94 @@  #include <linux/oprofile.h>  #include <linux/profile.h>  #include <linux/init.h> +#include <linux/cpu.h> +#include <linux/hrtimer.h> +#include <asm/irq_regs.h>  #include <asm/ptrace.h>  #include "oprof.h" -static int timer_notify(struct pt_regs *regs) +static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer); + +static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer) +{ +	oprofile_add_sample(get_irq_regs(), 0); +	hrtimer_forward_now(hrtimer, ns_to_ktime(TICK_NSEC)); +	return HRTIMER_RESTART; +} + +static void __oprofile_hrtimer_start(void *unused) +{ +	struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer); + +	hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); +	hrtimer->function = oprofile_hrtimer_notify; + +	hrtimer_start(hrtimer, ns_to_ktime(TICK_NSEC), +		      HRTIMER_MODE_REL_PINNED); +} + +static int oprofile_hrtimer_start(void)  { -	oprofile_add_sample(regs, 0); +	on_each_cpu(__oprofile_hrtimer_start, NULL, 1);  	return 0;  } -static int timer_start(void) +static void __oprofile_hrtimer_stop(int cpu)  { -	return register_timer_hook(timer_notify); +	struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu); + +	hrtimer_cancel(hrtimer);  } +static void oprofile_hrtimer_stop(void) +{ +	int cpu; + +	for_each_online_cpu(cpu) +		__oprofile_hrtimer_stop(cpu); +} -static void timer_stop(void) +static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, +					 unsigned long action, void *hcpu)  { -	unregister_timer_hook(timer_notify); +	long cpu = (long) hcpu; + +	switch (action) { +	case CPU_ONLINE: +	case CPU_ONLINE_FROZEN: +		smp_call_function_single(cpu, __oprofile_hrtimer_start, +					 NULL, 1); +		break; +	case CPU_DEAD: +	case CPU_DEAD_FROZEN: +		__oprofile_hrtimer_stop(cpu); +		break; +	} +	return NOTIFY_OK;  } +static struct notifier_block __refdata oprofile_cpu_notifier = { +	.notifier_call = oprofile_cpu_notify, +}; -void __init oprofile_timer_init(struct oprofile_operations *ops) +int __init oprofile_timer_init(struct oprofile_operations *ops)  { +	int rc; + +	rc = register_hotcpu_notifier(&oprofile_cpu_notifier); +	if (rc) +		return rc;  	ops->create_files = NULL;  	ops->setup = NULL;  	ops->shutdown = NULL; -	ops->start = timer_start; -	ops->stop = timer_stop; +	ops->start = oprofile_hrtimer_start; +	ops->stop = oprofile_hrtimer_stop;  	ops->cpu_type = "timer"; +	return 0; +} + +void __exit oprofile_timer_exit(void) +{ +	unregister_hotcpu_notifier(&oprofile_cpu_notifier);  } diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 4e3e0382c16..083034710fa 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -20,6 +20,7 @@  #include <linux/init.h>  #include <linux/pci.h>  #include <linux/string.h> +#include <linux/vmalloc.h>  #include <asm/pci-bridge.h>  #include <linux/mutex.h> @@ -430,6 +431,8 @@ int dlpar_remove_slot(char *drc_name)  			rc = dlpar_remove_pci_slot(drc_name, dn);  			break;  	} +	vm_unmap_aliases(); +  	printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);  exit:  	mutex_unlock(&rpadlpar_mutex); diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 71970224078..ef7411c660b 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -29,6 +29,7 @@  #include <linux/pci_hotplug.h>  #include <linux/smp.h>  #include <linux/init.h> +#include <linux/vmalloc.h>  #include <asm/eeh.h>       /* for eeh_add_device() */  #include <asm/rtas.h>		/* rtas_call */  #include <asm/pci-bridge.h>	/* for pci_controller */ @@ -418,6 +419,8 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)  		return -EINVAL;  	pcibios_remove_pci_devices(slot->bus); +	vm_unmap_aliases(); +  	slot->state = NOT_CONFIGURED;  	return 0;  } diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 417312528dd..371dc564e2e 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3626,14 +3626,15 @@ static void intel_iommu_detach_device(struct iommu_domain *domain,  	domain_remove_one_dev_info(dmar_domain, pdev);  } -static int intel_iommu_map_range(struct iommu_domain *domain, -				 unsigned long iova, phys_addr_t hpa, -				 size_t size, int iommu_prot) +static int intel_iommu_map(struct iommu_domain *domain, +			   unsigned long iova, phys_addr_t hpa, +			   int gfp_order, int iommu_prot)  {  	struct dmar_domain *dmar_domain = domain->priv;  	u64 max_addr;  	int addr_width;  	int prot = 0; +	size_t size;  	int ret;  	if (iommu_prot & IOMMU_READ) @@ -3643,6 +3644,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain,  	if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)  		prot |= DMA_PTE_SNP; +	size     = PAGE_SIZE << gfp_order;  	max_addr = iova + size;  	if (dmar_domain->max_addr < max_addr) {  		int min_agaw; @@ -3669,19 +3671,19 @@ static int intel_iommu_map_range(struct iommu_domain *domain,  	return ret;  } -static void intel_iommu_unmap_range(struct iommu_domain *domain, -				    unsigned long iova, size_t size) +static int intel_iommu_unmap(struct iommu_domain *domain, +			     unsigned long iova, int gfp_order)  {  	struct dmar_domain *dmar_domain = domain->priv; - -	if (!size) -		return; +	size_t size = PAGE_SIZE << gfp_order;  	dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,  			    (iova + size - 1) >> VTD_PAGE_SHIFT);  	if (dmar_domain->max_addr == iova + size)  		dmar_domain->max_addr = iova; + +	return gfp_order;  }  static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, @@ -3714,8 +3716,8 @@ static struct iommu_ops intel_iommu_ops = {  	.domain_destroy = intel_iommu_domain_destroy,  	.attach_dev	= intel_iommu_attach_device,  	.detach_dev	= intel_iommu_detach_device, -	.map		= intel_iommu_map_range, -	.unmap		= intel_iommu_unmap_range, +	.map		= intel_iommu_map, +	.unmap		= intel_iommu_unmap,  	.iova_to_phys	= intel_iommu_iova_to_phys,  	.domain_has_cap = intel_iommu_domain_has_cap,  }; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4fe36d2e104..19b111383f6 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -838,65 +838,11 @@ static void pci_bus_dump_resources(struct pci_bus *bus)  	}  } -static int __init pci_bus_get_depth(struct pci_bus *bus) -{ -	int depth = 0; -	struct pci_dev *dev; - -	list_for_each_entry(dev, &bus->devices, bus_list) { -		int ret; -		struct pci_bus *b = dev->subordinate; -		if (!b) -			continue; - -		ret = pci_bus_get_depth(b); -		if (ret + 1 > depth) -			depth = ret + 1; -	} - -	return depth; -} -static int __init pci_get_max_depth(void) -{ -	int depth = 0; -	struct pci_bus *bus; - -	list_for_each_entry(bus, &pci_root_buses, node) { -		int ret; - -		ret = pci_bus_get_depth(bus); -		if (ret > depth) -			depth = ret; -	} - -	return depth; -} - -/* - * first try will not touch pci bridge res - * second  and later try will clear small leaf bridge res - * will stop till to the max  deepth if can not find good one - */  void __init  pci_assign_unassigned_resources(void)  {  	struct pci_bus *bus; -	int tried_times = 0; -	enum release_type rel_type = leaf_only; -	struct resource_list_x head, *list; -	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | -				  IORESOURCE_PREFETCH; -	unsigned long failed_type; -	int max_depth = pci_get_max_depth(); -	int pci_try_num; -	head.next = NULL; - -	pci_try_num = max_depth + 1; -	printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", -		 max_depth, pci_try_num); - -again:  	/* Depth first, calculate sizes and alignments of all  	   subordinate buses. */  	list_for_each_entry(bus, &pci_root_buses, node) { @@ -904,65 +850,9 @@ again:  	}  	/* Depth last, allocate resources and update the hardware. */  	list_for_each_entry(bus, &pci_root_buses, node) { -		__pci_bus_assign_resources(bus, &head); -	} -	tried_times++; - -	/* any device complain? */ -	if (!head.next) -		goto enable_and_dump; -	failed_type = 0; -	for (list = head.next; list;) { -		failed_type |= list->flags; -		list = list->next; -	} -	/* -	 * io port are tight, don't try extra -	 * or if reach the limit, don't want to try more -	 */ -	failed_type &= type_mask; -	if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { -		free_failed_list(&head); -		goto enable_and_dump; -	} - -	printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", -			 tried_times + 1); - -	/* third times and later will not check if it is leaf */ -	if ((tried_times + 1) > 2) -		rel_type = whole_subtree; - -	/* -	 * Try to release leaf bridge's resources that doesn't fit resource of -	 * child device under that bridge -	 */ -	for (list = head.next; list;) { -		bus = list->dev->bus; -		pci_bus_release_bridge_resources(bus, list->flags & type_mask, -						  rel_type); -		list = list->next; -	} -	/* restore size and flags */ -	for (list = head.next; list;) { -		struct resource *res = list->res; - -		res->start = list->start; -		res->end = list->end; -		res->flags = list->flags; -		if (list->dev->subordinate) -			res->flags = 0; - -		list = list->next; -	} -	free_failed_list(&head); - -	goto again; - -enable_and_dump: -	/* Depth last, update the hardware. */ -	list_for_each_entry(bus, &pci_root_buses, node) +		pci_bus_assign_resources(bus);  		pci_enable_bridges(bus); +	}  	/* dump the resource on buses */  	list_for_each_entry(bus, &pci_root_buses, node) { diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 75ed866e695..c3383750e33 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -671,20 +671,22 @@ static int pccardd(void *__skt)  				socket_remove(skt);  			if (sysfs_events & PCMCIA_UEVENT_INSERT)  				socket_insert(skt); -			if ((sysfs_events & PCMCIA_UEVENT_RESUME) && -				!(skt->state & SOCKET_CARDBUS)) { -				ret = socket_resume(skt); -				if (!ret && skt->callback) -					skt->callback->resume(skt); -			}  			if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) &&  				!(skt->state & SOCKET_CARDBUS)) {  				if (skt->callback)  					ret = skt->callback->suspend(skt);  				else  					ret = 0; -				if (!ret) +				if (!ret) {  					socket_suspend(skt); +					msleep(100); +				} +			} +			if ((sysfs_events & PCMCIA_UEVENT_RESUME) && +				!(skt->state & SOCKET_CARDBUS)) { +				ret = socket_resume(skt); +				if (!ret && skt->callback) +					skt->callback->resume(skt);  			}  			if ((sysfs_events & PCMCIA_UEVENT_REQUERY) &&  				!(skt->state & SOCKET_CARDBUS)) { diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c index 2d48196a48c..0f4cc3f0002 100644 --- a/drivers/pcmcia/db1xxx_ss.c +++ b/drivers/pcmcia/db1xxx_ss.c @@ -146,7 +146,6 @@ static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data)  static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)  {  	int ret; -	unsigned long flags;  	if (sock->stschg_irq != -1) {  		ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq, @@ -162,30 +161,23 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)  	 * active one disabled.  	 */  	if (sock->board_type == BOARD_TYPE_DB1200) { -		local_irq_save(flags); -  		ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq,  				  IRQF_DISABLED, "pcmcia_insert", sock); -		if (ret) { -			local_irq_restore(flags); +		if (ret)  			goto out1; -		}  		ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq,  				  IRQF_DISABLED, "pcmcia_eject", sock);  		if (ret) {  			free_irq(sock->insert_irq, sock); -			local_irq_restore(flags);  			goto out1;  		} -		/* disable the currently active one */ +		/* enable the currently silent one */  		if (db1200_card_inserted(sock)) -			disable_irq_nosync(sock->insert_irq); +			enable_irq(sock->eject_irq);  		else -			disable_irq_nosync(sock->eject_irq); - -		local_irq_restore(flags); +			enable_irq(sock->insert_irq);  	} else {  		/* all other (older) Db1x00 boards use a GPIO to show  		 * card detection status:  use both-edge triggers. diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4014cf8e4a2..041eee43fd8 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -335,7 +335,6 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le  		mutex_lock(&s->ops_mutex);  		list_del(&p_dev->socket_device_list); -		p_dev->_removed = 1;  		mutex_unlock(&s->ops_mutex);  		dev_dbg(&p_dev->dev, "unregistering device\n"); @@ -654,14 +653,7 @@ static int pcmcia_requery_callback(struct device *dev, void * _data)  static void pcmcia_requery(struct pcmcia_socket *s)  { -	int present, has_pfc; - -	mutex_lock(&s->ops_mutex); -	present = s->pcmcia_state.present; -	mutex_unlock(&s->ops_mutex); - -	if (!present) -		return; +	int has_pfc;  	if (s->functions == 0) {  		pcmcia_card_add(s); @@ -828,11 +820,12 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,  	}  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { -		if (dev->device_no != did->device_no) -			return 0; +		dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n");  		mutex_lock(&dev->socket->ops_mutex);  		dev->socket->pcmcia_state.has_pfc = 1;  		mutex_unlock(&dev->socket->ops_mutex); +		if (dev->device_no != did->device_no) +			return 0;  	}  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { @@ -843,7 +836,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,  		/* if this is a pseudo-multi-function device,  		 * we need explicit matches */ -		if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) +		if (dev->socket->pcmcia_state.has_pfc)  			return 0;  		if (dev->device_no)  			return 0; @@ -1260,9 +1253,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)  	switch (event) {  	case CS_EVENT_CARD_REMOVAL: -		mutex_lock(&s->ops_mutex); -		s->pcmcia_state.present = 0; -		mutex_unlock(&s->ops_mutex); +		atomic_set(&skt->present, 0);  		pcmcia_card_remove(skt, NULL);  		handle_event(skt, event);  		mutex_lock(&s->ops_mutex); @@ -1271,9 +1262,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)  		break;  	case CS_EVENT_CARD_INSERTION: +		atomic_set(&skt->present, 1);  		mutex_lock(&s->ops_mutex);  		s->pcmcia_state.has_pfc = 0; -		s->pcmcia_state.present = 1;  		destroy_cis_cache(s); /* to be on the safe side... */  		mutex_unlock(&s->ops_mutex);  		pcmcia_card_add(skt); @@ -1292,6 +1283,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)  			destroy_cis_cache(skt);  			kfree(skt->fake_cis);  			skt->fake_cis = NULL; +			s->functions = 0;  			mutex_unlock(&s->ops_mutex);  			/* now, add the new card */  			ds_event(skt, CS_EVENT_CARD_INSERTION, @@ -1313,7 +1305,13 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)      return 0;  } /* ds_event */ - +/* + * NOTE: This is racy. There's no guarantee the card will still be + * physically present, even if the call to this function returns + * non-NULL. Furthermore, the device driver most likely is unbound + * almost immediately, so the timeframe where pcmcia_dev_present + * returns NULL is probably really really small. + */  struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)  {  	struct pcmcia_device *p_dev; @@ -1323,22 +1321,9 @@ struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)  	if (!p_dev)  		return NULL; -	mutex_lock(&p_dev->socket->ops_mutex); -	if (!p_dev->socket->pcmcia_state.present) -		goto out; - -	if (p_dev->socket->pcmcia_state.dead) -		goto out; +	if (atomic_read(&p_dev->socket->present) != 0) +		ret = p_dev; -	if (p_dev->_removed) -		goto out; - -	if (p_dev->suspended) -		goto out; - -	ret = p_dev; - out: -	mutex_unlock(&p_dev->socket->ops_mutex);  	pcmcia_put_dev(p_dev);  	return ret;  } @@ -1388,6 +1373,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,  		return ret;  	} +	atomic_set(&socket->present, 0); +  	return 0;  } @@ -1399,10 +1386,6 @@ static void pcmcia_bus_remove_socket(struct device *dev,  	if (!socket)  		return; -	mutex_lock(&socket->ops_mutex); -	socket->pcmcia_state.dead = 1; -	mutex_unlock(&socket->ops_mutex); -  	pccard_register_pcmcia(socket, NULL);  	/* unregister any unbound devices */ diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 104e73d5d86..7631faa0cad 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -711,7 +711,7 @@ static int ds_open(struct inode *inode, struct file *file)  	    warning_printed = 1;      } -    if (s->pcmcia_state.present) +    if (atomic_read(&s->present))  	queue_event(user, CS_EVENT_CARD_INSERTION);  out:      unlock_kernel(); @@ -770,9 +770,6 @@ static ssize_t ds_read(struct file *file, char __user *buf,  	return -EIO;      s = user->socket; -    if (s->pcmcia_state.dead) -	return -EIO; -      ret = wait_event_interruptible(s->queue, !queue_empty(user));      if (ret == 0)  	ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; @@ -838,8 +835,6 @@ static int ds_ioctl(struct inode *inode, struct file *file,  	return -EIO;      s = user->socket; -    if (s->pcmcia_state.dead) -	return -EIO;      size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;      if (size > sizeof(ds_ioctl_arg_t)) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 35bb44af49b..100e4d9372f 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -274,26 +274,6 @@ static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,  	pnp_add_bus_resource(dev, start, end);  } -static u64 addr_space_length(struct pnp_dev *dev, u64 min, u64 max, u64 len) -{ -	u64 max_len; - -	max_len = max - min + 1; -	if (len <= max_len) -		return len; - -	/* -	 * Per 6.4.3.5, _LEN cannot exceed _MAX - _MIN + 1, but some BIOSes -	 * don't do this correctly, e.g., -	 * https://bugzilla.kernel.org/show_bug.cgi?id=15480 -	 */ -	dev_info(&dev->dev, -	         "resource length %#llx doesn't fit in %#llx-%#llx, trimming\n", -		 (unsigned long long) len, (unsigned long long) min, -		 (unsigned long long) max); -	return max_len; -} -  static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,  						  struct acpi_resource *res)  { @@ -309,7 +289,8 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,  		return;  	} -	len = addr_space_length(dev, p->minimum, p->maximum, p->address_length); +	/* Windows apparently computes length rather than using _LEN */ +	len = p->maximum - p->minimum + 1;  	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;  	if (p->resource_type == ACPI_MEMORY_RANGE) @@ -330,7 +311,8 @@ static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,  	int window;  	u64 len; -	len = addr_space_length(dev, p->minimum, p->maximum, p->address_length); +	/* Windows apparently computes length rather than using _LEN */ +	len = p->maximum - p->minimum + 1;  	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;  	if (p->resource_type == ACPI_MEMORY_RANGE) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 2e54e6a23c7..e3446ab8b56 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -211,6 +211,8 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res)  			if (tres->flags & IORESOURCE_IO) {  				if (cannot_compare(tres->flags))  					continue; +				if (tres->flags & IORESOURCE_WINDOW) +					continue;  				tport = &tres->start;  				tend = &tres->end;  				if (ranged_conflict(port, end, tport, tend)) @@ -271,6 +273,8 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res)  			if (tres->flags & IORESOURCE_MEM) {  				if (cannot_compare(tres->flags))  					continue; +				if (tres->flags & IORESOURCE_WINDOW) +					continue;  				taddr = &tres->start;  				tend = &tres->end;  				if (ranged_conflict(addr, end, taddr, tend)) diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index b6218f11c95..552cad85ae5 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -109,7 +109,7 @@ static int max8925_is_enabled(struct regulator_dev *rdev)  	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);  	int ret; -	ret = max8925_reg_read(info->i2c, info->vol_reg); +	ret = max8925_reg_read(info->i2c, info->enable_reg);  	if (ret < 0)  		return ret; diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index acf222f91f5..0e86247d791 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -37,6 +37,9 @@   */  #define DASD_CHANQ_MAX_SIZE 4 +#define DASD_SLEEPON_START_TAG	(void *) 1 +#define DASD_SLEEPON_END_TAG	(void *) 2 +  /*   * SECTION: exported variables of dasd.c   */ @@ -62,6 +65,7 @@ static void dasd_device_tasklet(struct dasd_device *);  static void dasd_block_tasklet(struct dasd_block *);  static void do_kick_device(struct work_struct *);  static void do_restore_device(struct work_struct *); +static void do_reload_device(struct work_struct *);  static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);  static void dasd_device_timeout(unsigned long);  static void dasd_block_timeout(unsigned long); @@ -112,6 +116,7 @@ struct dasd_device *dasd_alloc_device(void)  	device->timer.data = (unsigned long) device;  	INIT_WORK(&device->kick_work, do_kick_device);  	INIT_WORK(&device->restore_device, do_restore_device); +	INIT_WORK(&device->reload_device, do_reload_device);  	device->state = DASD_STATE_NEW;  	device->target = DASD_STATE_NEW;  	mutex_init(&device->state_mutex); @@ -518,6 +523,26 @@ void dasd_kick_device(struct dasd_device *device)  }  /* + * dasd_reload_device will schedule a call do do_reload_device to the kernel + * event daemon. + */ +static void do_reload_device(struct work_struct *work) +{ +	struct dasd_device *device = container_of(work, struct dasd_device, +						  reload_device); +	device->discipline->reload(device); +	dasd_put_device(device); +} + +void dasd_reload_device(struct dasd_device *device) +{ +	dasd_get_device(device); +	/* queue call to dasd_reload_device to the kernel event daemon. */ +	schedule_work(&device->reload_device); +} +EXPORT_SYMBOL(dasd_reload_device); + +/*   * dasd_restore_device will schedule a call do do_restore_device to the kernel   * event daemon.   */ @@ -1472,7 +1497,10 @@ void dasd_add_request_tail(struct dasd_ccw_req *cqr)   */  static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)  { -	wake_up((wait_queue_head_t *) data); +	spin_lock_irq(get_ccwdev_lock(cqr->startdev->cdev)); +	cqr->callback_data = DASD_SLEEPON_END_TAG; +	spin_unlock_irq(get_ccwdev_lock(cqr->startdev->cdev)); +	wake_up(&generic_waitq);  }  static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) @@ -1482,10 +1510,7 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)  	device = cqr->startdev;  	spin_lock_irq(get_ccwdev_lock(device->cdev)); -	rc = ((cqr->status == DASD_CQR_DONE || -	       cqr->status == DASD_CQR_NEED_ERP || -	       cqr->status == DASD_CQR_TERMINATED) && -	      list_empty(&cqr->devlist)); +	rc = (cqr->callback_data == DASD_SLEEPON_END_TAG);  	spin_unlock_irq(get_ccwdev_lock(device->cdev));  	return rc;  } @@ -1573,7 +1598,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)  			wait_event(generic_waitq, !(device->stopped));  		cqr->callback = dasd_wakeup_cb; -		cqr->callback_data = (void *) &generic_waitq; +		cqr->callback_data = DASD_SLEEPON_START_TAG;  		dasd_add_request_tail(cqr);  		if (interruptible) {  			rc = wait_event_interruptible( @@ -1652,7 +1677,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)  	}  	cqr->callback = dasd_wakeup_cb; -	cqr->callback_data = (void *) &generic_waitq; +	cqr->callback_data = DASD_SLEEPON_START_TAG;  	cqr->status = DASD_CQR_QUEUED;  	list_add(&cqr->devlist, &device->ccw_queue); diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 6632649dd6a..85bfd879485 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1418,9 +1418,29 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(  						struct dasd_ccw_req *erp)  {  	struct dasd_ccw_req *cqr = erp->refers; +	char *sense;  	if (cqr->block &&  	    (cqr->block->base != cqr->startdev)) { + +		sense = dasd_get_sense(&erp->refers->irb); +		/* +		 * dynamic pav may have changed base alias mapping +		 */ +		if (!test_bit(DASD_FLAG_OFFLINE, &cqr->startdev->flags) && sense +		    && (sense[0] == 0x10) && (sense[7] == 0x0F) +		    && (sense[8] == 0x67)) { +			/* +			 * remove device from alias handling to prevent new +			 * requests from being scheduled on the +			 * wrong alias device +			 */ +			dasd_alias_remove_device(cqr->startdev); + +			/* schedule worker to reload device */ +			dasd_reload_device(cqr->startdev); +		} +  		if (cqr->startdev->features & DASD_FEATURE_ERPLOG) {  			DBF_DEV_EVENT(DBF_ERR, cqr->startdev,  				    "ERP on alias device for request %p," diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 8c4814258e9..4155805dcdf 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)  	struct alias_server *server, *newserver;  	struct alias_lcu *lcu, *newlcu;  	int is_lcu_known; -	struct dasd_uid *uid; +	struct dasd_uid uid;  	private = (struct dasd_eckd_private *) device->private; -	uid = &private->uid; + +	device->discipline->get_uid(device, &uid);  	spin_lock_irqsave(&aliastree.lock, flags);  	is_lcu_known = 1; -	server = _find_server(uid); +	server = _find_server(&uid);  	if (!server) {  		spin_unlock_irqrestore(&aliastree.lock, flags); -		newserver = _allocate_server(uid); +		newserver = _allocate_server(&uid);  		if (IS_ERR(newserver))  			return PTR_ERR(newserver);  		spin_lock_irqsave(&aliastree.lock, flags); -		server = _find_server(uid); +		server = _find_server(&uid);  		if (!server) {  			list_add(&newserver->server, &aliastree.serverlist);  			server = newserver; @@ -214,14 +215,14 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)  		}  	} -	lcu = _find_lcu(server, uid); +	lcu = _find_lcu(server, &uid);  	if (!lcu) {  		spin_unlock_irqrestore(&aliastree.lock, flags); -		newlcu = _allocate_lcu(uid); +		newlcu = _allocate_lcu(&uid);  		if (IS_ERR(newlcu))  			return PTR_ERR(newlcu);  		spin_lock_irqsave(&aliastree.lock, flags); -		lcu = _find_lcu(server, uid); +		lcu = _find_lcu(server, &uid);  		if (!lcu) {  			list_add(&newlcu->lcu, &server->lculist);  			lcu = newlcu; @@ -256,20 +257,20 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device)  	unsigned long flags;  	struct alias_server *server;  	struct alias_lcu *lcu; -	struct dasd_uid *uid; +	struct dasd_uid uid;  	private = (struct dasd_eckd_private *) device->private; -	uid = &private->uid; +	device->discipline->get_uid(device, &uid);  	lcu = NULL;  	spin_lock_irqsave(&aliastree.lock, flags); -	server = _find_server(uid); +	server = _find_server(&uid);  	if (server) -		lcu = _find_lcu(server, uid); +		lcu = _find_lcu(server, &uid);  	spin_unlock_irqrestore(&aliastree.lock, flags);  	if (!lcu) {  		DBF_EVENT_DEVID(DBF_ERR, device->cdev,  				"could not find lcu for %04x %02x", -				uid->ssid, uid->real_unit_addr); +				uid.ssid, uid.real_unit_addr);  		WARN_ON(1);  		return;  	} @@ -282,20 +283,20 @@ void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)  	unsigned long flags;  	struct alias_server *server;  	struct alias_lcu *lcu; -	struct dasd_uid *uid; +	struct dasd_uid uid;  	private = (struct dasd_eckd_private *) device->private; -	uid = &private->uid; +	device->discipline->get_uid(device, &uid);  	lcu = NULL;  	spin_lock_irqsave(&aliastree.lock, flags); -	server = _find_server(uid); +	server = _find_server(&uid);  	if (server) -		lcu = _find_lcu(server, uid); +		lcu = _find_lcu(server, &uid);  	spin_unlock_irqrestore(&aliastree.lock, flags);  	if (!lcu) {  		DBF_EVENT_DEVID(DBF_ERR, device->cdev,  				"could not find lcu for %04x %02x", -				uid->ssid, uid->real_unit_addr); +				uid.ssid, uid.real_unit_addr);  		WARN_ON(1);  		return;  	} @@ -314,9 +315,11 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)  	struct alias_lcu *lcu;  	struct alias_server *server;  	int was_pending; +	struct dasd_uid uid;  	private = (struct dasd_eckd_private *) device->private;  	lcu = private->lcu; +	device->discipline->get_uid(device, &uid);  	spin_lock_irqsave(&lcu->lock, flags);  	list_del_init(&device->alias_list);  	/* make sure that the workers don't use this device */ @@ -353,7 +356,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)  			_schedule_lcu_update(lcu, NULL);  		spin_unlock(&lcu->lock);  	} -	server = _find_server(&private->uid); +	server = _find_server(&uid);  	if (server && list_empty(&server->lculist)) {  		list_del(&server->server);  		_free_server(server); @@ -366,19 +369,30 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)   * in the lcu is up to date and will update the device uid before   * adding it to a pav group.   */ +  static int _add_device_to_lcu(struct alias_lcu *lcu, -			      struct dasd_device *device) +			      struct dasd_device *device, +			      struct dasd_device *pos)  {  	struct dasd_eckd_private *private;  	struct alias_pav_group *group; -	struct dasd_uid *uid; +	struct dasd_uid uid; +	unsigned long flags;  	private = (struct dasd_eckd_private *) device->private; -	uid = &private->uid; -	uid->type = lcu->uac->unit[uid->real_unit_addr].ua_type; -	uid->base_unit_addr = lcu->uac->unit[uid->real_unit_addr].base_ua; -	dasd_set_uid(device->cdev, &private->uid); + +	/* only lock if not already locked */ +	if (device != pos) +		spin_lock_irqsave_nested(get_ccwdev_lock(device->cdev), flags, +					 CDEV_NESTED_SECOND); +	private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type; +	private->uid.base_unit_addr = +		lcu->uac->unit[private->uid.real_unit_addr].base_ua; +	uid = private->uid; + +	if (device != pos) +		spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);  	/* if we have no PAV anyway, we don't need to bother with PAV groups */  	if (lcu->pav == NO_PAV) { @@ -386,25 +400,25 @@ static int _add_device_to_lcu(struct alias_lcu *lcu,  		return 0;  	} -	group = _find_group(lcu, uid); +	group = _find_group(lcu, &uid);  	if (!group) {  		group = kzalloc(sizeof(*group), GFP_ATOMIC);  		if (!group)  			return -ENOMEM; -		memcpy(group->uid.vendor, uid->vendor, sizeof(uid->vendor)); -		memcpy(group->uid.serial, uid->serial, sizeof(uid->serial)); -		group->uid.ssid = uid->ssid; -		if (uid->type == UA_BASE_DEVICE) -			group->uid.base_unit_addr = uid->real_unit_addr; +		memcpy(group->uid.vendor, uid.vendor, sizeof(uid.vendor)); +		memcpy(group->uid.serial, uid.serial, sizeof(uid.serial)); +		group->uid.ssid = uid.ssid; +		if (uid.type == UA_BASE_DEVICE) +			group->uid.base_unit_addr = uid.real_unit_addr;  		else -			group->uid.base_unit_addr = uid->base_unit_addr; -		memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit)); +			group->uid.base_unit_addr = uid.base_unit_addr; +		memcpy(group->uid.vduit, uid.vduit, sizeof(uid.vduit));  		INIT_LIST_HEAD(&group->group);  		INIT_LIST_HEAD(&group->baselist);  		INIT_LIST_HEAD(&group->aliaslist);  		list_add(&group->group, &lcu->grouplist);  	} -	if (uid->type == UA_BASE_DEVICE) +	if (uid.type == UA_BASE_DEVICE)  		list_move(&device->alias_list, &group->baselist);  	else  		list_move(&device->alias_list, &group->aliaslist); @@ -525,7 +539,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)  	if (rc)  		return rc; -	spin_lock_irqsave(&lcu->lock, flags); +	/* need to take cdev lock before lcu lock */ +	spin_lock_irqsave_nested(get_ccwdev_lock(refdev->cdev), flags, +				 CDEV_NESTED_FIRST); +	spin_lock(&lcu->lock);  	lcu->pav = NO_PAV;  	for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) {  		switch (lcu->uac->unit[i].ua_type) { @@ -542,9 +559,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)  	list_for_each_entry_safe(device, tempdev, &lcu->active_devices,  				 alias_list) { -		_add_device_to_lcu(lcu, device); +		_add_device_to_lcu(lcu, device, refdev);  	} -	spin_unlock_irqrestore(&lcu->lock, flags); +	spin_unlock(&lcu->lock); +	spin_unlock_irqrestore(get_ccwdev_lock(refdev->cdev), flags);  	return 0;  } @@ -628,9 +646,12 @@ int dasd_alias_add_device(struct dasd_device *device)  	private = (struct dasd_eckd_private *) device->private;  	lcu = private->lcu;  	rc = 0; -	spin_lock_irqsave(&lcu->lock, flags); + +	/* need to take cdev lock before lcu lock */ +	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); +	spin_lock(&lcu->lock);  	if (!(lcu->flags & UPDATE_PENDING)) { -		rc = _add_device_to_lcu(lcu, device); +		rc = _add_device_to_lcu(lcu, device, device);  		if (rc)  			lcu->flags |= UPDATE_PENDING;  	} @@ -638,10 +659,19 @@ int dasd_alias_add_device(struct dasd_device *device)  		list_move(&device->alias_list, &lcu->active_devices);  		_schedule_lcu_update(lcu, device);  	} -	spin_unlock_irqrestore(&lcu->lock, flags); +	spin_unlock(&lcu->lock); +	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);  	return rc;  } +int dasd_alias_update_add_device(struct dasd_device *device) +{ +	struct dasd_eckd_private *private; +	private = (struct dasd_eckd_private *) device->private; +	private->lcu->flags |= UPDATE_PENDING; +	return dasd_alias_add_device(device); +} +  int dasd_alias_remove_device(struct dasd_device *device)  {  	struct dasd_eckd_private *private; @@ -740,19 +770,30 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu)  	struct alias_pav_group *pavgroup;  	struct dasd_device *device;  	struct dasd_eckd_private *private; +	unsigned long flags;  	/* active and inactive list can contain alias as well as base devices */  	list_for_each_entry(device, &lcu->active_devices, alias_list) {  		private = (struct dasd_eckd_private *) device->private; -		if (private->uid.type != UA_BASE_DEVICE) +		spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); +		if (private->uid.type != UA_BASE_DEVICE) { +			spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), +					       flags);  			continue; +		} +		spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);  		dasd_schedule_block_bh(device->block);  		dasd_schedule_device_bh(device);  	}  	list_for_each_entry(device, &lcu->inactive_devices, alias_list) {  		private = (struct dasd_eckd_private *) device->private; -		if (private->uid.type != UA_BASE_DEVICE) +		spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); +		if (private->uid.type != UA_BASE_DEVICE) { +			spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), +					       flags);  			continue; +		} +		spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);  		dasd_schedule_block_bh(device->block);  		dasd_schedule_device_bh(device);  	} diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index eff9c812c5c..34d51dd4c53 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -49,7 +49,6 @@ struct dasd_devmap {          unsigned int devindex;          unsigned short features;  	struct dasd_device *device; -	struct dasd_uid uid;  };  /* @@ -936,42 +935,46 @@ dasd_device_status_show(struct device *dev, struct device_attribute *attr,  static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); -static ssize_t -dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t dasd_alias_show(struct device *dev, +			       struct device_attribute *attr, char *buf)  { -	struct dasd_devmap *devmap; -	int alias; +	struct dasd_device *device; +	struct dasd_uid uid; -	devmap = dasd_find_busid(dev_name(dev)); -	spin_lock(&dasd_devmap_lock); -	if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { -		spin_unlock(&dasd_devmap_lock); +	device = dasd_device_from_cdev(to_ccwdev(dev)); +	if (IS_ERR(device))  		return sprintf(buf, "0\n"); + +	if (device->discipline && device->discipline->get_uid && +	    !device->discipline->get_uid(device, &uid)) { +		if (uid.type == UA_BASE_PAV_ALIAS || +		    uid.type == UA_HYPER_PAV_ALIAS) +			return sprintf(buf, "1\n");  	} -	if (devmap->uid.type == UA_BASE_PAV_ALIAS || -	    devmap->uid.type == UA_HYPER_PAV_ALIAS) -		alias = 1; -	else -		alias = 0; -	spin_unlock(&dasd_devmap_lock); -	return sprintf(buf, alias ? "1\n" : "0\n"); +	dasd_put_device(device); + +	return sprintf(buf, "0\n");  }  static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); -static ssize_t -dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t dasd_vendor_show(struct device *dev, +				struct device_attribute *attr, char *buf)  { -	struct dasd_devmap *devmap; +	struct dasd_device *device; +	struct dasd_uid uid;  	char *vendor; -	devmap = dasd_find_busid(dev_name(dev)); -	spin_lock(&dasd_devmap_lock); -	if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) -		vendor = devmap->uid.vendor; -	else -		vendor = ""; -	spin_unlock(&dasd_devmap_lock); +	device = dasd_device_from_cdev(to_ccwdev(dev)); +	vendor = ""; +	if (IS_ERR(device)) +		return snprintf(buf, PAGE_SIZE, "%s\n", vendor); + +	if (device->discipline && device->discipline->get_uid && +	    !device->discipline->get_uid(device, &uid)) +			vendor = uid.vendor; + +	dasd_put_device(device);  	return snprintf(buf, PAGE_SIZE, "%s\n", vendor);  } @@ -985,48 +988,51 @@ static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);  static ssize_t  dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)  { -	struct dasd_devmap *devmap; +	struct dasd_device *device; +	struct dasd_uid uid;  	char uid_string[UID_STRLEN];  	char ua_string[3]; -	struct dasd_uid *uid; -	devmap = dasd_find_busid(dev_name(dev)); -	spin_lock(&dasd_devmap_lock); -	if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { -		spin_unlock(&dasd_devmap_lock); -		return sprintf(buf, "\n"); -	} -	uid = &devmap->uid; -	switch (uid->type) { -	case UA_BASE_DEVICE: -		sprintf(ua_string, "%02x", uid->real_unit_addr); -		break; -	case UA_BASE_PAV_ALIAS: -		sprintf(ua_string, "%02x", uid->base_unit_addr); -		break; -	case UA_HYPER_PAV_ALIAS: -		sprintf(ua_string, "xx"); -		break; -	default: -		/* should not happen, treat like base device */ -		sprintf(ua_string, "%02x", uid->real_unit_addr); -		break; +	device = dasd_device_from_cdev(to_ccwdev(dev)); +	uid_string[0] = 0; +	if (IS_ERR(device)) +		return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); + +	if (device->discipline && device->discipline->get_uid && +	    !device->discipline->get_uid(device, &uid)) { +		switch (uid.type) { +		case UA_BASE_DEVICE: +			snprintf(ua_string, sizeof(ua_string), "%02x", +				 uid.real_unit_addr); +			break; +		case UA_BASE_PAV_ALIAS: +			snprintf(ua_string, sizeof(ua_string), "%02x", +				 uid.base_unit_addr); +			break; +		case UA_HYPER_PAV_ALIAS: +			snprintf(ua_string, sizeof(ua_string), "xx"); +			break; +		default: +			/* should not happen, treat like base device */ +			snprintf(ua_string, sizeof(ua_string), "%02x", +				 uid.real_unit_addr); +			break; +		} + +		if (strlen(uid.vduit) > 0) +			snprintf(uid_string, sizeof(uid_string), +				 "%s.%s.%04x.%s.%s", +				 uid.vendor, uid.serial, uid.ssid, ua_string, +				 uid.vduit); +		else +			snprintf(uid_string, sizeof(uid_string), +				 "%s.%s.%04x.%s", +				 uid.vendor, uid.serial, uid.ssid, ua_string);  	} -	if (strlen(uid->vduit) > 0) -		snprintf(uid_string, sizeof(uid_string), -			 "%s.%s.%04x.%s.%s", -			 uid->vendor, uid->serial, -			 uid->ssid, ua_string, -			 uid->vduit); -	else -		snprintf(uid_string, sizeof(uid_string), -			 "%s.%s.%04x.%s", -			 uid->vendor, uid->serial, -			 uid->ssid, ua_string); -	spin_unlock(&dasd_devmap_lock); +	dasd_put_device(device); +  	return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);  } -  static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);  /* @@ -1094,50 +1100,6 @@ static struct attribute_group dasd_attr_group = {  };  /* - * Return copy of the device unique identifier. - */ -int -dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) -{ -	struct dasd_devmap *devmap; - -	devmap = dasd_find_busid(dev_name(&cdev->dev)); -	if (IS_ERR(devmap)) -		return PTR_ERR(devmap); -	spin_lock(&dasd_devmap_lock); -	*uid = devmap->uid; -	spin_unlock(&dasd_devmap_lock); -	return 0; -} -EXPORT_SYMBOL_GPL(dasd_get_uid); - -/* - * Register the given device unique identifier into devmap struct. - * In addition check if the related storage server subsystem ID is already - * contained in the dasd_server_ssid_list. If subsystem ID is not contained, - * create new entry. - * Return 0 if server was already in serverlist, - *	  1 if the server was added successful - *	 <0 in case of error. - */ -int -dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) -{ -	struct dasd_devmap *devmap; - -	devmap = dasd_find_busid(dev_name(&cdev->dev)); -	if (IS_ERR(devmap)) -		return PTR_ERR(devmap); - -	spin_lock(&dasd_devmap_lock); -	devmap->uid = *uid; -	spin_unlock(&dasd_devmap_lock); - -	return 0; -} -EXPORT_SYMBOL_GPL(dasd_set_uid); - -/*   * Return value of the specified feature.   */  int diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0cb23311685..5b1cd8d6e97 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid)  /*   * Generate device unique id that specifies the physical device.   */ -static int dasd_eckd_generate_uid(struct dasd_device *device, -				  struct dasd_uid *uid) +static int dasd_eckd_generate_uid(struct dasd_device *device)  {  	struct dasd_eckd_private *private; +	struct dasd_uid *uid;  	int count; +	unsigned long flags;  	private = (struct dasd_eckd_private *) device->private;  	if (!private)  		return -ENODEV;  	if (!private->ned || !private->gneq)  		return -ENODEV; - +	uid = &private->uid; +	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);  	memset(uid, 0, sizeof(struct dasd_uid));  	memcpy(uid->vendor, private->ned->HDA_manufacturer,  	       sizeof(uid->vendor) - 1); @@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device,  				private->vdsneq->uit[count]);  		}  	} +	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);  	return 0;  } +static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid) +{ +	struct dasd_eckd_private *private; +	unsigned long flags; + +	if (device->private) { +		private = (struct dasd_eckd_private *)device->private; +		spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); +		*uid = private->uid; +		spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); +		return 0; +	} +	return -EINVAL; +} +  static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,  						    void *rcd_buffer,  						    struct ciw *ciw, __u8 lpm) @@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)  {  	struct dasd_eckd_private *private;  	struct dasd_block *block; +	struct dasd_uid temp_uid;  	int is_known, rc;  	int readonly; @@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device)  	if (rc)  		goto out_err1; -	/* Generate device unique id and register in devmap */ -	rc = dasd_eckd_generate_uid(device, &private->uid); +	/* Generate device unique id */ +	rc = dasd_eckd_generate_uid(device);  	if (rc)  		goto out_err1; -	dasd_set_uid(device->cdev, &private->uid); -	if (private->uid.type == UA_BASE_DEVICE) { +	dasd_eckd_get_uid(device, &temp_uid); +	if (temp_uid.type == UA_BASE_DEVICE) {  		block = dasd_alloc_block();  		if (IS_ERR(block)) {  			DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", @@ -1451,6 +1470,7 @@ static int dasd_eckd_ready_to_online(struct dasd_device *device)  static int dasd_eckd_online_to_ready(struct dasd_device *device)  { +	cancel_work_sync(&device->reload_device);  	return dasd_alias_remove_device(device);  }; @@ -1709,10 +1729,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,  {  	char mask;  	char *sense = NULL; +	struct dasd_eckd_private *private; +	private = (struct dasd_eckd_private *) device->private;  	/* first of all check for state change pending interrupt */  	mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;  	if ((scsw_dstat(&irb->scsw) & mask) == mask) { +		/* for alias only and not in offline processing*/ +		if (!device->block && private->lcu && +		    !test_bit(DASD_FLAG_OFFLINE, &device->flags)) { +			/* +			 * the state change could be caused by an alias +			 * reassignment remove device from alias handling +			 * to prevent new requests from being scheduled on +			 * the wrong alias device +			 */ +			dasd_alias_remove_device(device); + +			/* schedule worker to reload device */ +			dasd_reload_device(device); +		} +  		dasd_generic_handle_state_change(device);  		return;  	} @@ -3259,7 +3296,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,  		dasd_eckd_dump_sense_ccw(device, req, irb);  } -int dasd_eckd_pm_freeze(struct dasd_device *device) +static int dasd_eckd_pm_freeze(struct dasd_device *device)  {  	/*  	 * the device should be disconnected from our LCU structure @@ -3272,7 +3309,7 @@ int dasd_eckd_pm_freeze(struct dasd_device *device)  	return 0;  } -int dasd_eckd_restore_device(struct dasd_device *device) +static int dasd_eckd_restore_device(struct dasd_device *device)  {  	struct dasd_eckd_private *private;  	struct dasd_eckd_characteristics temp_rdc_data; @@ -3287,15 +3324,16 @@ int dasd_eckd_restore_device(struct dasd_device *device)  	if (rc)  		goto out_err; -	/* Generate device unique id and register in devmap */ -	rc = dasd_eckd_generate_uid(device, &private->uid); -	dasd_get_uid(device->cdev, &temp_uid); +	dasd_eckd_get_uid(device, &temp_uid); +	/* Generate device unique id */ +	rc = dasd_eckd_generate_uid(device); +	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);  	if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0)  		dev_err(&device->cdev->dev, "The UID of the DASD has "  			"changed\n"); +	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);  	if (rc)  		goto out_err; -	dasd_set_uid(device->cdev, &private->uid);  	/* register lcu with alias handling, enable PAV if this is a new lcu */  	is_known = dasd_alias_make_device_known_to_lcu(device); @@ -3336,6 +3374,56 @@ out_err:  	return -1;  } +static int dasd_eckd_reload_device(struct dasd_device *device) +{ +	struct dasd_eckd_private *private; +	int rc, old_base; +	char print_uid[60]; +	struct dasd_uid uid; +	unsigned long flags; + +	private = (struct dasd_eckd_private *) device->private; + +	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); +	old_base = private->uid.base_unit_addr; +	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + +	/* Read Configuration Data */ +	rc = dasd_eckd_read_conf(device); +	if (rc) +		goto out_err; + +	rc = dasd_eckd_generate_uid(device); +	if (rc) +		goto out_err; +	/* +	 * update unit address configuration and +	 * add device to alias management +	 */ +	dasd_alias_update_add_device(device); + +	dasd_eckd_get_uid(device, &uid); + +	if (old_base != uid.base_unit_addr) { +		if (strlen(uid.vduit) > 0) +			snprintf(print_uid, sizeof(print_uid), +				 "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial, +				 uid.ssid, uid.base_unit_addr, uid.vduit); +		else +			snprintf(print_uid, sizeof(print_uid), +				 "%s.%s.%04x.%02x", uid.vendor, uid.serial, +				 uid.ssid, uid.base_unit_addr); + +		dev_info(&device->cdev->dev, +			 "An Alias device was reassigned to a new base device " +			 "with UID: %s\n", print_uid); +	} +	return 0; + +out_err: +	return -1; +} +  static struct ccw_driver dasd_eckd_driver = {  	.name	     = "dasd-eckd",  	.owner	     = THIS_MODULE, @@ -3389,6 +3477,8 @@ static struct dasd_discipline dasd_eckd_discipline = {  	.ioctl = dasd_eckd_ioctl,  	.freeze = dasd_eckd_pm_freeze,  	.restore = dasd_eckd_restore_device, +	.reload = dasd_eckd_reload_device, +	.get_uid = dasd_eckd_get_uid,  };  static int __init diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 864d53c0420..dd6385a5af1 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -426,7 +426,6 @@ struct alias_pav_group {  	struct dasd_device *next;  }; -  struct dasd_eckd_private {  	struct dasd_eckd_characteristics rdc_data;  	u8 *conf_data; @@ -463,4 +462,5 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *);  void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *);  void dasd_alias_lcu_setup_complete(struct dasd_device *);  void dasd_alias_wait_for_lcu_setup(struct dasd_device *); +int dasd_alias_update_add_device(struct dasd_device *);  #endif				/* DASD_ECKD_H */ diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index a91d4a97d4f..32fac186ba3 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -81,6 +81,10 @@ struct dasd_block;  #define DASD_SIM_MSG_TO_OP 0x03  #define DASD_SIM_LOG 0x0C +/* lock class for nested cdev lock */ +#define CDEV_NESTED_FIRST 1 +#define CDEV_NESTED_SECOND 2 +  /*   * SECTION: MACROs for klogd and s390 debug feature (dbf)   */ @@ -229,6 +233,24 @@ struct dasd_ccw_req {  typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);  /* + * Unique identifier for dasd device. + */ +#define UA_NOT_CONFIGURED  0x00 +#define UA_BASE_DEVICE	   0x01 +#define UA_BASE_PAV_ALIAS  0x02 +#define UA_HYPER_PAV_ALIAS 0x03 + +struct dasd_uid { +	__u8 type; +	char vendor[4]; +	char serial[15]; +	__u16 ssid; +	__u8 real_unit_addr; +	__u8 base_unit_addr; +	char vduit[33]; +}; + +/*   * the struct dasd_discipline is   * sth like a table of virtual functions, if you think of dasd_eckd   * inheriting dasd... @@ -312,28 +334,15 @@ struct dasd_discipline {  	/* suspend/resume functions */  	int (*freeze) (struct dasd_device *);  	int (*restore) (struct dasd_device *); -}; -extern struct dasd_discipline *dasd_diag_discipline_pointer; - -/* - * Unique identifier for dasd device. - */ -#define UA_NOT_CONFIGURED  0x00 -#define UA_BASE_DEVICE	   0x01 -#define UA_BASE_PAV_ALIAS  0x02 -#define UA_HYPER_PAV_ALIAS 0x03 +	/* reload device after state change */ +	int (*reload) (struct dasd_device *); -struct dasd_uid { -	__u8 type; -	char vendor[4]; -	char serial[15]; -	__u16 ssid; -	__u8 real_unit_addr; -	__u8 base_unit_addr; -	char vduit[33]; +	int (*get_uid) (struct dasd_device *, struct dasd_uid *);  }; +extern struct dasd_discipline *dasd_diag_discipline_pointer; +  /*   * Notification numbers for extended error reporting notifications:   * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's @@ -386,6 +395,7 @@ struct dasd_device {          struct tasklet_struct tasklet;  	struct work_struct kick_work;  	struct work_struct restore_device; +	struct work_struct reload_device;  	struct timer_list timer;  	debug_info_t *debug_area; @@ -582,6 +592,7 @@ void dasd_enable_device(struct dasd_device *);  void dasd_set_target_state(struct dasd_device *, int);  void dasd_kick_device(struct dasd_device *);  void dasd_restore_device(struct dasd_device *); +void dasd_reload_device(struct dasd_device *);  void dasd_add_request_head(struct dasd_ccw_req *);  void dasd_add_request_tail(struct dasd_ccw_req *); @@ -629,8 +640,6 @@ void dasd_devmap_exit(void);  struct dasd_device *dasd_create_device(struct ccw_device *);  void dasd_delete_device(struct dasd_device *); -int dasd_get_uid(struct ccw_device *, struct dasd_uid *); -int dasd_set_uid(struct ccw_device *, struct dasd_uid *);  int dasd_get_feature(struct ccw_device *, int);  int dasd_set_feature(struct ccw_device *, int, int); diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 4e34d3686c2..40834f18754 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -148,13 +148,12 @@ config VMLOGRDR  	  This driver depends on the IUCV support driver.  config VMCP -	tristate "Support for the z/VM CP interface (VM only)" +	bool "Support for the z/VM CP interface"  	depends on S390  	help  	  Select this option if you want to be able to interact with the control  	  program on z/VM -  config MONREADER  	tristate "API for reading z/VM monitor service records"  	depends on IUCV diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 0eabcca3c92..857dfcb7b35 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -484,6 +484,7 @@ fs3270_open(struct inode *inode, struct file *filp)  		raw3270_del_view(&fp->view);  		goto out;  	} +	nonseekable_open(inode, filp);  	filp->private_data = fp;  out:  	mutex_unlock(&fs3270_mutex); diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index cb6bffe7141..18d9a497863 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -49,7 +49,7 @@ static unsigned char ret_diacr[NR_DEAD] = {  struct kbd_data *  kbd_alloc(void) {  	struct kbd_data *kbd; -	int i, len; +	int i;  	kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL);  	if (!kbd) @@ -59,12 +59,11 @@ kbd_alloc(void) {  		goto out_kbd;  	for (i = 0; i < ARRAY_SIZE(key_maps); i++) {  		if (key_maps[i]) { -			kbd->key_maps[i] = -				kmalloc(sizeof(u_short)*NR_KEYS, GFP_KERNEL); +			kbd->key_maps[i] = kmemdup(key_maps[i], +						   sizeof(u_short) * NR_KEYS, +						   GFP_KERNEL);  			if (!kbd->key_maps[i])  				goto out_maps; -			memcpy(kbd->key_maps[i], key_maps[i], -			       sizeof(u_short)*NR_KEYS);  		}  	}  	kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); @@ -72,23 +71,21 @@ kbd_alloc(void) {  		goto out_maps;  	for (i = 0; i < ARRAY_SIZE(func_table); i++) {  		if (func_table[i]) { -			len = strlen(func_table[i]) + 1; -			kbd->func_table[i] = kmalloc(len, GFP_KERNEL); +			kbd->func_table[i] = kstrdup(func_table[i], +						     GFP_KERNEL);  			if (!kbd->func_table[i])  				goto out_func; -			memcpy(kbd->func_table[i], func_table[i], len);  		}  	}  	kbd->fn_handler =  		kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL);  	if (!kbd->fn_handler)  		goto out_func; -	kbd->accent_table = -		kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL); +	kbd->accent_table = kmemdup(accent_table, +				    sizeof(struct kbdiacruc) * MAX_DIACR, +				    GFP_KERNEL);  	if (!kbd->accent_table)  		goto out_fn_handler; -	memcpy(kbd->accent_table, accent_table, -	       sizeof(struct kbdiacruc)*MAX_DIACR);  	kbd->accent_table_size = accent_table_size;  	return kbd; diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 5bb59d36a6d..04e532eec03 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -1,24 +1,20 @@  /* - * Copyright IBM Corp. 2004,2007 + * Copyright IBM Corp. 2004,2010   * Interface implementation for communication with the z/VM control program - * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>   * + * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>   *   * z/VMs CP offers the possibility to issue commands via the diagnose code 8   * this driver implements a character device that issues these commands and   * returns the answer of CP. - + *   * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS   */ -#define KMSG_COMPONENT "vmcp" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -  #include <linux/fs.h>  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/miscdevice.h> -#include <linux/module.h>  #include <linux/slab.h>  #include <asm/compat.h>  #include <asm/cpcmd.h> @@ -26,10 +22,6 @@  #include <asm/uaccess.h>  #include "vmcp.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Borntraeger <borntraeger@de.ibm.com>"); -MODULE_DESCRIPTION("z/VM CP interface"); -  static debug_info_t *vmcp_debug;  static int vmcp_open(struct inode *inode, struct file *file) @@ -197,11 +189,8 @@ static int __init vmcp_init(void)  {  	int ret; -	if (!MACHINE_IS_VM) { -		pr_warning("The z/VM CP interface device driver cannot be " -			   "loaded without z/VM\n"); -		return -ENODEV; -	} +	if (!MACHINE_IS_VM) +		return 0;  	vmcp_debug = debug_register("vmcp", 1, 1, 240);  	if (!vmcp_debug) @@ -214,19 +203,8 @@ static int __init vmcp_init(void)  	}  	ret = misc_register(&vmcp_dev); -	if (ret) { +	if (ret)  		debug_unregister(vmcp_debug); -		return ret; -	} - -	return 0; -} - -static void __exit vmcp_exit(void) -{ -	misc_deregister(&vmcp_dev); -	debug_unregister(vmcp_debug); +	return ret;  } - -module_init(vmcp_init); -module_exit(vmcp_exit); +device_initcall(vmcp_init); diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 7217966f7d3..f5ea3384a4b 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -445,7 +445,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp)  	}  	kfree(chunk_array);  	filp->private_data = buf; -	return 0; +	return nonseekable_open(inode, filp);  }  static int zcore_memmap_release(struct inode *inode, struct file *filp) @@ -473,7 +473,7 @@ static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,  static int zcore_reipl_open(struct inode *inode, struct file *filp)  { -	return 0; +	return nonseekable_open(inode, filp);  }  static int zcore_reipl_release(struct inode *inode, struct file *filp) diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 3b6f4adc509..a83877c664a 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -803,6 +803,7 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd,  static const struct file_operations chsc_fops = {  	.owner = THIS_MODULE, +	.open = nonseekable_open,  	.unlocked_ioctl = chsc_ioctl,  	.compat_ioctl = chsc_ioctl,  }; diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5feea1a371e..f4e6cf3aceb 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -616,7 +616,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs)  	struct pt_regs *old_regs;  	old_regs = set_irq_regs(regs); -	s390_idle_check(); +	s390_idle_check(regs, S390_lowcore.int_clock, +			S390_lowcore.async_enter_timer);  	irq_enter();  	__get_cpu_var(s390_idle).nohz_delay = 1;  	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 511649115bd..ac94ac75145 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -648,6 +648,8 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)  static void __init  css_generate_pgid(struct channel_subsystem *css, u32 tod_high)  { +	struct cpuid cpu_id; +  	if (css_general_characteristics.mcss) {  		css->global_pgid.pgid_high.ext_cssid.version = 0x80;  		css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; @@ -658,8 +660,9 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high)  		css->global_pgid.pgid_high.cpu_addr = 0;  #endif  	} -	css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident; -	css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine; +	get_cpu_id(&cpu_id); +	css->global_pgid.cpu_id = cpu_id.ident; +	css->global_pgid.cpu_model = cpu_id.machine;  	css->global_pgid.tod_high = tod_high;  } @@ -1062,6 +1065,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf,  }  static const struct file_operations cio_settle_proc_fops = { +	.open = nonseekable_open,  	.write = cio_settle_write,  }; diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 48aa0647432..f0037eefd44 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -13,8 +13,8 @@  #include <asm/debug.h>  #include "chsc.h" -#define QDIO_BUSY_BIT_PATIENCE		100	/* 100 microseconds */ -#define QDIO_INPUT_THRESHOLD		500	/* 500 microseconds */ +#define QDIO_BUSY_BIT_PATIENCE		(100 << 12)	/* 100 microseconds */ +#define QDIO_INPUT_THRESHOLD		(500 << 12)	/* 500 microseconds */  /*   * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait @@ -296,10 +296,8 @@ struct qdio_q {  	struct qdio_irq *irq_ptr;  	struct sl *sl;  	/* -	 * Warning: Leave this member at the end so it won't be cleared in -	 * qdio_fill_qs. A page is allocated under this pointer and used for -	 * slib and sl. slib is 2048 bytes big and sl points to offset -	 * PAGE_SIZE / 2. +	 * A page is allocated under this pointer and used for slib and sl. +	 * slib is 2048 bytes big and sl points to offset PAGE_SIZE / 2.  	 */  	struct slib *slib;  } __attribute__ ((aligned(256))); @@ -372,11 +370,6 @@ static inline int multicast_outbound(struct qdio_q *q)  	       (q->nr == q->irq_ptr->nr_output_qs - 1);  } -static inline unsigned long long get_usecs(void) -{ -	return monotonic_clock() >> 12; -} -  #define pci_out_supported(q) \  	(q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)  #define is_qebsm(q)			(q->irq_ptr->sch_token != 0) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 88be7b9ea6e..00520f9a7a8 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -336,10 +336,10 @@ again:  		WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2);  		if (!start_time) { -			start_time = get_usecs(); +			start_time = get_clock();  			goto again;  		} -		if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) +		if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE)  			goto again;  	}  	return cc; @@ -536,7 +536,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q)  	if ((bufnr != q->last_move) || q->qdio_error) {  		q->last_move = bufnr;  		if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) -			q->u.in.timestamp = get_usecs(); +			q->u.in.timestamp = get_clock();  		return 1;  	} else  		return 0; @@ -567,7 +567,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)  	 * At this point we know, that inbound first_to_check  	 * has (probably) not moved (see qdio_inbound_processing).  	 */ -	if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { +	if (get_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) {  		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x",  			      q->first_to_check);  		return 1; @@ -606,7 +606,7 @@ static void qdio_kick_handler(struct qdio_q *q)  static void __qdio_inbound_processing(struct qdio_q *q)  {  	qperf_inc(q, tasklet_inbound); -again: +  	if (!qdio_inbound_q_moved(q))  		return; @@ -615,7 +615,10 @@ again:  	if (!qdio_inbound_q_done(q)) {  		/* means poll time is not yet over */  		qperf_inc(q, tasklet_inbound_resched); -		goto again; +		if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { +			tasklet_schedule(&q->tasklet); +			return; +		}  	}  	qdio_stop_polling(q); @@ -625,7 +628,8 @@ again:  	 */  	if (!qdio_inbound_q_done(q)) {  		qperf_inc(q, tasklet_inbound_resched2); -		goto again; +		if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) +			tasklet_schedule(&q->tasklet);  	}  } @@ -955,6 +959,9 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,  		return;  	} +	if (irq_ptr->perf_stat_enabled) +		irq_ptr->perf_stat.qdio_int++; +  	if (IS_ERR(irb)) {  		switch (PTR_ERR(irb)) {  		case -EIO: @@ -1016,30 +1023,6 @@ int qdio_get_ssqd_desc(struct ccw_device *cdev,  }  EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); -/** - * qdio_cleanup - shutdown queues and free data structures - * @cdev: associated ccw device - * @how: use halt or clear to shutdown - * - * This function calls qdio_shutdown() for @cdev with method @how. - * and qdio_free(). The qdio_free() return value is ignored since - * !irq_ptr is already checked. - */ -int qdio_cleanup(struct ccw_device *cdev, int how) -{ -	struct qdio_irq *irq_ptr = cdev->private->qdio_data; -	int rc; - -	if (!irq_ptr) -		return -ENODEV; - -	rc = qdio_shutdown(cdev, how); - -	qdio_free(cdev); -	return rc; -} -EXPORT_SYMBOL_GPL(qdio_cleanup); -  static void qdio_shutdown_queues(struct ccw_device *cdev)  {  	struct qdio_irq *irq_ptr = cdev->private->qdio_data; @@ -1157,28 +1140,6 @@ int qdio_free(struct ccw_device *cdev)  EXPORT_SYMBOL_GPL(qdio_free);  /** - * qdio_initialize - allocate and establish queues for a qdio subchannel - * @init_data: initialization data - * - * This function first allocates queues via qdio_allocate() and on success - * establishes them via qdio_establish(). - */ -int qdio_initialize(struct qdio_initialize *init_data) -{ -	int rc; - -	rc = qdio_allocate(init_data); -	if (rc) -		return rc; - -	rc = qdio_establish(init_data); -	if (rc) -		qdio_free(init_data->cdev); -	return rc; -} -EXPORT_SYMBOL_GPL(qdio_initialize); - -/**   * qdio_allocate - allocate qdio queues and associated data   * @init_data: initialization data   */ diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 7f4a7546514..6326b67c45d 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -106,10 +106,12 @@ int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs  static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,  			      qdio_handler_t *handler, int i)  { -	/* must be cleared by every qdio_establish */ -	memset(q, 0, ((char *)&q->slib) - ((char *)q)); -	memset(q->slib, 0, PAGE_SIZE); +	struct slib *slib = q->slib; +	/* queue must be cleared for qdio_establish */ +	memset(q, 0, sizeof(*q)); +	memset(slib, 0, PAGE_SIZE); +	q->slib = slib;  	q->irq_ptr = irq_ptr;  	q->mask = 1 << (31 - i);  	q->nr = i; diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index ce5f8910ff8..8daf1b99f15 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -95,7 +95,7 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)  	for_each_input_queue(irq_ptr, q, i)  		list_add_rcu(&q->entry, &tiq_list);  	mutex_unlock(&tiq_list_lock); -	xchg(irq_ptr->dsci, 1); +	xchg(irq_ptr->dsci, 1 << 7);  }  void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) @@ -173,7 +173,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data)  		/* prevent racing */  		if (*tiqdio_alsi) -			xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); +			xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7);  	}  } diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 304caf54997..41e0aaefafd 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -302,7 +302,7 @@ static ssize_t zcrypt_write(struct file *filp, const char __user *buf,  static int zcrypt_open(struct inode *inode, struct file *filp)  {  	atomic_inc(&zcrypt_open_count); -	return 0; +	return nonseekable_open(inode, filp);  }  /** diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3ba738b2e27..28f71349fde 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1292,13 +1292,14 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)  		QETH_QDIO_CLEANING)) {  	case QETH_QDIO_ESTABLISHED:  		if (card->info.type == QETH_CARD_TYPE_IQD) -			rc = qdio_cleanup(CARD_DDEV(card), +			rc = qdio_shutdown(CARD_DDEV(card),  				QDIO_FLAG_CLEANUP_USING_HALT);  		else -			rc = qdio_cleanup(CARD_DDEV(card), +			rc = qdio_shutdown(CARD_DDEV(card),  				QDIO_FLAG_CLEANUP_USING_CLEAR);  		if (rc)  			QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); +		qdio_free(CARD_DDEV(card));  		atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);  		break;  	case QETH_QDIO_CLEANING: @@ -3810,10 +3811,18 @@ static int qeth_qdio_establish(struct qeth_card *card)  	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,  		QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { -		rc = qdio_initialize(&init_data); -		if (rc) +		rc = qdio_allocate(&init_data); +		if (rc) { +			atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); +			goto out; +		} +		rc = qdio_establish(&init_data); +		if (rc) {  			atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); +			qdio_free(CARD_DDEV(card)); +		}  	} +out:  	kfree(out_sbal_ptrs);  	kfree(in_sbal_ptrs);  	kfree(qib_param_field); diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 25d9e0ae9c5..1a2db0a3573 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -254,6 +254,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,  }  static const struct file_operations zfcp_cfdc_fops = { +	.open = nonseekable_open,  	.unlocked_ioctl = zfcp_cfdc_dev_ioctl,  #ifdef CONFIG_COMPAT  	.compat_ioctl = zfcp_cfdc_dev_ioctl diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 9201afe6560..7f87979da22 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -4724,6 +4724,10 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)  	BUG_ON((unsigned long)asc_dvc->overrun_buf & 7);  	asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf,  					ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); +	if (dma_mapping_error(board->dev, asc_dvc->overrun_dma)) { +		warn_code = -ENOMEM; +		goto err_dma_map; +	}  	phy_addr = cpu_to_le32(asc_dvc->overrun_dma);  	AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,  				 (uchar *)&phy_addr, 1); @@ -4739,14 +4743,23 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)  	AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);  	if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {  		asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; -		return warn_code; +		warn_code = UW_ERR; +		goto err_mcode_start;  	}  	if (AscStartChip(iop_base) != 1) {  		asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; -		return warn_code; +		warn_code = UW_ERR; +		goto err_mcode_start;  	}  	return warn_code; + +err_mcode_start: +	dma_unmap_single(board->dev, asc_dvc->overrun_dma, +			 ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); +err_dma_map: +	asc_dvc->overrun_dma = 0; +	return warn_code;  }  static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) @@ -4802,6 +4815,8 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)  	}  	release_firmware(fw);  	warn_code |= AscInitMicroCodeVar(asc_dvc); +	if (!asc_dvc->overrun_dma) +		return warn_code;  	asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;  	AscEnableInterrupt(iop_base);  	return warn_code; @@ -7978,9 +7993,10 @@ static int advansys_reset(struct scsi_cmnd *scp)  		status = AscInitAsc1000Driver(asc_dvc);  		/* Refer to ASC_IERR_* definitions for meaning of 'err_code'. */ -		if (asc_dvc->err_code) { +		if (asc_dvc->err_code || !asc_dvc->overrun_dma) {  			scmd_printk(KERN_INFO, scp, "SCSI bus reset error: " -				    "0x%x\n", asc_dvc->err_code); +				    "0x%x, status: 0x%x\n", asc_dvc->err_code, +				    status);  			ret = FAILED;  		} else if (status) {  			scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: " @@ -12311,7 +12327,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,  		asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL);  		if (!asc_dvc_varp->overrun_buf) {  			ret = -ENOMEM; -			goto err_free_wide_mem; +			goto err_free_irq;  		}  		warn_code = AscInitAsc1000Driver(asc_dvc_varp); @@ -12320,30 +12336,36 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,  					"warn 0x%x, error 0x%x\n",  					asc_dvc_varp->init_state, warn_code,  					asc_dvc_varp->err_code); -			if (asc_dvc_varp->err_code) { +			if (!asc_dvc_varp->overrun_dma) {  				ret = -ENODEV; -				kfree(asc_dvc_varp->overrun_buf); +				goto err_free_mem;  			}  		}  	} else { -		if (advansys_wide_init_chip(shost)) +		if (advansys_wide_init_chip(shost)) {  			ret = -ENODEV; +			goto err_free_mem; +		}  	} -	if (ret) -		goto err_free_wide_mem; -  	ASC_DBG_PRT_SCSI_HOST(2, shost);  	ret = scsi_add_host(shost, boardp->dev);  	if (ret) -		goto err_free_wide_mem; +		goto err_free_mem;  	scsi_scan_host(shost);  	return 0; - err_free_wide_mem: -	advansys_wide_free_mem(boardp); + err_free_mem: +	if (ASC_NARROW_BOARD(boardp)) { +		if (asc_dvc_varp->overrun_dma) +			dma_unmap_single(boardp->dev, asc_dvc_varp->overrun_dma, +					 ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); +		kfree(asc_dvc_varp->overrun_buf); +	} else +		advansys_wide_free_mem(boardp); + err_free_irq:  	free_irq(boardp->irq, shost);   err_free_dma:  #ifdef CONFIG_ISA diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 6d5ae4474bb..633e0903635 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -471,12 +471,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)  	WARN_ON(hdrlength >= 256);  	hdr->hlength = hdrlength & 0xFF; +	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);  	if (session->tt->init_task && session->tt->init_task(task))  		return -EIO;  	task->state = ISCSI_TASK_RUNNING; -	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);  	session->cmdsn++;  	conn->scsicmd_pdus_cnt++; diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index b00efd19aad..88f74467257 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -395,11 +395,15 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,  void sas_ata_task_abort(struct sas_task *task)  {  	struct ata_queued_cmd *qc = task->uldd_task; +	struct request_queue *q = qc->scsicmd->device->request_queue;  	struct completion *waiting; +	unsigned long flags;  	/* Bounce SCSI-initiated commands to the SCSI EH */  	if (qc->scsicmd) { +		spin_lock_irqsave(q->queue_lock, flags);  		blk_abort_request(qc->scsicmd->request); +		spin_unlock_irqrestore(q->queue_lock, flags);  		scsi_schedule_eh(qc->scsicmd->device->host);  		return;  	} diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 2660e1b4569..822835055ce 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -1030,6 +1030,8 @@ int __sas_task_abort(struct sas_task *task)  void sas_task_abort(struct sas_task *task)  {  	struct scsi_cmnd *sc = task->uldd_task; +	struct request_queue *q = sc->device->request_queue; +	unsigned long flags;  	/* Escape for libsas internal commands */  	if (!sc) { @@ -1044,7 +1046,9 @@ void sas_task_abort(struct sas_task *task)  		return;  	} +	spin_lock_irqsave(q->queue_lock, flags);  	blk_abort_request(sc->request); +	spin_unlock_irqrestore(q->queue_lock, flags);  	scsi_schedule_eh(sc->device->host);  } diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 3e10c306de9..3a5bfd10b2c 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -957,7 +957,8 @@ static int resp_start_stop(struct scsi_cmnd * scp,  static sector_t get_sdebug_capacity(void)  {  	if (scsi_debug_virtual_gb > 0) -		return 2048 * 1024 * (sector_t)scsi_debug_virtual_gb; +		return (sector_t)scsi_debug_virtual_gb * +			(1073741824 / scsi_debug_sector_size);  	else  		return sdebug_store_sectors;  } diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d45c69ca573..7ad53fa4276 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -302,7 +302,20 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)  		if (scmd->device->allow_restart &&  		    (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))  			return FAILED; -		return SUCCESS; + +		if (blk_barrier_rq(scmd->request)) +			/* +			 * barrier requests should always retry on UA +			 * otherwise block will get a spurious error +			 */ +			return NEEDS_RETRY; +		else +			/* +			 * for normal (non barrier) commands, pass the +			 * UA upwards for a determination in the +			 * completion functions +			 */ +			return SUCCESS;  		/* these three are not supported */  	case COPY_ABORTED: diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8b827f37b03..de6c60320f6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1040,6 +1040,7 @@ static void sd_prepare_flush(struct request_queue *q, struct request *rq)  {  	rq->cmd_type = REQ_TYPE_BLOCK_PC;  	rq->timeout = SD_TIMEOUT; +	rq->retries = SD_MAX_RETRIES;  	rq->cmd[0] = SYNCHRONIZE_CACHE;  	rq->cmd_len = 10;  } diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 105449c15fa..e17764d7147 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -69,6 +69,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {  	},  	{ 0 }  }; +MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl);  static int __devinit zorro7xx_init_one(struct zorro_dev *z,  				       const struct zorro_device_id *ent) diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 24485cc62ff..4822cb50cd0 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -348,6 +348,8 @@ static const struct pnp_device_id pnp_dev_table[] = {  	{	"FUJ02E6",		0	},  	/* Fujitsu Wacom 2FGT Tablet PC device */  	{	"FUJ02E7",		0	}, +	/* Fujitsu Wacom 1FGT Tablet PC device */ +	{	"FUJ02E9",		0	},  	/*  	 * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in  	 * disguise) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4315b23590b..eacb588a934 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -120,7 +120,8 @@  #define  MX2_UCR3_RXDMUXSEL	 (1<<2)  /* RXD Muxed Input Select, on mx2/mx3 */  #define  UCR3_INVT  	 (1<<1)  /* Inverted Infrared transmission */  #define  UCR3_BPEN  	 (1<<0)  /* Preset registers enable */ -#define  UCR4_CTSTL_32   (32<<10) /* CTS trigger level (32 chars) */ +#define  UCR4_CTSTL_SHF  10      /* CTS trigger level shift */ +#define  UCR4_CTSTL_MASK 0x3F    /* CTS trigger is 6 bits wide */  #define  UCR4_INVR  	 (1<<9)  /* Inverted infrared reception */  #define  UCR4_ENIRI 	 (1<<8)  /* Serial infrared interrupt enable */  #define  UCR4_WKEN  	 (1<<7)  /* Wake interrupt enable */ @@ -591,6 +592,9 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)  	return 0;  } +/* half the RX buffer size */ +#define CTSTL 16 +  static int imx_startup(struct uart_port *port)  {  	struct imx_port *sport = (struct imx_port *)port; @@ -607,6 +611,10 @@ static int imx_startup(struct uart_port *port)  	if (USE_IRDA(sport))  		temp |= UCR4_IRSC; +	/* set the trigger level for CTS */ +	temp &= ~(UCR4_CTSTL_MASK<<  UCR4_CTSTL_SHF); +	temp |= CTSTL<<  UCR4_CTSTL_SHF; +  	writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);  	if (USE_IRDA(sport)) { diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 3119fddaedb..02469c31bf0 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -29,39 +29,6 @@   * kind, whether express or implied.   */ -/* Platform device Usage : - * - * Since PSCs can have multiple function, the correct driver for each one - * is selected by calling mpc52xx_match_psc_function(...). The function - * handled by this driver is "uart". - * - * The driver init all necessary registers to place the PSC in uart mode without - * DCD. However, the pin multiplexing aren't changed and should be set either - * by the bootloader or in the platform init code. - * - * The idx field must be equal to the PSC index (e.g. 0 for PSC1, 1 for PSC2, - * and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and - * so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly - * fpr the console code : without this 1:1 mapping, at early boot time, when we - * are parsing the kernel args console=ttyPSC?, we wouldn't know which PSC it - * will be mapped to. - */ - -/* OF Platform device Usage : - * - * This driver is only used for PSCs configured in uart mode.  The device - * tree will have a node for each PSC with "mpc52xx-psc-uart" in the compatible - * list. - * - * By default, PSC devices are enumerated in the order they are found.  However - * a particular PSC number can be forces by adding 'device_no = <port#>' - * to the device node. - * - * The driver init all necessary registers to place the PSC in uart mode without - * DCD. However, the pin multiplexing aren't changed and should be set either - * by the bootloader or in the platform init code. - */ -  #undef DEBUG  #include <linux/device.h> @@ -1500,7 +1467,7 @@ mpc52xx_uart_init(void)  	/*  	 * Map the PSC FIFO Controller and init if on MPC512x.  	 */ -	if (psc_ops->fifoc_init) { +	if (psc_ops && psc_ops->fifoc_init) {  		ret = psc_ops->fifoc_init();  		if (ret)  			return ret; diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 4eaa043ca2a..700e10833bf 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -752,8 +752,10 @@ static void pmz_break_ctl(struct uart_port *port, int break_state)  		uap->curregs[R5] = new_reg;  		/* NOTE: Not subject to 'transmitter active' rule. */ -		if (ZS_IS_ASLEEP(uap)) +		if (ZS_IS_ASLEEP(uap)) { +			spin_unlock_irqrestore(&port->lock, flags);  			return; +		}  		write_zsreg(uap, R5, uap->curregs[R5]);  	} diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c index 2e71bbc04da..b1962025b1a 100644 --- a/drivers/serial/serial_ks8695.c +++ b/drivers/serial/serial_ks8695.c @@ -650,6 +650,7 @@ static struct console ks8695_console = {  static int __init ks8695_console_init(void)  { +	add_preferred_console(SERIAL_KS8695_DEVNAME, 0, NULL);  	register_console(&ks8695_console);  	return 0;  } diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index d8356af118a..e0de0d0eede 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -204,6 +204,7 @@ static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)  	cs->chconf0 = val;  	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val); +	mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);  }  static void omap2_mcspi_set_dma_req(const struct spi_device *spi, @@ -532,7 +533,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)  					goto out;  				}  #ifdef VERBOSE -				dev_dbg(&spi->dev, "write-%d %04x\n", +				dev_dbg(&spi->dev, "write-%d %08x\n",  						word_len, *tx);  #endif  				__raw_writel(*tx++, tx_reg); @@ -550,7 +551,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)  					mcspi_write_chconf0(spi, l);  				*rx++ = __raw_readl(rx_reg);  #ifdef VERBOSE -				dev_dbg(&spi->dev, "read-%d %04x\n", +				dev_dbg(&spi->dev, "read-%d %08x\n",  						word_len, *(rx - 1));  #endif  			} diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9ffb0fdbd6f..b3a1f9259b6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -41,7 +41,7 @@ static void spidev_release(struct device *dev)  		spi->master->cleanup(spi);  	spi_master_put(spi->master); -	kfree(dev); +	kfree(spi);  }  static ssize_t @@ -257,6 +257,7 @@ int spi_add_device(struct spi_device *spi)  {  	static DEFINE_MUTEX(spi_add_lock);  	struct device *dev = spi->master->dev.parent; +	struct device *d;  	int status;  	/* Chipselects are numbered 0..max; validate. */ @@ -278,10 +279,11 @@ int spi_add_device(struct spi_device *spi)  	 */  	mutex_lock(&spi_add_lock); -	if (bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev)) -			!= NULL) { +	d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev)); +	if (d != NULL) {  		dev_err(dev, "chipselect %d already in use\n",  				spi->chip_select); +		put_device(d);  		status = -EBUSY;  		goto done;  	} diff --git a/drivers/staging/dt3155/dt3155_drv.c b/drivers/staging/dt3155/dt3155_drv.c index e2c44ec6fc4..7ac2c6d8e9a 100644 --- a/drivers/staging/dt3155/dt3155_drv.c +++ b/drivers/staging/dt3155/dt3155_drv.c @@ -464,9 +464,9 @@ static void dt3155_init_isr(int minor)    /* 50/60 Hz should be set before this point but let's make sure it is */    /* right anyway */ -  ReadI2C(dt3155_lbase[ minor ], CONFIG, &i2c_csr2.reg); +  ReadI2C(dt3155_lbase[ minor ], CSR2, &i2c_csr2.reg);    i2c_csr2.fld.HZ50 = FORMAT50HZ; -  WriteI2C(dt3155_lbase[ minor ], CONFIG, i2c_config.reg); +  WriteI2C(dt3155_lbase[ minor ], CSR2, i2c_csr2.reg);    /* enable busmaster chip, clear flags */ diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c index 5d53889fb4a..3a1112d29ae 100644 --- a/drivers/staging/hv/Hv.c +++ b/drivers/staging/hv/Hv.c @@ -306,9 +306,9 @@ void HvCleanup(void)  	DPRINT_ENTER(VMBUS);  	if (gHvContext.SignalEventBuffer) { +		kfree(gHvContext.SignalEventBuffer);  		gHvContext.SignalEventBuffer = NULL;  		gHvContext.SignalEventParam = NULL; -		kfree(gHvContext.SignalEventBuffer);  	}  	if (gHvContext.HypercallPage) { diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c index cd2930de217..6704f64c93f 100644 --- a/drivers/staging/hv/RndisFilter.c +++ b/drivers/staging/hv/RndisFilter.c @@ -751,6 +751,7 @@ static int RndisFilterOpenDevice(struct rndis_device *Device)  	ret = RndisFilterSetPacketFilter(Device,  					 NDIS_PACKET_TYPE_BROADCAST | +					 NDIS_PACKET_TYPE_ALL_MULTICAST |  					 NDIS_PACKET_TYPE_DIRECTED);  	if (ret == 0)  		Device->State = RNDIS_DEV_DATAINITIALIZED; diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 2ccb6b93fe4..ab27d9a4446 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -403,8 +403,7 @@ static int netvsc_probe(struct device *device)  	if (!net_drv_obj->Base.OnDeviceAdd)  		return -1; -	net = alloc_netdev(sizeof(struct net_device_context), "seth%d", -			   ether_setup); +	net = alloc_etherdev(sizeof(struct net_device_context));  	if (!net)  		return -1; diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index ea76902797b..82e43588e8a 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -618,7 +618,7 @@ static int lis3l02dq_thresh_handler_th(struct iio_dev *dev_info,  static void lis3l02dq_thresh_handler_bh_no_check(struct work_struct *work_s)  {  	struct iio_work_cont *wc -		= container_of(work_s, struct iio_work_cont, ws_nocheck); +		= container_of(work_s, struct iio_work_cont, ws);  	struct lis3l02dq_state *st = wc->st;  	u8 t; diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 93712430e57..a4d97ea0df3 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -493,6 +493,9 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)  	struct lis3l02dq_state *state = indio_dev->dev_data;  	state->trig = iio_allocate_trigger(); +	if (!state->trig) +		return -ENOMEM; +  	state->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL);  	if (!state->trig->name) {  		ret = -ENOMEM; diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 790d1cc9cdc..773f1d1d9c6 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -557,6 +557,7 @@ error_put_reg:  	if (!IS_ERR(st->reg))  		regulator_put(st->reg);  error_free_st: +	i2c_set_clientdata(client, NULL);  	kfree(st);  error_ret: @@ -574,6 +575,7 @@ static int max1363_remove(struct i2c_client *client)  		regulator_disable(st->reg);  		regulator_put(st->reg);  	} +	i2c_set_clientdata(client, NULL);  	kfree(st);  	return 0; diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 37f58f66e49..1d77082c853 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -537,6 +537,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *dev_info)  	sysfs_remove_group(&dev_info->dev.kobj, dev_info->attrs);  } +/* Return a negative errno on failure */  int iio_get_new_idr_val(struct idr *this_idr)  {  	int ret; @@ -660,7 +661,7 @@ static int iio_device_register_eventset(struct iio_dev *dev_info)  	for (i = 0; i < dev_info->num_interrupt_lines; i++) {  		dev_info->event_interfaces[i].owner = dev_info->driver_module;  		ret = iio_get_new_idr_val(&iio_event_idr); -		if (ret) +		if (ret < 0)  			goto error_free_setup_ev_ints;  		else  			dev_info->event_interfaces[i].id = ret; diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 1ba4aa392f6..8770a00e365 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -682,6 +682,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client,  fail2:  	iio_device_unregister(chip->indio_dev);  fail1: +	i2c_set_clientdata(client, NULL);  	kfree(chip);  	return err;  } @@ -692,6 +693,7 @@ static int tsl2563_remove(struct i2c_client *client)  	iio_device_unregister(chip->indio_dev); +	i2c_set_clientdata(client, NULL);  	kfree(chip);  	return 0;  } diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index b104c3d9c35..cf22c091668 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -293,7 +293,7 @@ again:  		return -EAGAIN;  	memcpy(data, last_written_p_copy, ring->buf.bpd); -	if (unlikely(ring->last_written_p >= last_written_p_copy)) +	if (unlikely(ring->last_written_p != last_written_p_copy))  		goto again;  	iio_unmark_sw_rb_in_use(&ring->buf); diff --git a/drivers/staging/octeon/cvmx-helper-board.c b/drivers/staging/octeon/cvmx-helper-board.c index 3085e38a6f9..00a555b8335 100644 --- a/drivers/staging/octeon/cvmx-helper-board.c +++ b/drivers/staging/octeon/cvmx-helper-board.c @@ -153,6 +153,14 @@ int cvmx_helper_board_get_mii_address(int ipd_port)  		 * through switch.  		 */  		return -1; + +	case CVMX_BOARD_TYPE_CUST_WSX16: +		if (ipd_port >= 0 && ipd_port <= 3) +			return ipd_port; +		else if (ipd_port >= 16 && ipd_port <= 19) +			return ipd_port - 16 + 4; +		else +			return -1;  	}  	/* Some unknown board. Somebody forgot to update this function... */ diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index 1873a79bb03..740db0c1ac0 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -63,6 +63,7 @@ struct usb_device_id rtusb_usb_id[] = {  	{USB_DEVICE(0x07D1, 0x3C11)},	/* D-Link */  	{USB_DEVICE(0x14B2, 0x3C07)},	/* AL */  	{USB_DEVICE(0x050D, 0x8053)},	/* Belkin */ +	{USB_DEVICE(0x050D, 0x825B)},	/* Belkin */  	{USB_DEVICE(0x14B2, 0x3C23)},	/* Airlink */  	{USB_DEVICE(0x14B2, 0x3C27)},	/* Airlink */  	{USB_DEVICE(0x07AA, 0x002F)},	/* Corega */ diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index e16256fe595..04d9b85f3d4 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -113,14 +113,17 @@ u32 rt_global_debug_component = \  static const struct usb_device_id rtl8192_usb_id_tbl[] = {  	/* Realtek */ +	{USB_DEVICE(0x0bda, 0x8171)},  	{USB_DEVICE(0x0bda, 0x8192)},  	{USB_DEVICE(0x0bda, 0x8709)},  	/* Corega */  	{USB_DEVICE(0x07aa, 0x0043)},  	/* Belkin */  	{USB_DEVICE(0x050d, 0x805E)}, +	{USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */  	/* Sitecom */  	{USB_DEVICE(0x0df6, 0x0031)}, +	{USB_DEVICE(0x0df6, 0x004b)},	/* WL-349 */  	/* EnGenius */  	{USB_DEVICE(0x1740, 0x9201)},  	/* Dlink */ diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c index 6da1021e8a6..a2566f1075d 100644 --- a/drivers/staging/usbip/usbip_event.c +++ b/drivers/staging/usbip/usbip_event.c @@ -117,6 +117,9 @@ void usbip_stop_eh(struct usbip_device *ud)  {  	struct usbip_task *eh = &ud->eh; +	if (eh->thread == current) +		return; /* do not wait for myself */ +  	wait_for_completion(&eh->thread_done);  	usbip_dbg_eh("usbip_eh has finished\n");  } diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c index 68f24425977..783051f59f1 100644 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ b/drivers/staging/vme/bridges/vme_tsi148.c @@ -2455,9 +2455,10 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	dev_info(&pdev->dev, "VME Write and flush and error check is %s\n",  		err_chk ? "enabled" : "disabled"); -	if (tsi148_crcsr_init(tsi148_bridge, pdev)) +	if (tsi148_crcsr_init(tsi148_bridge, pdev)) {  		dev_err(&pdev->dev, "CR/CSR configuration failed.\n");  		goto err_crcsr; +	}  	retval = vme_register_bridge(tsi148_bridge);  	if (retval != 0) { diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index be6331e2c27..5e1a253b08a 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1542,6 +1542,9 @@ static const struct usb_device_id acm_ids[] = {  	{ USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */  	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */  	}, +	{ USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ +	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ +	},  	/* Nokia S60 phones expose two ACM channels. The first is  	 * a modem and is picked up by the standard AT-command diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 97a819c23ef..7e594449600 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -109,7 +109,7 @@ config USB_SUSPEND  config USB_OTG  	bool  	depends on USB && EXPERIMENTAL -	select USB_SUSPEND +	depends on USB_SUSPEND  	default n diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index bdf87a8414a..2c95153c0f2 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -120,7 +120,7 @@ int usb_choose_configuration(struct usb_device *udev)  		 * than a vendor-specific driver. */  		else if (udev->descriptor.bDeviceClass !=  						USB_CLASS_VENDOR_SPEC && -				(!desc || desc->bInterfaceClass != +				(desc && desc->bInterfaceClass !=  						USB_CLASS_VENDOR_SPEC)) {  			best = c;  			break; diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 97b40ce133f..111a01a747f 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -380,6 +380,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)  	mutex_lock(&inode->i_mutex);  	dentry_unhash(dentry);  	if (usbfs_empty(dentry)) { +		dont_mount(dentry);  		drop_nlink(dentry->d_inode);  		drop_nlink(dentry->d_inode);  		dput(dentry); @@ -515,13 +516,13 @@ static int fs_create_by_name (const char *name, mode_t mode,  	*dentry = NULL;  	mutex_lock(&parent->d_inode->i_mutex);  	*dentry = lookup_one_len(name, parent, strlen(name)); -	if (!IS_ERR(dentry)) { +	if (!IS_ERR(*dentry)) {  		if ((mode & S_IFMT) == S_IFDIR)  			error = usbfs_mkdir (parent->d_inode, *dentry, mode);  		else   			error = usbfs_create (parent->d_inode, *dentry, mode);  	} else -		error = PTR_ERR(dentry); +		error = PTR_ERR(*dentry);  	mutex_unlock(&parent->d_inode->i_mutex);  	return error; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 1297e9b16a5..0561430f2ed 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -718,7 +718,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,  EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);  /** - * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP + * usb_alloc_coherent - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP   * @dev: device the buffer will be used with   * @size: requested buffer size   * @mem_flags: affect whether allocation may block @@ -737,30 +737,30 @@ EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);   * architectures where CPU caches are not DMA-coherent.  On systems without   * bus-snooping caches, these buffers are uncached.   * - * When the buffer is no longer used, free it with usb_buffer_free(). + * When the buffer is no longer used, free it with usb_free_coherent().   */ -void *usb_buffer_alloc(struct usb_device *dev, size_t size, gfp_t mem_flags, -		       dma_addr_t *dma) +void *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags, +			 dma_addr_t *dma)  {  	if (!dev || !dev->bus)  		return NULL;  	return hcd_buffer_alloc(dev->bus, size, mem_flags, dma);  } -EXPORT_SYMBOL_GPL(usb_buffer_alloc); +EXPORT_SYMBOL_GPL(usb_alloc_coherent);  /** - * usb_buffer_free - free memory allocated with usb_buffer_alloc() + * usb_free_coherent - free memory allocated with usb_alloc_coherent()   * @dev: device the buffer was used with   * @size: requested buffer size   * @addr: CPU address of buffer   * @dma: DMA address of buffer   *   * This reclaims an I/O buffer, letting it be reused.  The memory must have - * been allocated using usb_buffer_alloc(), and the parameters must match + * been allocated using usb_alloc_coherent(), and the parameters must match   * those provided in that allocation request.   */ -void usb_buffer_free(struct usb_device *dev, size_t size, void *addr, -		     dma_addr_t dma) +void usb_free_coherent(struct usb_device *dev, size_t size, void *addr, +		       dma_addr_t dma)  {  	if (!dev || !dev->bus)  		return; @@ -768,7 +768,7 @@ void usb_buffer_free(struct usb_device *dev, size_t size, void *addr,  		return;  	hcd_buffer_free(dev->bus, size, addr, dma);  } -EXPORT_SYMBOL_GPL(usb_buffer_free); +EXPORT_SYMBOL_GPL(usb_free_coherent);  /**   * usb_buffer_map - create DMA mapping(s) for an urb diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 124a8ccfdcd..1f73b485732 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2145,6 +2145,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,  	u32 epctrl;  	u32 mps;  	int dir_in; +	int ret = 0;  	dev_dbg(hsotg->dev,  		"%s: ep %s: a 0x%02x, attr 0x%02x, mps 0x%04x, intr %d\n", @@ -2196,7 +2197,8 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,  	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {  	case USB_ENDPOINT_XFER_ISOC:  		dev_err(hsotg->dev, "no current ISOC support\n"); -		return -EINVAL; +		ret = -EINVAL; +		goto out;  	case USB_ENDPOINT_XFER_BULK:  		epctrl |= S3C_DxEPCTL_EPType_Bulk; @@ -2235,8 +2237,9 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,  	/* enable the endpoint interrupt */  	s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); +out:  	spin_unlock_irqrestore(&hs_ep->lock, flags); -	return 0; +	return ret;  }  static int s3c_hsotg_ep_disable(struct usb_ep *ep) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 68b83ab7071..944291e10f9 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -331,6 +331,8 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)  	 */  	if (at91_suspend_entering_slow_clock()) {  		ohci_usb_reset (ohci); +		/* flush the writes */ +		(void) ohci_readl (ohci, &ohci->regs->control);  		at91_stop_clock();  	} diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 32bbce9718f..65cac8cc892 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -697,7 +697,7 @@ static int ohci_hub_control (  	u16		wLength  ) {  	struct ohci_hcd	*ohci = hcd_to_ohci (hcd); -	int		ports = hcd_to_bus (hcd)->root_hub->maxchild; +	int		ports = ohci->num_ports;  	u32		temp;  	int		retval = 0; diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 50f57f46883..e62b30b3e42 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -660,13 +660,13 @@ static struct ehci_qh *oxu_qh_alloc(struct oxu_hcd *oxu)  		if (qh->dummy == NULL) {  			oxu_dbg(oxu, "no dummy td\n");  			oxu->qh_used[i] = 0; - -			return NULL; +			qh = NULL; +			goto unlock;  		}  		oxu->qh_used[i] = 1;  	} - +unlock:  	spin_unlock(&oxu->mem_lock);  	return qh; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index e11cc3aa4b8..3b867a8af7b 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -720,10 +720,10 @@ retry:  		/* port status seems weird until after reset, so  		 * force the reset and make khubd clean up later.  		 */ -		if (sl811->stat_insrmv & 1) -			sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION; -		else +		if (irqstat & SL11H_INTMASK_RD)  			sl811->port1 &= ~(1 << USB_PORT_FEAT_CONNECTION); +		else +			sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION;  		sl811->port1 |= 1 << USB_PORT_FEAT_C_CONNECTION; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index c09539bad1e..d64f5724bfc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -582,6 +582,19 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,  	return EP_INTERVAL(interval);  } +/* The "Mult" field in the endpoint context is only set for SuperSpeed devices. + * High speed endpoint descriptors can define "the number of additional + * transaction opportunities per microframe", but that goes in the Max Burst + * endpoint context field. + */ +static inline u32 xhci_get_endpoint_mult(struct usb_device *udev, +		struct usb_host_endpoint *ep) +{ +	if (udev->speed != USB_SPEED_SUPER || !ep->ss_ep_comp) +		return 0; +	return ep->ss_ep_comp->desc.bmAttributes; +} +  static inline u32 xhci_get_endpoint_type(struct usb_device *udev,  		struct usb_host_endpoint *ep)  { @@ -612,6 +625,36 @@ static inline u32 xhci_get_endpoint_type(struct usb_device *udev,  	return type;  } +/* Return the maximum endpoint service interval time (ESIT) payload. + * Basically, this is the maxpacket size, multiplied by the burst size + * and mult size. + */ +static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci, +		struct usb_device *udev, +		struct usb_host_endpoint *ep) +{ +	int max_burst; +	int max_packet; + +	/* Only applies for interrupt or isochronous endpoints */ +	if (usb_endpoint_xfer_control(&ep->desc) || +			usb_endpoint_xfer_bulk(&ep->desc)) +		return 0; + +	if (udev->speed == USB_SPEED_SUPER) { +		if (ep->ss_ep_comp) +			return ep->ss_ep_comp->desc.wBytesPerInterval; +		xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n"); +		/* Assume no bursts, no multiple opportunities to send. */ +		return ep->desc.wMaxPacketSize; +	} + +	max_packet = ep->desc.wMaxPacketSize & 0x3ff; +	max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11; +	/* A 0 in max burst means 1 transfer per ESIT */ +	return max_packet * (max_burst + 1); +} +  int xhci_endpoint_init(struct xhci_hcd *xhci,  		struct xhci_virt_device *virt_dev,  		struct usb_device *udev, @@ -623,6 +666,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,  	struct xhci_ring *ep_ring;  	unsigned int max_packet;  	unsigned int max_burst; +	u32 max_esit_payload;  	ep_index = xhci_get_endpoint_index(&ep->desc);  	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); @@ -644,6 +688,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,  	ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;  	ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep); +	ep_ctx->ep_info |= EP_MULT(xhci_get_endpoint_mult(udev, ep));  	/* FIXME dig Mult and streams info out of ep companion desc */ @@ -689,6 +734,26 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,  	default:  		BUG();  	} +	max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep); +	ep_ctx->tx_info = MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload); + +	/* +	 * XXX no idea how to calculate the average TRB buffer length for bulk +	 * endpoints, as the driver gives us no clue how big each scatter gather +	 * list entry (or buffer) is going to be. +	 * +	 * For isochronous and interrupt endpoints, we set it to the max +	 * available, until we have new API in the USB core to allow drivers to +	 * declare how much bandwidth they actually need. +	 * +	 * Normally, it would be calculated by taking the total of the buffer +	 * lengths in the TD and then dividing by the number of TRBs in a TD, +	 * including link TRBs, No-op TRBs, and Event data TRBs.  Since we don't +	 * use Event Data TRBs, and we don't chain in a link TRB on short +	 * transfers, we're basically dividing by 1. +	 */ +	ep_ctx->tx_info |= AVG_TRB_LENGTH_FOR_EP(max_esit_payload); +  	/* FIXME Debug endpoint context */  	return 0;  } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e5eb09b2f38..ea389e9a493 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -609,6 +609,10 @@ struct xhci_ep_ctx {  #define MAX_PACKET_MASK		(0xffff << 16)  #define MAX_PACKET_DECODED(p)	(((p) >> 16) & 0xffff) +/* tx_info bitmasks */ +#define AVG_TRB_LENGTH_FOR_EP(p)	((p) & 0xffff) +#define MAX_ESIT_PAYLOAD_FOR_EP(p)	(((p) & 0xffff) << 16) +  /**   * struct xhci_input_control_context diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index b4c783c284b..07fe490b44d 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -42,7 +42,7 @@ config USB_MUSB_SOC  	default y if (BF52x && !BF522 && !BF523)  comment "DaVinci 35x and 644x USB support" -	depends on USB_MUSB_HDRC && ARCH_DAVINCI +	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx  comment "OMAP 243x high speed USB support"  	depends on USB_MUSB_HDRC && ARCH_OMAP2430 diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 85710ccc188..3a485dabebb 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -6,7 +6,7 @@ musb_hdrc-objs := musb_core.o  obj-$(CONFIG_USB_MUSB_HDRC)	+= musb_hdrc.o -ifeq ($(CONFIG_ARCH_DAVINCI),y) +ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y)  	musb_hdrc-objs	+= davinci.o  endif diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 719a22d664e..ec8d324237f 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -172,13 +172,7 @@ static irqreturn_t blackfin_interrupt(int irq, void *__hci)  	spin_unlock_irqrestore(&musb->lock, flags); -	/* REVISIT we sometimes get spurious IRQs on g_ep0 -	 * not clear why... fall in BF54x too. -	 */ -	if (retval != IRQ_HANDLED) -		DBG(5, "spurious?\n"); - -	return IRQ_HANDLED; +	return retval;  }  static void musb_conn_timer_handler(unsigned long _musb) diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 29bce5c0fd1..ce2e16fee0d 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -444,6 +444,8 @@ int __init musb_platform_init(struct musb *musb)  	return 0;  fail: +	clk_disable(musb->clock); +  	usb_nop_xceiv_unregister();  	return -ENODEV;  } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0e8b8ab1d16..705cc4ad873 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -965,10 +965,8 @@ static void musb_shutdown(struct platform_device *pdev)  	spin_lock_irqsave(&musb->lock, flags);  	musb_platform_disable(musb);  	musb_generic_disable(musb); -	if (musb->clock) { +	if (musb->clock)  		clk_put(musb->clock); -		musb->clock = NULL; -	}  	spin_unlock_irqrestore(&musb->lock, flags);  	/* FIXME power down */ @@ -1853,15 +1851,6 @@ static void musb_free(struct musb *musb)  	put_device(musb->xceiv->dev);  #endif -	musb_writeb(musb->mregs, MUSB_DEVCTL, 0); -	musb_platform_exit(musb); -	musb_writeb(musb->mregs, MUSB_DEVCTL, 0); - -	if (musb->clock) { -		clk_disable(musb->clock); -		clk_put(musb->clock); -	} -  #ifdef CONFIG_USB_MUSB_HDRC_HCD  	usb_put_hcd(musb_to_hcd(musb));  #else @@ -1889,8 +1878,10 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)  	 */  	if (!plat) {  		dev_dbg(dev, "no platform_data?\n"); -		return -ENODEV; +		status = -ENODEV; +		goto fail0;  	} +  	switch (plat->mode) {  	case MUSB_HOST:  #ifdef CONFIG_USB_MUSB_HDRC_HCD @@ -1912,13 +1903,16 @@ bad_config:  #endif  	default:  		dev_err(dev, "incompatible Kconfig role setting\n"); -		return -EINVAL; +		status = -EINVAL; +		goto fail0;  	}  	/* allocate */  	musb = allocate_instance(dev, plat->config, ctrl); -	if (!musb) -		return -ENOMEM; +	if (!musb) { +		status = -ENOMEM; +		goto fail0; +	}  	spin_lock_init(&musb->lock);  	musb->board_mode = plat->mode; @@ -1936,7 +1930,7 @@ bad_config:  		if (IS_ERR(musb->clock)) {  			status = PTR_ERR(musb->clock);  			musb->clock = NULL; -			goto fail; +			goto fail1;  		}  	} @@ -1955,12 +1949,12 @@ bad_config:  	 */  	musb->isr = generic_interrupt;  	status = musb_platform_init(musb); -  	if (status < 0) -		goto fail; +		goto fail2; +  	if (!musb->isr) {  		status = -ENODEV; -		goto fail2; +		goto fail3;  	}  #ifndef CONFIG_MUSB_PIO_ONLY @@ -1986,7 +1980,7 @@ bad_config:  			? MUSB_CONTROLLER_MHDRC  			: MUSB_CONTROLLER_HDRC, musb);  	if (status < 0) -		goto fail2; +		goto fail3;  #ifdef CONFIG_USB_MUSB_OTG  	setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); @@ -1999,7 +1993,7 @@ bad_config:  	if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {  		dev_err(dev, "request_irq %d failed!\n", nIrq);  		status = -ENODEV; -		goto fail2; +		goto fail3;  	}  	musb->nIrq = nIrq;  /* FIXME this handles wakeup irqs wrong */ @@ -2039,8 +2033,6 @@ bad_config:  		musb->xceiv->state = OTG_STATE_A_IDLE;  		status = usb_add_hcd(musb_to_hcd(musb), -1, 0); -		if (status) -			goto fail;  		DBG(1, "%s mode, status %d, devctl %02x %c\n",  			"HOST", status, @@ -2055,8 +2047,6 @@ bad_config:  		musb->xceiv->state = OTG_STATE_B_IDLE;  		status = musb_gadget_setup(musb); -		if (status) -			goto fail;  		DBG(1, "%s mode, status %d, dev%02x\n",  			is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", @@ -2064,12 +2054,14 @@ bad_config:  			musb_readb(musb->mregs, MUSB_DEVCTL));  	} +	if (status < 0) +		goto fail3;  #ifdef CONFIG_SYSFS  	status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); -#endif  	if (status) -		goto fail2; +		goto fail4; +#endif  	dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",  			({char *s; @@ -2085,17 +2077,29 @@ bad_config:  	return 0; -fail2: +fail4: +	if (!is_otg_enabled(musb) && is_host_enabled(musb)) +		usb_remove_hcd(musb_to_hcd(musb)); +	else +		musb_gadget_cleanup(musb); + +fail3: +	if (musb->irq_wake) +		device_init_wakeup(dev, 0);  	musb_platform_exit(musb); -fail: -	dev_err(musb->controller, -		"musb_init_controller failed with status %d\n", status); +fail2:  	if (musb->clock)  		clk_put(musb->clock); -	device_init_wakeup(dev, 0); + +fail1: +	dev_err(musb->controller, +		"musb_init_controller failed with status %d\n", status); +  	musb_free(musb); +fail0: +  	return status;  } @@ -2132,7 +2136,6 @@ static int __init musb_probe(struct platform_device *pdev)  	/* clobbered by use_dma=n */  	orig_dma_mask = dev->dma_mask;  #endif -  	status = musb_init_controller(dev, irq, base);  	if (status < 0)  		iounmap(base); @@ -2155,6 +2158,10 @@ static int __exit musb_remove(struct platform_device *pdev)  	if (musb->board_mode == MUSB_HOST)  		usb_remove_hcd(musb_to_hcd(musb));  #endif +	musb_writeb(musb->mregs, MUSB_DEVCTL, 0); +	musb_platform_exit(musb); +	musb_writeb(musb->mregs, MUSB_DEVCTL, 0); +  	musb_free(musb);  	iounmap(ctrl_base);  	device_init_wakeup(&pdev->dev, 0); @@ -2176,6 +2183,7 @@ void musb_save_context(struct musb *musb)  	if (is_host_enabled(musb)) {  		musb_context.frame = musb_readw(musb_base, MUSB_FRAME);  		musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE); +		musb_context.busctl = musb_read_ulpi_buscontrol(musb->mregs);  	}  	musb_context.power = musb_readb(musb_base, MUSB_POWER);  	musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); @@ -2247,6 +2255,7 @@ void musb_restore_context(struct musb *musb)  	if (is_host_enabled(musb)) {  		musb_writew(musb_base, MUSB_FRAME, musb_context.frame);  		musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode); +		musb_write_ulpi_buscontrol(musb->mregs, musb_context.busctl);  	}  	musb_writeb(musb_base, MUSB_POWER, musb_context.power);  	musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index cd9f4a9a06c..ac17b004909 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -478,7 +478,7 @@ struct musb_context_registers {  	u16 frame;  	u8 index, testmode; -	u8 devctl, misc; +	u8 devctl, busctl, misc;  	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];  }; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index dec896e888d..877d20b1dff 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2042,6 +2042,7 @@ static int musb_urb_enqueue(  		 * odd, rare, error prone, but legal.  		 */  		kfree(qh); +		qh = NULL;  		ret = 0;  	} else  		ret = musb_schedule(musb, qh, diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 490cdf15ccb..82592633502 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -331,8 +331,5 @@ int musb_platform_exit(struct musb *musb)  	musb_platform_suspend(musb); -	clk_put(musb->clock); -	musb->clock = NULL; -  	return 0;  } diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index ab776a8d98c..60d3938cafc 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -29,6 +29,19 @@ static void tusb_source_power(struct musb *musb, int is_on);  #define TUSB_REV_MAJOR(reg_val)		((reg_val >> 4) & 0xf)  #define TUSB_REV_MINOR(reg_val)		(reg_val & 0xf) +#ifdef CONFIG_PM +/* REVISIT: These should be only needed if somebody implements off idle */ +void musb_platform_save_context(struct musb *musb, +			struct musb_context_registers *musb_context) +{ +} + +void musb_platform_restore_context(struct musb *musb, +			struct musb_context_registers *musb_context) +{ +} +#endif +  /*   * Checks the revision. We need to use the DMA register as 3.0 does not   * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV. diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 5afa070d7dc..c061a88f2b0 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -39,7 +39,7 @@ struct tusb_omap_dma_ch {  	struct tusb_omap_dma	*tusb_dma; -	void __iomem		*dma_addr; +	dma_addr_t		dma_addr;  	u32			len;  	u16			packet_sz; @@ -126,6 +126,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)  	struct tusb_omap_dma_ch	*chdat = to_chdat(channel);  	struct tusb_omap_dma	*tusb_dma = chdat->tusb_dma;  	struct musb		*musb = chdat->musb; +	struct device		*dev = musb->controller;  	struct musb_hw_ep	*hw_ep = chdat->hw_ep;  	void __iomem		*ep_conf = hw_ep->conf;  	void __iomem		*mbase = musb->mregs; @@ -173,13 +174,15 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)  		DBG(3, "Using PIO for remaining %lu bytes\n", pio);  		buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len;  		if (chdat->tx) { -			dma_cache_maint(phys_to_virt((u32)chdat->dma_addr), -					chdat->transfer_len, DMA_TO_DEVICE); +			dma_unmap_single(dev, chdat->dma_addr, +						chdat->transfer_len, +						DMA_TO_DEVICE);  			musb_write_fifo(hw_ep, pio, buf);  		} else { +			dma_unmap_single(dev, chdat->dma_addr, +						chdat->transfer_len, +						DMA_FROM_DEVICE);  			musb_read_fifo(hw_ep, pio, buf); -			dma_cache_maint(phys_to_virt((u32)chdat->dma_addr), -					chdat->transfer_len, DMA_FROM_DEVICE);  		}  		channel->actual_len += pio;  	} @@ -224,6 +227,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,  	struct tusb_omap_dma_ch		*chdat = to_chdat(channel);  	struct tusb_omap_dma		*tusb_dma = chdat->tusb_dma;  	struct musb			*musb = chdat->musb; +	struct device			*dev = musb->controller;  	struct musb_hw_ep		*hw_ep = chdat->hw_ep;  	void __iomem			*mbase = musb->mregs;  	void __iomem			*ep_conf = hw_ep->conf; @@ -299,14 +303,16 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,  	chdat->packet_sz = packet_sz;  	chdat->len = len;  	channel->actual_len = 0; -	chdat->dma_addr = (void __iomem *)dma_addr; +	chdat->dma_addr = dma_addr;  	channel->status = MUSB_DMA_STATUS_BUSY;  	/* Since we're recycling dma areas, we need to clean or invalidate */  	if (chdat->tx) -		dma_cache_maint(phys_to_virt(dma_addr), len, DMA_TO_DEVICE); +		dma_map_single(dev, phys_to_virt(dma_addr), len, +				DMA_TO_DEVICE);  	else -		dma_cache_maint(phys_to_virt(dma_addr), len, DMA_FROM_DEVICE); +		dma_map_single(dev, phys_to_virt(dma_addr), len, +				DMA_FROM_DEVICE);  	/* Use 16-bit transfer if dma_addr is not 32-bit aligned */  	if ((dma_addr & 0x3) == 0) { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ca9d866672a..84d0edad8e4 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -305,6 +305,11 @@ static int  option_resume(struct usb_serial *serial);  #define ZTE_PRODUCT_CDMA_TECH			0xfffe  #define ZTE_PRODUCT_AC8710			0xfff1  #define ZTE_PRODUCT_AC2726			0xfff5 +#define ZTE_PRODUCT_AC8710T			0xffff + +/* ZTE PRODUCTS -- alternate vendor ID */ +#define ZTE_VENDOR_ID2				0x1d6b +#define ZTE_PRODUCT_MF_330			0x0002  #define BENQ_VENDOR_ID				0x04a5  #define BENQ_PRODUCT_H10			0x4068 @@ -373,6 +378,8 @@ static int  option_resume(struct usb_serial *serial);  #define HAIER_VENDOR_ID				0x201e  #define HAIER_PRODUCT_CE100			0x2009 +#define CINTERION_VENDOR_ID			0x0681 +  /* some devices interfaces need special handling due to a number of reasons */  enum option_blacklist_reason {  		OPTION_BLACKLIST_NONE = 0, @@ -679,6 +686,8 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE(ZTE_VENDOR_ID2, ZTE_PRODUCT_MF_330) },  	{ 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 */ @@ -716,6 +725,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},  	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, +	{ USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },  	{ } /* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index c97a0bb5b6d..c28b1607eac 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -59,6 +59,7 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) },  	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },  	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, +	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },  	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },  	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },  	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index a352d5f3a59..23c09b38b9e 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -20,6 +20,7 @@  #define PL2303_PRODUCT_ID_ALDIGA	0x0611  #define PL2303_PRODUCT_ID_MMX		0x0612  #define PL2303_PRODUCT_ID_GPRS		0x0609 +#define PL2303_PRODUCT_ID_HCR331	0x331a  #define ATEN_VENDOR_ID		0x0557  #define ATEN_VENDOR_ID2		0x0547 diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 880e990abb0..e1bfda33f5b 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1735,7 +1735,7 @@ static int ti_download_firmware(struct ti_device *tdev)  		return -ENOENT;  	}  	if (fw_p->size > TI_FIRMWARE_BUF_SIZE) { -		dev_err(&dev->dev, "%s - firmware too large %d \n", __func__, fw_p->size); +		dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size);  		return -ENOENT;  	} diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index e69d238c5af..49fa953aaf6 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1035,7 +1035,12 @@ int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len)  /* This actually signals the guest, using eventfd. */  void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)  { -	__u16 flags = 0; +	__u16 flags; +	/* Flush out used index updates. This is paired +	 * with the barrier that the Guest executes when enabling +	 * interrupts. */ +	smp_mb(); +  	if (get_user(flags, &vq->avail->flags)) {  		vq_err(vq, "Failed to get flags");  		return; diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index dca48df9844..e5d6b56d444 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -50,8 +50,9 @@  #include <linux/fb.h>  #include <linux/init.h>  #include <linux/ioport.h> - +#include <linux/platform_device.h>  #include <linux/uaccess.h> +  #include <asm/system.h>  #include <asm/irq.h>  #include <asm/amigahw.h> @@ -1135,7 +1136,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg  	 * Interface to the low level console driver  	 */ -static void amifb_deinit(void); +static void amifb_deinit(struct platform_device *pdev);  	/*  	 * Internal routines @@ -2246,7 +2247,7 @@ static inline void chipfree(void)  	 * Initialisation  	 */ -static int __init amifb_init(void) +static int __init amifb_probe(struct platform_device *pdev)  {  	int tag, i, err = 0;  	u_long chipptr; @@ -2261,16 +2262,6 @@ static int __init amifb_init(void)  	}  	amifb_setup(option);  #endif -	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) -		return -ENODEV; - -	/* -	 * We request all registers starting from bplpt[0] -	 */ -	if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, -				"amifb [Denise/Lisa]")) -		return -EBUSY; -  	custom.dmacon = DMAF_ALL | DMAF_MASTER;  	switch (amiga_chipset) { @@ -2377,6 +2368,7 @@ default_chipset:  	fb_info.fbops = &amifb_ops;  	fb_info.par = ¤tpar;  	fb_info.flags = FBINFO_DEFAULT; +	fb_info.device = &pdev->dev;  	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,  			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { @@ -2451,18 +2443,18 @@ default_chipset:  	return 0;  amifb_error: -	amifb_deinit(); +	amifb_deinit(pdev);  	return err;  } -static void amifb_deinit(void) +static void amifb_deinit(struct platform_device *pdev)  {  	if (fb_info.cmap.len)  		fb_dealloc_cmap(&fb_info.cmap); +	fb_dealloc_cmap(&fb_info.cmap);  	chipfree();  	if (videomemory)  		iounmap((void*)videomemory); -	release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);  	custom.dmacon = DMAF_ALL | DMAF_MASTER;  } @@ -3794,14 +3786,35 @@ static void ami_rebuild_copper(void)  	}  } -static void __exit amifb_exit(void) +static int __exit amifb_remove(struct platform_device *pdev)  {  	unregister_framebuffer(&fb_info); -	amifb_deinit(); +	amifb_deinit(pdev);  	amifb_video_off(); +	return 0; +} + +static struct platform_driver amifb_driver = { +	.remove = __exit_p(amifb_remove), +	.driver   = { +		.name	= "amiga-video", +		.owner	= THIS_MODULE, +	}, +}; + +static int __init amifb_init(void) +{ +	return platform_driver_probe(&amifb_driver, amifb_probe);  }  module_init(amifb_init); + +static void __exit amifb_exit(void) +{ +	platform_driver_unregister(&amifb_driver); +} +  module_exit(amifb_exit);  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-video"); diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 44e49c28b2a..c2ec3dcd4e9 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -488,9 +488,9 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)  	fbinfo->fbops = &bfin_t350mcqb_fb_ops;  	fbinfo->flags = FBINFO_FLAG_DEFAULT; -	info->fb_buffer = -	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, -			       GFP_KERNEL); +	info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len + +				ACTIVE_VIDEO_MEM_OFFSET, +				&info->dma_handle, GFP_KERNEL);  	if (NULL == info->fb_buffer) {  		printk(KERN_ERR DRIVER_NAME @@ -568,8 +568,8 @@ out7:  out6:  	fb_dealloc_cmap(&fbinfo->cmap);  out4: -	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, -			  info->dma_handle); +	dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET, +			 info->fb_buffer, info->dma_handle);  out3:  	framebuffer_release(fbinfo);  out2: @@ -592,8 +592,9 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev)  	free_irq(info->irq, info);  	if (info->fb_buffer != NULL) -		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, -				  info->dma_handle); +		dma_free_coherent(NULL, fbinfo->fix.smem_len + +			ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer, +			info->dma_handle);  	fb_dealloc_cmap(&fbinfo->cmap); diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8d8dfda2f86..6df7c54db0a 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -299,6 +299,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = {  	},  	{ 0 }  }; +MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);  static const struct {  	zorro_id id2; diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 6c91c61cdb6..1b0feb8e724 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = {  	{ ZORRO_PROD_HELFRICH_RAINBOW_II },  	{ 0 }  }; +MODULE_DEVICE_TABLE(zorro, fm2fb_devices);  static struct zorro_driver fm2fb_driver = {  	.name		= "fm2fb", diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index e14bd074912..e8c76994481 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -695,6 +695,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,  	 * 1) Enable Runtime PM  	 * 2) Force Runtime PM Resume since hardware is accessed from probe()  	 */ +	priv->dev = &pdev->dev;  	pm_runtime_enable(priv->dev);  	pm_runtime_resume(priv->dev);  	return 0; @@ -957,25 +958,24 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)  	if (!pdev->dev.platform_data) {  		dev_err(&pdev->dev, "no platform data defined\n"); -		error = -EINVAL; -		goto err0; +		return -EINVAL;  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	i = platform_get_irq(pdev, 0);  	if (!res || i < 0) {  		dev_err(&pdev->dev, "cannot get platform resources\n"); -		error = -ENOENT; -		goto err0; +		return -ENOENT;  	}  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (!priv) {  		dev_err(&pdev->dev, "cannot allocate device data\n"); -		error = -ENOMEM; -		goto err0; +		return -ENOMEM;  	} +	platform_set_drvdata(pdev, priv); +  	error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,  			    dev_name(&pdev->dev), priv);  	if (error) { @@ -984,8 +984,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)  	}  	priv->irq = i; -	priv->dev = &pdev->dev; -	platform_set_drvdata(pdev, priv);  	pdata = pdev->dev.platform_data;  	j = 0; @@ -1099,9 +1097,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)  		info = ch->info;  		if (info->fbdefio) { -			priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * +			ch->sglist = vmalloc(sizeof(struct scatterlist) *  					info->fix.smem_len >> PAGE_SHIFT); -			if (!priv->ch->sglist) { +			if (!ch->sglist) {  				dev_err(&pdev->dev, "cannot allocate sglist\n");  				goto err1;  			} @@ -1126,9 +1124,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)  	}  	return 0; - err1: +err1:  	sh_mobile_lcdc_remove(pdev); - err0: +  	return error;  } @@ -1139,7 +1137,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)  	int i;  	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) -		if (priv->ch[i].info->dev) +		if (priv->ch[i].info && priv->ch[i].info->dev)  			unregister_framebuffer(priv->ch[i].info);  	sh_mobile_lcdc_stop(priv); @@ -1162,7 +1160,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)  	if (priv->dot_clk)  		clk_put(priv->dot_clk); -	pm_runtime_disable(priv->dev); +	if (priv->dev) +		pm_runtime_disable(priv->dev);  	if (priv->base)  		iounmap(priv->base); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0bf5020d0d3..b87ba23442d 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -175,7 +175,7 @@ config SA1100_WATCHDOG  config MPCORE_WATCHDOG  	tristate "MPcore watchdog" -	depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS +	depends on HAVE_ARM_TWD  	help  	  Watchdog timer embedded into the MPcore system. diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 500d38342e1..801ead19149 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -121,7 +121,7 @@ static ssize_t booke_wdt_write(struct file *file, const char __user *buf,  	return count;  } -static const struct watchdog_info ident = { +static struct watchdog_info ident = {  	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,  	.identity = "PowerPC Book-E Watchdog",  }; diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 88ed54e50f7..59359c9a5e0 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -244,7 +244,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");  module_param(timeout, int, 0);  MODULE_PARM_DESC(timeout,  	"Watchdog timeout in seconds. (1<=timeout<=3600, default=" -				__MODULE_STRING(WATCHDOG_TIMEOUT) ")"); +				__MODULE_STRING(WDT_TIMEOUT) ")");  MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"  		"Alessandro Zummo <a.zummo@towertech.it>"); diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 016c6a791ca..b8ec7aca3c8 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -31,8 +31,9 @@  #include <linux/platform_device.h>  #include <linux/uaccess.h>  #include <linux/slab.h> +#include <linux/io.h> -#include <asm/hardware/arm_twd.h> +#include <asm/smp_twd.h>  struct mpcore_wdt {  	unsigned long	timer_alive; @@ -44,7 +45,7 @@ struct mpcore_wdt {  };  static struct platform_device *mpcore_wdt_dev; -extern unsigned int mpcore_timer_rate; +static DEFINE_SPINLOCK(wdt_lock);  #define TIMER_MARGIN	60  static int mpcore_margin = TIMER_MARGIN; @@ -94,13 +95,15 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg)   */  static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)  { -	unsigned int count; +	unsigned long count; +	spin_lock(&wdt_lock);  	/* Assume prescale is set to 256 */ -	count = (mpcore_timer_rate / 256) * mpcore_margin; +	count =  __raw_readl(wdt->base + TWD_WDOG_COUNTER); +	count = (0xFFFFFFFFU - count) * (HZ / 5); +	count = (count / 256) * mpcore_margin;  	/* Reload the counter */ -	spin_lock(&wdt_lock);  	writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);  	wdt->perturb = wdt->perturb ? 0 : 1;  	spin_unlock(&wdt_lock); @@ -119,7 +122,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt)  {  	dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); -	spin_lock(&wdt_lock);  	/* This loads the count register but does NOT start the count yet */  	mpcore_wdt_keepalive(wdt); @@ -130,7 +132,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt)  		/* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */  		writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);  	} -	spin_unlock(&wdt_lock);  }  static int mpcore_wdt_set_heartbeat(int t) @@ -360,7 +361,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)  	mpcore_wdt_miscdev.parent = &dev->dev;  	ret = misc_register(&mpcore_wdt_miscdev);  	if (ret) { -		dev_printk(KERN_ERR, _dev, +		dev_printk(KERN_ERR, wdt->dev,  			"cannot register miscdev on minor=%d (err=%d)\n",  							WATCHDOG_MINOR, ret);  		goto err_misc; @@ -369,13 +370,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)  	ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED,  							"mpcore_wdt", wdt);  	if (ret) { -		dev_printk(KERN_ERR, _dev, +		dev_printk(KERN_ERR, wdt->dev,  			"cannot register IRQ%d for watchdog\n", wdt->irq);  		goto err_irq;  	}  	mpcore_wdt_stop(wdt); -	platform_set_drvdata(&dev->dev, wdt); +	platform_set_drvdata(dev, wdt);  	mpcore_wdt_dev = dev;  	return 0; diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index c8eadd47817..88c83aa5730 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -67,8 +67,8 @@ static DEFINE_SPINLOCK(sbwd_lock);  void sbwdog_set(char __iomem *wdog, unsigned long t)  {  	spin_lock(&sbwd_lock); -	__raw_writeb(0, wdog - 0x10); -	__raw_writeq(t & 0x7fffffUL, wdog); +	__raw_writeb(0, wdog); +	__raw_writeq(t & 0x7fffffUL, wdog - 0x10);  	spin_unlock(&sbwd_lock);  } diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index 8d44c9b6fb5..c7d67e9a746 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -30,7 +30,7 @@  static int nowayout = WATCHDOG_NOWAYOUT;  static unsigned int margin = 60;	/* (secs) Default is 1 minute */  static unsigned long wdt_status; -static DEFINE_SPINLOCK(wdt_lock); +static DEFINE_MUTEX(wdt_lock);  #define WDT_IN_USE		0  #define WDT_OK_TO_CLOSE		1 @@ -45,26 +45,26 @@ static DEFINE_SPINLOCK(wdt_lock);  static void wdt_send_data(unsigned char command, unsigned char data)  { -	outb(command, COMMAND_PORT); -	msleep(100);  	outb(data, DATA_PORT);  	msleep(200); +	outb(command, COMMAND_PORT); +	msleep(100);  }  static void wdt_enable(void)  { -	spin_lock(&wdt_lock); +	mutex_lock(&wdt_lock);  	wdt_send_data(IFACE_ON_COMMAND, 1);  	wdt_send_data(REBOOT_COMMAND, margin); -	spin_unlock(&wdt_lock); +	mutex_unlock(&wdt_lock);  }  static void wdt_disable(void)  { -	spin_lock(&wdt_lock); +	mutex_lock(&wdt_lock);  	wdt_send_data(IFACE_ON_COMMAND, 0);  	wdt_send_data(REBOOT_COMMAND, 0); -	spin_unlock(&wdt_lock); +	mutex_unlock(&wdt_lock);  }  static int fitpc2_wdt_open(struct inode *inode, struct file *file) diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 2ac4440e7b0..8943b8ccee1 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -80,12 +80,6 @@ static void do_suspend(void)  	shutting_down = SHUTDOWN_SUSPEND; -	err = stop_machine_create(); -	if (err) { -		printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); -		goto out; -	} -  #ifdef CONFIG_PREEMPT  	/* If the kernel is preemptible, we need to freeze all the processes  	   to prevent them from being in the middle of a pagetable update @@ -93,7 +87,7 @@ static void do_suspend(void)  	err = freeze_processes();  	if (err) {  		printk(KERN_ERR "xen suspend: freeze failed %d\n", err); -		goto out_destroy_sm; +		goto out;  	}  #endif @@ -136,12 +130,8 @@ out_resume:  out_thaw:  #ifdef CONFIG_PREEMPT  	thaw_processes(); - -out_destroy_sm: -#endif -	stop_machine_destroy(); -  out: +#endif  	shutting_down = SHUTDOWN_INVALID;  }  #endif	/* CONFIG_PM_SLEEP */ diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index d47c47fc048..3c7046d7965 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -97,7 +97,7 @@ static void zorro_seq_stop(struct seq_file *m, void *v)  static int zorro_seq_show(struct seq_file *m, void *v)  { -	u_int slot = *(loff_t *)v; +	unsigned int slot = *(loff_t *)v;  	struct zorro_dev *z = &zorro_autocon[slot];  	seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id, @@ -129,7 +129,7 @@ static const struct file_operations zorro_devices_proc_fops = {  static struct proc_dir_entry *proc_bus_zorro_dir; -static int __init zorro_proc_attach_device(u_int slot) +static int __init zorro_proc_attach_device(unsigned int slot)  {  	struct proc_dir_entry *entry;  	char name[4]; @@ -146,7 +146,7 @@ static int __init zorro_proc_attach_device(u_int slot)  static int __init zorro_proc_init(void)  { -	u_int slot; +	unsigned int slot;  	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) {  		proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL); diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 53180a37cc9..7ee2b6e7178 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -137,10 +137,34 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv)  	return 0;  } +static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) +{ +#ifdef CONFIG_HOTPLUG +	struct zorro_dev *z; + +	if (!dev) +		return -ENODEV; + +	z = to_zorro_dev(dev); +	if (!z) +		return -ENODEV; + +	if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) || +	    add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) || +	    add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) || +	    add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id)) +		return -ENOMEM; + +	return 0; +#else /* !CONFIG_HOTPLUG */ +	return -ENODEV; +#endif /* !CONFIG_HOTPLUG */ +}  struct bus_type zorro_bus_type = {  	.name	= "zorro",  	.match	= zorro_bus_match, +	.uevent	= zorro_uevent,  	.probe	= zorro_device_probe,  	.remove	= zorro_device_remove,  }; diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 1d2a772ea14..eb924e0a64c 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -77,6 +77,16 @@ static struct bin_attribute zorro_config_attr = {  	.read = zorro_read_config,  }; +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, +			     char *buf) +{ +	struct zorro_dev *z = to_zorro_dev(dev); + +	return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id); +} + +static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL); +  int zorro_create_sysfs_dev_files(struct zorro_dev *z)  {  	struct device *dev = &z->dev; @@ -89,6 +99,7 @@ int zorro_create_sysfs_dev_files(struct zorro_dev *z)  	    (error = device_create_file(dev, &dev_attr_slotaddr)) ||  	    (error = device_create_file(dev, &dev_attr_slotsize)) ||  	    (error = device_create_file(dev, &dev_attr_resource)) || +	    (error = device_create_file(dev, &dev_attr_modalias)) ||  	    (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr)))  		return error; diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index d45fb34e2d2..6455f3a244c 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -15,6 +15,8 @@  #include <linux/zorro.h>  #include <linux/bitops.h>  #include <linux/string.h> +#include <linux/platform_device.h> +#include <linux/slab.h>  #include <asm/setup.h>  #include <asm/amigahw.h> @@ -26,24 +28,17 @@       *  Zorro Expansion Devices       */ -u_int zorro_num_autocon = 0; +unsigned int zorro_num_autocon;  struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];      /* -     *  Single Zorro bus +     *  Zorro bus       */ -struct zorro_bus zorro_bus = {\ -    .resources = { -	/* Zorro II regions (on Zorro II/III) */ -	{ .name = "Zorro II exp", .start = 0x00e80000, .end = 0x00efffff }, -	{ .name = "Zorro II mem", .start = 0x00200000, .end = 0x009fffff }, -	/* Zorro III regions (on Zorro III only) */ -	{ .name = "Zorro III exp", .start = 0xff000000, .end = 0xffffffff }, -	{ .name = "Zorro III cfg", .start = 0x40000000, .end = 0x7fffffff } -    }, -    .name = "Zorro bus" +struct zorro_bus { +	struct list_head devices;	/* list of devices on this bus */ +	struct device dev;  }; @@ -53,18 +48,19 @@ struct zorro_bus zorro_bus = {\  struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from)  { -    struct zorro_dev *z; +	struct zorro_dev *z; -    if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) -	return NULL; +	if (!zorro_num_autocon) +		return NULL; -    for (z = from ? from+1 : &zorro_autocon[0]; -	 z < zorro_autocon+zorro_num_autocon; -	 z++) -	if (id == ZORRO_WILDCARD || id == z->id) -	    return z; -    return NULL; +	for (z = from ? from+1 : &zorro_autocon[0]; +	     z < zorro_autocon+zorro_num_autocon; +	     z++) +		if (id == ZORRO_WILDCARD || id == z->id) +			return z; +	return NULL;  } +EXPORT_SYMBOL(zorro_find_device);      /* @@ -83,121 +79,138 @@ struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from)       */  DECLARE_BITMAP(zorro_unused_z2ram, 128); +EXPORT_SYMBOL(zorro_unused_z2ram);  static void __init mark_region(unsigned long start, unsigned long end,  			       int flag)  { -    if (flag) -	start += Z2RAM_CHUNKMASK; -    else -	end += Z2RAM_CHUNKMASK; -    start &= ~Z2RAM_CHUNKMASK; -    end &= ~Z2RAM_CHUNKMASK; - -    if (end <= Z2RAM_START || start >= Z2RAM_END) -	return; -    start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; -    end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; -    while (start < end) { -	u32 chunk = start>>Z2RAM_CHUNKSHIFT;  	if (flag) -	    set_bit(chunk, zorro_unused_z2ram); +		start += Z2RAM_CHUNKMASK;  	else -	    clear_bit(chunk, zorro_unused_z2ram); -	start += Z2RAM_CHUNKSIZE; -    } +		end += Z2RAM_CHUNKMASK; +	start &= ~Z2RAM_CHUNKMASK; +	end &= ~Z2RAM_CHUNKMASK; + +	if (end <= Z2RAM_START || start >= Z2RAM_END) +		return; +	start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; +	end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; +	while (start < end) { +		u32 chunk = start>>Z2RAM_CHUNKSHIFT; +		if (flag) +			set_bit(chunk, zorro_unused_z2ram); +		else +			clear_bit(chunk, zorro_unused_z2ram); +		start += Z2RAM_CHUNKSIZE; +	}  } -static struct resource __init *zorro_find_parent_resource(struct zorro_dev *z) +static struct resource __init *zorro_find_parent_resource( +	struct platform_device *bridge, struct zorro_dev *z)  { -    int i; +	int i; -    for (i = 0; i < zorro_bus.num_resources; i++) -	if (zorro_resource_start(z) >= zorro_bus.resources[i].start && -	    zorro_resource_end(z) <= zorro_bus.resources[i].end) -		return &zorro_bus.resources[i]; -    return &iomem_resource; +	for (i = 0; i < bridge->num_resources; i++) { +		struct resource *r = &bridge->resource[i]; +		if (zorro_resource_start(z) >= r->start && +		    zorro_resource_end(z) <= r->end) +			return r; +	} +	return &iomem_resource;  } -    /* -     *  Initialization -     */ -static int __init zorro_init(void) +static int __init amiga_zorro_probe(struct platform_device *pdev)  { -    struct zorro_dev *z; -    unsigned int i; -    int error; - -    if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) -	return 0; +	struct zorro_bus *bus; +	struct zorro_dev *z; +	struct resource *r; +	unsigned int i; +	int error; -    pr_info("Zorro: Probing AutoConfig expansion devices: %d device%s\n", -	   zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); +	/* Initialize the Zorro bus */ +	bus = kzalloc(sizeof(*bus), GFP_KERNEL); +	if (!bus) +		return -ENOMEM; -    /* Initialize the Zorro bus */ -    INIT_LIST_HEAD(&zorro_bus.devices); -    dev_set_name(&zorro_bus.dev, "zorro"); -    error = device_register(&zorro_bus.dev); -    if (error) { -	pr_err("Zorro: Error registering zorro_bus\n"); -	return error; -    } +	INIT_LIST_HEAD(&bus->devices); +	bus->dev.parent = &pdev->dev; +	dev_set_name(&bus->dev, "zorro"); +	error = device_register(&bus->dev); +	if (error) { +		pr_err("Zorro: Error registering zorro_bus\n"); +		kfree(bus); +		return error; +	} +	platform_set_drvdata(pdev, bus); -    /* Request the resources */ -    zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2; -    for (i = 0; i < zorro_bus.num_resources; i++) -	request_resource(&iomem_resource, &zorro_bus.resources[i]); +	/* Register all devices */ +	pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n", +		 zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); -    /* Register all devices */ -    for (i = 0; i < zorro_num_autocon; i++) { -	z = &zorro_autocon[i]; -	z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); -	if (z->id == ZORRO_PROD_GVP_EPC_BASE) { -	    /* GVP quirk */ -	    unsigned long magic = zorro_resource_start(z)+0x8000; -	    z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; -	} -	sprintf(z->name, "Zorro device %08x", z->id); -	zorro_name_device(z); -	z->resource.name = z->name; -	if (request_resource(zorro_find_parent_resource(z), &z->resource)) -	    pr_err("Zorro: Address space collision on device %s %pR\n", -		   z->name, &z->resource); -	dev_set_name(&z->dev, "%02x", i); -	z->dev.parent = &zorro_bus.dev; -	z->dev.bus = &zorro_bus_type; -	error = device_register(&z->dev); -	if (error) { -	    pr_err("Zorro: Error registering device %s\n", z->name); -	    continue; +	for (i = 0; i < zorro_num_autocon; i++) { +		z = &zorro_autocon[i]; +		z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); +		if (z->id == ZORRO_PROD_GVP_EPC_BASE) { +			/* GVP quirk */ +			unsigned long magic = zorro_resource_start(z)+0x8000; +			z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; +		} +		sprintf(z->name, "Zorro device %08x", z->id); +		zorro_name_device(z); +		z->resource.name = z->name; +		r = zorro_find_parent_resource(pdev, z); +		error = request_resource(r, &z->resource); +		if (error) +			dev_err(&bus->dev, +				"Address space collision on device %s %pR\n", +				z->name, &z->resource); +		dev_set_name(&z->dev, "%02x", i); +		z->dev.parent = &bus->dev; +		z->dev.bus = &zorro_bus_type; +		error = device_register(&z->dev); +		if (error) { +			dev_err(&bus->dev, "Error registering device %s\n", +				z->name); +			continue; +		} +		error = zorro_create_sysfs_dev_files(z); +		if (error) +			dev_err(&z->dev, "Error creating sysfs files\n");  	} -	error = zorro_create_sysfs_dev_files(z); -	if (error) -	    dev_err(&z->dev, "Error creating sysfs files\n"); -    } -    /* Mark all available Zorro II memory */ -    zorro_for_each_dev(z) { -	if (z->rom.er_Type & ERTF_MEMLIST) -	    mark_region(zorro_resource_start(z), zorro_resource_end(z)+1, 1); -    } +	/* Mark all available Zorro II memory */ +	zorro_for_each_dev(z) { +		if (z->rom.er_Type & ERTF_MEMLIST) +			mark_region(zorro_resource_start(z), +				    zorro_resource_end(z)+1, 1); +	} -    /* Unmark all used Zorro II memory */ -    for (i = 0; i < m68k_num_memory; i++) -	if (m68k_memory[i].addr < 16*1024*1024) -	    mark_region(m68k_memory[i].addr, -			m68k_memory[i].addr+m68k_memory[i].size, 0); +	/* Unmark all used Zorro II memory */ +	for (i = 0; i < m68k_num_memory; i++) +		if (m68k_memory[i].addr < 16*1024*1024) +			mark_region(m68k_memory[i].addr, +				    m68k_memory[i].addr+m68k_memory[i].size, +				    0); -    return 0; +	return 0;  } -subsys_initcall(zorro_init); +static struct platform_driver amiga_zorro_driver = { +	.driver   = { +		.name	= "amiga-zorro", +		.owner	= THIS_MODULE, +	}, +}; -EXPORT_SYMBOL(zorro_find_device); -EXPORT_SYMBOL(zorro_unused_z2ram); +static int __init amiga_zorro_init(void) +{ +	return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe); +} + +module_init(amiga_zorro_init);  MODULE_LICENSE("GPL");  |